@Transactiona注解失效原因

用在非public方法

@Transactional是基于动态代理的,Spring的代理工厂在启动时会扫描所有的类和方法,并检查方法的修饰符是否为public,非public时不会获取@Transactional的属性信息,这时不会生成动态代理对象。

同一个类中,非@Transactional方法调用@Transactional方法

其实是AOP失效原因,类内部方法的调用是通过this调用的,不会使用动态代理对象,事务不会回滚。

异常被"吃了"

Spring是根据抛出的异常来回滚的,如果异常被捕获了没有抛出的话,事务就不会回滚。

(类本身) 未被spring管理

只有被spring扫描到并管理的bean,才支持AOP。

多线程调用

spring的事务是通过数据库连接来实现的。当前线程中保存了一个map,key是数据源,value是数据库连接。只有拥有同一个数据库连接才能同时提交和回滚。如果在不同的线程,拿到的数据库连接肯定是不一样的,所以是不同的事务。

事务管理器设置的不对

TransactionManager配置的DataSource与执行mapper对应Mybatis绑定的DataSource不匹配。

Sping开启事务,将链接与线程绑定,放入TransactionSynchronizationManager,key为数据源,value为链接的包装
TransactionSynchronizationManager.bindResource(this.getDataSource(), txObject.getConnectionHolder());
Mybatis通过配置的数据源获取链接的包装
ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);

rollbackFor属性设置不对

Spring默认抛出RuntimeException时才会回滚事务,要想其他类型异常也回滚则需要设置rollbackFor属性的值。

数据库引擎不支持事务

比如使用MyISAM。

posted on 2023-03-29 15:09  zhengbiyu  阅读(86)  评论(0)    收藏  举报