Hibernate审计日志时业务数据无法同步问题解决

Hibernate审计日志时业务数据无法同步问题解决

1.      问题描述

整个项目采用SpringMVC3.0+Hibernate3.6作为基础框架,项目刚开始没有加入日志审计功能,业务添加、删除、修改、查询都正常,没有任何问题。后期增加了操作历史的审计日志功能后,添加、修改、删除数据时,页面的数据时十有八九不能刷新。说明一下,日志审计功能使用Hibernate的监听器来实现的。

2.      问题分析

业务很简单,添加、修该、删除功能都用Ajax异步提交,调用成功后,根据Action方法的返回值,来刷新列表数据。调试跟踪代码也没找到问题,数据都能及同步数据库,也没有丢过数据。但有一点是调试时,页面数据总能刷出新增的数据。尝试在Action返回页面之前然线程休眠1秒钟,页面就可以刷出本次添加的数据,问题很诡异啊。果断画出调用时序图仔细分析一下:


从表面看,很像是数据脏都问题,刷新数据时,读取到了脏数据。事物也没发现问题,但为什么读到脏数据呢,不解啊。看以下审计代码,感觉有段代码很奇怪,伪代码如下

 

public class HistoryListener implementsPostInsertEventListener,  PostUpdateEventListener,PostDeleteEventListener {

 

void onPostInsert (PostInsertEvent event){

         Loglog = new Log();

         Log.setAction(ACTION.INSERT);

         Log.setXXXX(event.getState().getXX());

         ……

         saveOperation(log,event.getSession());

}

…..

saveOperation(Log log,Session session){

       Transacton tx = session.beginTransaction();

       try{

session.save(log);

session.commit()

}catch{

         If(tx!=null){

         tx.rollback();

}

}

}

}

问题找到了,从画出的时序图可以看出,Hibernate监听器其实是异步实现的,图中的动作3成功返回和动作4saveActionLog()是异步执行的,在监听器代码中event.getSession()和Service中用的是同一session,这就延长session的生命周期,成功返回后页面刷新调用list这个时间间隔非常小,上一个session没有结束数据可能还没有flush(),所以list()返回的数据可能是没有同步之前的数据。

3.      解决办法

缩短回话的生命周期

public class HistoryListener implementsPostInsertEventListener, PostUpdateEventListener, PostDeleteEventListener {

 

voidonPostInsert (PostInsertEvent event){

Log log = new Log();

Log.setAction(ACTION.INSERT);

Log.setXXXX(event.getState().getXX());

……

//saveOperation(log,event.getSession());  不能使用这个session保存日志

saveOperation(log);

}

…..

saveOperation(finalLog log){

//使用新的线程会开启一个新的session

new Thread(new Runnable(){

           void run(){

                    LogService logService =ServiceFaced.getService(LogService.class);

                    logservice.save(log);

}

}).start()

}catch{

If(tx!=null){

tx.rollback();

}

}

}

}

4.      问题总结

业务系统中的session尽可能只用来进行业务操作,生命周期应该和页面请求保持一致(页面发起request请求时,  session生命周期开时开始,页面response时,生命周期结束)。如果session的生命周期是绑定在线程(Thread)上,做审计日志,尽可能使用一个新的线程来记录日志,这也本例子的解决办法。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值