spring事务失效场景

110 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第29天,点击查看活动详情

一、什么是事务

事务是逻辑上的一组操作,要么都执行,要么都不执行

二、事务功能的总体接口设计

主要看下三大接口

  • PlatformTransactionManager : 事务管理器,Spring 事务策略的核心。

  • TransactionDefinition : 事务定义信息事,如超时时间、隔离级别、传播属性、超时、只读等

  • TransactionStatus : 事务的一些状态信息,如是否是一个新的事务、是否已被标记为回滚

PlatformTransactionManager 会根据 TransactionDefinition 的定义比如事务超时时间、隔离级别、传播行为等来进行事务管理 ,而 TransactionStatus 接口则提供了一些方法来获取事务相应的状态比如是否新事务、是否可以回滚等等。

三、Spring支持两种方式的事务管理

spring提供的事务机制主要包括编程式事务声明式事务

编程式事务是手动在代码里面进行事务的提交回滚操作,代码侵入性比较强

声明式事务是基于AOP切面的主要采用注解和xml配置的方式。

四、@Transactional

该注解可以作用于接口方法上。

  • 作用在类上,表示该类下面所有的public接口都使用该事务机制;

  • 作用在方法上,会覆盖类上的事务配置信息;

  • 作用在接口上并且配置了spring AOP使用cglib代理将会导致@Transactional注解失效。

@Transactional 配置事务

  • 1、spring 事务默认回滚的是运行时异常(RuntimeException)和错误(Error)非检测异常,例如SQLException 不会回滚。加上rollbackFor = Exception.class 可解决。

  • 2、在service中使用了try catch 捕获了异常,事务不会回滚,因为try catch 异常之后就相当于没有异常,建议异常在controller中统一处理。

五、注解的失效场景

@Transactional失效场景:

  • 1、@Transactional作用在非public公共方法上;

  • 2、@Transactional 注解属性 propagation 设置错误;

    TransactionDefinition.PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。

    TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起。

    TransactionDefinition.PROPAGATION_NEVER:以非事务方式运行,如果当前存在事务,则抛出异常。

    如果设置以上三种,可能导致事务失效。

  • 3、@Transactional的rollbackfor设置错误

    Spring默认抛出了未检查unchecked异常(继承自 RuntimeException 的异常)或者 Error 才回滚事务; 期望 Spring 能够回滚事务,就需要指定 rollbackFor 属性rollbackFor=MyWxception.class

  • 4、同一个类中调用方法,导致@Transactional失效;

    只有当事务方法被当前类以外的代码调用时,才会由Spring生成的代理对象来管理;

5、异常被catch吃了导致@Transactional失效;

6、数据引擎不支持事务;

**事务能否生效与数据库引擎是否支持事务是关键**。
比如常用的 MySQL 数据库默认使用支持事务的 innodb引擎。
如果把数据库引擎变为 myisam,那么程序也就不再支持事务了!