(1)事务方法所在的类没有加载到容器中(未被Spring管理的Bean)
如果一个被注解的类不是由Spring容器来创建的,比如手动new对象,那么该类的事务注解则不会生效。可以通过将该类交给Spring容器来解决此问题。
(2)事务方法不是public类型
@Transactional
注解只对public方法有效,如果使用它来注解非public方法,则不会开启事务。
(3)同一类中,一个没有添加事务的方法调用另外以一个添加事务的方法,事务不生效
如果一个使用@Transactional
注解标记的方法A中调用了另外一个没被事务管理的方法B并在B中发生异常,就会导致整个事务失效,并不会出现回滚。原因在于,Spring事务实现是通过生成代理对象并对应用程序进行拦截来实现的,而内部调用的方法不通过代理对象的方式调用,因此不会触发事务机制。
(4)spring事务默认只回滚运行时异常,可以用rollbackfor属性设置
在Spring中,当方法被声明为事务方法时,在抛出运行时异常(如NullPointerException
、IndexOutOfBoundException
等)的情况下,Spring会对整个事务进行回滚操作;而对于非运行时异常(如IOException
、SQLException
等),即使发生异常,Spring也不会对事务进行回滚。可以理解为,Spring默认只对未处理的RuntimeException及其子类进行回滚,对于其他异常则不会回滚。这样做是为了防止一些预期的业务异常导致整个事务被回滚。
可以通过配置rollbackFor
属性或noRollbackFor
属性来改变这种默认的行为。rollbackFor
属性用于指定要回滚的异常类型,noRollbackFor
属性用于指定不回滚的异常类型。例如:
@Transactional(rollbackFor = ArithmeticException.class, noRollbackFor = IOException.class)
public void doSomething() {// ...
}
(5)业务自己捕获了异常,事务会认为程序正常秩序
当一个事务方法抛出异常时,如果异常被捕捉住(try/catch块中),那么Spring就无法获取到异常信息,并且整个事务也就无法回滚。解决方法是在catch块中重新抛出异常,或者使用Spring提供的@Transactional(rollbackFor = Exception.class)
注解。