需要实现一个日志审计的功能,从JE上看到了一个帖子,列举了六种方案(帖子的名字叫《JPA + Hibernate 3 CRUD操作历史审计日志的解决方案(附源码)》),这次刚好用的是hibernate做持久化,就选择了event-listener的方式。但是需要进行日志记录的数据,都是没有在前端提供物理删除逻辑的,用的全是置状态的逻辑删除。
示例伪代码如下:
String hql ="update test.Demo set flag := flag where id := id ";
Query query = getSession().createQuery(hql)
.setParameter("flag",DELETE) //DELETE 表示删除状态
.setParameter("id","1001");
int rows = query.executeUpdate();
然后问题出现了:hibernate无法将逻辑删除的日志记录下来。大概看了一下相关的实现代码,QueryImpl.java应该是调用的SessionImpl.java,而SessionImpl.java的该方法实现是这样的:
public int executeUpdate(String query, QueryParameters queryParameters) throws HibernateException {
errorIfClosed();
checkTransactionSynchStatus();
queryParameters.validateParameters();
HQLQueryPlan plan = getHQLQueryPlan( query, false );
autoFlushIfRequired( plan.getQuerySpaces() );
boolean success = false;
int result = 0;
try {
result = plan.performExecuteUpdate( queryParameters, this );
success = true;
}
finally {
afterOperation(success);
}
return result;
}
又看了一些save/update的一些方法,都和Listener相关,那Event-Listener应该是做在SessionImpl类中的。
再大胆猜测一下,和Query相关的应该是HQLQueryPlan.java,Query都没有事件监听器(注:我没有验证是不是这样),想想也合理,从Hibernate的逻辑上讲无法实现对不加任何假设条件的Query的监听。
但是我需要的是一个完整的实现日志审计的方案,总不能对Query的单个对象的修改,物理删除,逻辑删除(修改)就不做日志吧!业务级需要的特殊需求,肯定应该业务级自己实现的,但是在网上没有发现相关的实现思路和示例。没有成熟的借鉴就只好自己先搞一个思路:
1 定义自己的事件和监听;
2 抽取Query方式的单个对象修改,单个对象逻辑删除,单个对象物理删除的方法成通用方法,放在一个基础类中;
3 在抽取的方法上中,添加上监听器方法调用,
4 实现自己的监听,并把实现的类实例,注入到存在通用方法的基础类;
5 实现单对象修改、单对象逻辑删除或物理删除时需要调用基础类中的对应方法;
现在的日志审计应该是基本一致了。一半是用Hibernate本身的机制实现的,一半是借鉴其思想根据具体业务逻辑自定义监听器和事件实现的。构成相对一个完整的业务日志审计功能。
先试试吧,希望能发现更好一点儿的方式......