项目中想记录操作日志,也就是针对一些关键的信息的操作,进行日志的记录。首先考虑到的就是在数据变更的时候能得到通知,然后去做变更信息的记录操作。项目中使用的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了。
我的实现方法是这样的:编写监听注册类:
- 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());
- }
- }
- }
在系统启动类中添加方法:
- public static void startHibernateListeners()
- {
- if(applicationContext != null)
- {
- IListeners listeners = (IListeners)applicationContext.getBean("com.xk.commons.hibernate.listener.IListeners");
- listeners.registerListeners();
- }
- }
这个方法中用到了Spring容器applicationContext,也就是说,调用这个方法的时机必须在spring的环境准备好以后,如下:
- String springConfigPath = getSpringConfig();
- applicationContext = new FileSystemXmlApplicationContext(springConfigPath);
- logger.info("load spring config file : {}", springConfigPath);
- startHibernateListeners();
上面的代码片段很好理解。下面是我们的监听的相应处理类:
- 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方法中,我们进行相应的变更处理就可以了。