持续创作,加速成长!这是我参与「掘金日新计划 · 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,那么程序也就不再支持事务了!