1.抛出编译异常 ,事务只能捕捉运行时异常和error

解决方案: 配置rollbackFor eg. 配置@Transactional(rollbackFor = Exception.class)

2.选用了错误的事务传播机制 例如 @Transactional(propagation = Propagation.NOT_SUPPORTED)

有事务挂起 ,无事务就以非事务的方式执行。

3.业务自身捕捉到异常[try catch finally] 而不是通过抛出异常交给类处理

因为spring事务只有捕捉到了业务抛出去的异常,才能进行后续的处理,如果业务自己捕获了异常,则事务无法感知。

解决方案:将异常原样抛出 尽量不要在业务方法中使用try...catch来捕获你的异常,防止影响了事务。

4.跨了线程的事务

原因:如果事务方法内,开启了新线程去执行其他事务方法也是不受当前事务方法控制的。因为不同线程拥有的threadlocal 不一样。

所以:当你需要明确开启新线程,请分开处理。

5.@Transactional放在非public方法上。

原因:AbstractFallbackTransactionAttributeSource类调用computeTransactionAttribute()时,过滤了非public方法上事务配置信息(相当于没有配置无事务运行机制)。

 

什么是传播事务:事务是数据库的一种特性,而Spring只是封装这个特性,方便我们使用,最终的执行实际上都是在数据库中完成,但是对于数据库来说,事务是单一的,没有那么多业务场景,但是对于Spring来说,会面对各种各样的业务需求,所以需要有一套可以从代码层面去控制事务来满足我们的场景需求,所以也就有了传播机制。

 

事务传播机制是通过@Transactional实现得,使用了ThreadLocal实现得 ,保证事务方法拿到的数据库连接是同一个呢?答案就是使用了ThreadLocal。

我们平时开发不可能所有数据库操作都在一个方法里,之前说过保证事务的很重要的一点是始终用一个连接connection,所以被调用方法里有操作数据库时也需要用这个主方法中创建的connection。

因为不太可能把所有调用方法都加一个connection入参,所以比较优雅的方法是把连接放在ThreadLocal里,其他方法要操作数据库时就从ThreadLocal里get即可。

 

 

 posted on 2022-07-23 13:16  小北呦  阅读(506)  评论(0)    收藏  举报