(郁闷系列)让我郁闷的Spring事务回滚及对其它AOP操作的影响
问题很简单,使用Spring声明式事务管理,框架采用spring+hibernate,编程上采用Srping封装的Hibernate模板,架构上分为三层表示层+service+dao
首先,我采用Aop来处理Service层抛出的异常,例如MyExceptionAdvice,当然了,处理异常的类需要实现ThrowAdvice接口,但是这个时候问题就来了,假设这个时候从service层抛出Runtime异常,那么此时Spring的事务会回滚,,我MyExceptionAdvice里面规定的方法也能接收到这个异常,另外,我还想在MyExceptionAdvice里对数据库进行一步操作,那么这个时候这个操作就不会生效。最现实的例子就是,当有异常发生时,我需要向数据库插入一条日志。但是基于上述我所说的,这条日志不能成功的插入到数据库。
原因分析及尝试的解决办法:
原因应该是,由于抛出runtime异常,所以事务回滚造成的,这时,我们就会想,能不能重新启动一个事务,按照Spring事务定义的策略,可以在事务定义的时候将写日志的方法定义为REQUIRES_NEW,但是实践下来,好像也不管用,那位用过这个的给说说?
注意上面的ExampleService,LogService及他们的实现,以及处理异常的拦截类都配置到Spring配置文件了。类之间的调用以及拦截类的拦截都没有问题,唯一的问题就是记录日志的时候没有事务。public class ExampleServiceImpl implements ExampleService{ public void saveExample(.....){ try { dao.save(); }catch(Exception e) //or RuntimeException { writeLog(); throw new RuntimeException(); } } } public class LogServiceImpl implements LogService{ public void writeLog(){ try { logDao.log(); }catch(Exception e) { loggger.log("log exception ",e); throw new RuntimeException(); } } } 8 楼 jamesby 2007-04-07 首先去掉ExceptionHandleAdvice 是为了测试REQUIRES_NEW是否真的起作用,如果去掉起作用说明与异常拦截器有关。
如果还是不起作用说明是配置或者代码的问题。 9 楼 lizwjiang 2007-04-10 过了一个周末,帖子居然在前面两页找不到了,javaeye的发帖量不小啊,废话少说,继续讨论:
首先多谢楼上几位的讨论,其实我在发第一个帖子的时候已经做过类似的测试就是:
如果异常是checkedException的话,这时Exception advice拦截到,并做日志记录,那么事务会继续做提交,日志能正常记录。
后面加了一个测试:如果不抛异常的话,那么使用REQUIRES_NEW对事务没有影响,CRUD都没问题
如果那位机器方便的话,可以试试,一个很奇怪的现象。 10 楼 janh 2007-04-14 使用REQUIRES_NEW可以实现新建一个事务,记录日志并提交啊,最好是把异常处理和事务管理的顺序处理好,
见 http://www.iteye.com/topic/71030,但是异常处理类并不需要实现MyExceptionAdvice啊,不知道你用的方法是不是和我一样。 11 楼 lizwjiang 2007-04-16 janh 写道使用REQUIRES_NEW可以实现新建一个事务,记录日志并提交啊,最好是把异常处理和事务管理的顺序处理好,
见 http://www.iteye.com/topic/71030,但是异常处理类并不需要实现MyExceptionAdvice啊,不知道你用的方法是不是和我一样。
thanks a lot,janh,It's great.
我上面写的情况和你的不太一样,但是问题已经解决了,你上面连接的帖子我已经看过并测试过,very good,对我后面问题的解决帮助很大。具体问题的解决,我再blog里会另写一篇文章来描述。