目录

线上问题:

事务注意事项

总结:

线上问题:

仔细分析了抛出的异常,发现异常为SocketTimeoutException,查阅事务回滚时需要的异常,发现

java中事务嵌套事务_回滚

默认事务只对error和runtimeException异常会进行回滚,其他异常不会回滚

加上@Transactional(rollbackFor=MyException.class)后事务会捕捉到此类异常,

在Spring里,同样只会rollback unchecked exception(RuntimeExcption及子类),而checked exception(Exception及子类)是不会rollback的,除非你特别声明。

 @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW,rollbackFor = {MyException1.class,MyException2.class})    

因此所有在service层方法中用throws定义的Exception,都必须在事务定义中进行rollback设定。(请勿善忘)

所有在service层方法中被catch处理了的异常,又希望容器辅助rollback的话,必须重抛一个预定义的RuntimeException的子类。(请勿回望)

事务注意事项

要根据实际的需求来决定是否要使用事务,最好是在编码之前就考虑好,不然到以后就难以维护;

如果使用了事务,请务必进行事务测试,因为很多情况下以为事务是生效的,但是实际上可能未生效!

1:事务@Transactional的使用要放再类的公共(public)方法中,需要注意的是在 protected、private 方法上使用 @Transactional 注解,它也不会报错(IDEA会有提示),但事务无效。

2:事务@Transactional是不会对该方法里面的子方法生效!也就是你在公共方法A声明的事务@Transactional,但是在A方法中有个子方法B和C,其中方法B进行了数据操作,但是该异常被B自己处理了,这样的话事务是不会生效的!反之B方法声明的事务@Transactional,但是公共方法A却未声明事务的话,也是不会生效的!如果想事务生效,需要将子方法的事务控制交给调用的方法,在子方法中使用rollbackFor注解指定需要回滚的异常或者将异常抛出交给调用的方法处理。一句话就是在使用事务的时候子方法最好将异常抛出!

3:事务@Transactional由spring控制的时候,它会在抛出异常的时候进行回滚。如果自己使用catch捕获了处理了,是不生效的,如果想生效可以进行手动回滚或者在catch里面将异常抛出,比如throw new RuntimeException();。

总结:

  1. Spring事务管理是根据异常来进行回滚操作;
  2. Spring与Mybatis整合时,虽然在Service方法中并没有check异常,但是如果数据库有异常发生,默认会进行事务回滚。
  3. Spring 如果不添加rollbackFor等属性,Spring碰到Unchecked Exceptions都会回滚,不仅是RuntimeException,也包括Error。
  4. 如果在事务方法中捕获异常并进行处理,一定要继续抛出异常并在Spring事务管理中进行rollbak-for配置。