項目中想記錄操做日誌,也就是針對一些關鍵的信息的操做,進行日誌的記錄。首先考慮到的就是在數據變動的時候能獲得通知,而後去作變動信息的記錄操做。項目中使用的hibernate4,因而上網查了一下,發如今hibernate支持interceptor和listener,可是interceptor是在操做前攔截。這個顯然並不合適。操做前攔截的話,若是已經記錄完了操做日誌,結果數據操做並沒成功怎麼辦?是否能回滾?總之感受不太合適。listener是滿合適的。晚上不少的介紹,可是都是基於hibernate3之前版本的,都是說在spring配置sessionFactory的時候,加個eventListeners的屬性就能夠了。而hibernate4中已經徹底變了,spring對hibernate4也不支持eventListener屬性了。網上搜來搜去,國人針對hibernate4這個改變的解決辦法幾乎沒有。因而查看官方文檔。發如今hibernate4中,listener的註冊是經過Integrator來完成的,而Integrator是經過服務來發布的。須要在配置META-INF/services/org.hibernate.integrator.spi.Integrator文件中。可是這種方式,在listener中就沒法使用spring的依賴注入,由於他們根本不在spring容器內。還好,sessionFactory中是能夠得到到註冊對象的。那麼咱們只要再應用啓動的時候,當spring環境準備好之後,在完成hibernate監聽的註冊就ok了。spring
個人實現方法是這樣的:編寫監聽註冊類:session
- public class ListenersImpl implements IListeners
- {
- private List<AlterationListener> listeners;
- private SessionFactory sessionFactory;
- private static final Logger logger = LoggerFactory.getLogger(ListenersImpl.class);
- public void setSessionFactory(SessionFactory sessionFactory)
- {
- this.sessionFactory = sessionFactory;
- }
- public void setListeners(List<AlterationListener> listeners)
- {
- this.listeners = listeners;
- }
- public void registerListeners()
- {
- EventListenerRegistry registry = ((SessionFactoryImpl)sessionFactory).getServiceRegistry().getService(EventListenerRegistry.class);
- for(AlterationListener listener : listeners)
- {
- registry.getEventListenerGroup(EventType.POST_INSERT).appendListener(listener);
- registry.getEventListenerGroup(EventType.POST_UPDATE).appendListener(listener);
- registry.getEventListenerGroup(EventType.POST_DELETE).appendListener(listener);
- logger.info("register hibernate listener : {} operation : [insert, update, delete]", listener.getClass().getName());
- }
- }
- }
在系統啓動類中添加方法:app
- public static void startHibernateListeners()
- {
- if(applicationContext != null)
- {
- IListeners listeners = (IListeners)applicationContext.getBean("com.xk.commons.hibernate.listener.IListeners");
- listeners.registerListeners();
- }
- }
這個方法中用到了Spring容器applicationContext,也就是說,調用這個方法的時機必須在spring的環境準備好之後,以下:ide
- String springConfigPath = getSpringConfig();
- applicationContext = new FileSystemXmlApplicationContext(springConfigPath);
- logger.info("load spring config file : {}", springConfigPath);
- startHibernateListeners();
上面的代碼片斷很好理解。下面是咱們的監聽的相應處理類:this
- public class AlterationListener implements PostUpdateEventListener, PostInsertEventListener, PostDeleteEventListener
- {
- /**
- *
- */
- private static final long serialVersionUID = 8775069565992961824L;
- private EventCenter eventCenter;
- public void setEventCenter(EventCenter eventCenter)
- {
- this.eventCenter = eventCenter;
- }
- private String eventType;
- public void setEventType(String eventType)
- {
- this.eventType = eventType;
- }
- public void onPostDelete(PostDeleteEvent event)
- {
- // TODO Auto-generated method stub
- }
- public void onPostInsert(PostInsertEvent event)
- {
- // TODO Auto-generated method stub
- }
- public void onPostUpdate(PostUpdateEvent event)
- {
- // TODO Auto-generated method stub
- Event evt = new Event(this, event, eventType);
- eventCenter.addEvent(evt);
- }
- }
能夠看到在onPostUpdate方法中,咱們進行相應的變動處理就能夠了。spa