1. 声明式事务概念
编程式事务指通过编写代码的方式直接控制事务的提交和回滚。
1 |
|
- 细节没有被屏蔽:具体操作过程中,所有细节都需要程序员自己来完成,比较繁琐。
- 代码复用性不高:如果没有有效抽取出来,每次实现功能都需要自己编写代码,代码就没有得到复用。
声明式事务是指使用注解或 XML 配置的方式来控制事务的提交和回滚。
Spring声明式事务对应依赖
- spring-tx: 包含声明式事务实现的基本规范(事务管理器规范接口和事务增强等等)
- spring-jdbc: 包含DataSource方式事务管理器实现类DataSourceTransactionManager
- spring-orm: 包含其他持久层框架的事务管理器实现类例如:Hibernate/Jpa等
Spring声明式事务对应事务管理器接口
org.springframework.jdbc.datasource.DataSourceTransactionManager
可用于整合 JDBC
方式、JdbcTemplate
方式、Mybatis
方式的事务实现
DataSourceTransactionManager
类中的主要方法:
doBegin()
:开启事务doSuspend()
:挂起事务doResume()
:恢复挂起的事务doCommit()
:提交事务doRollback()
:回滚事务
2. 基于注解的声明式事务
2.1 使用方法
配置类上添加 @EnableTransactionManagement
, 实例化 TransactionManager
组件
1 |
|
使用声明事务注解 @Transactional
1 |
|
将
@Transactional
标记在类上会作用在类中所有方法,设置的事务属性也会延续影响到方法执行时的事务属性对一个方法来说,离它最近的
@Transactional
注解中的事务属性设置生效
2.2 事务属性
只读
@Transactional(readOnly = true)
超时时间
@Transactional(timeout = 3)
- 单位为秒,默认为 -1,永不超时
- 超时会执行回滚
事务异常
@Transactional(rollbackFor = Exception.class, noRollbackFor = FileNotFoundException.class)
- 默认只针对运行时异常回滚,编译时异常不回滚
rollbackFor
: 指定哪些异常类才会回滚,默认是RuntimeException and Error
异常方可回滚noRollbackFor
: 指定哪些异常不会回滚, 默认没有指定, 如果指定, 应该在rollbackFor
的范围内
事务隔离级别
@Transactional(isolation = Isolation.REPEATABLE_READ)
- isolation: 设置事务的隔离级别, mysql默认是repeatable read
数据库事务的隔离级别是指在多个事务并发执行时,数据库系统为了保证数据一致性所遵循的规定。常见的隔离级别包括:
- 读未提交(Read Uncommitted):事务可以读取未被提交的数据,容易产生脏读、不可重复读和幻读等问题。实现简单但不太安全,一般不用。
- 读已提交(Read Committed):事务只能读取已经提交的数据,可以避免脏读问题,但可能引发不可重复读和幻读。
- 可重复读(Repeatable Read):在一个事务中,相同的查询将返回相同的结果集,不管其他事务对数据做了什么修改。可以避免脏读和不可重复读,但仍有幻读的问题。
- 串行化(Serializable):最高的隔离级别,完全禁止了并发,只允许一个事务执行完毕之后才能执行另一个事务。可以避免以上所有问题,但效率较低,不适用于高并发场景。
事务传播行为
1 |
|
@Transactional
注解通过 propagation
属性设置事务的传播行为
- 它的默认值是
Propagation propagation() default Propagation.REQUIRED;
- 可选值由
org.springframework.transaction.annotation.Propagation
枚举类提供Propagation.REQUIRED
:如果当前存在事务,则加入当前事务,否则创建一个新事务。
Propagation.REQUIRES_NEW
:创建一个新事务,并在新事务中执行。如果当前存在事务,则挂起当前事务,即使新事务抛出异常,也不会影响当前事务。Propagation.NESTED
:如果当前存在事务,则在该事务中嵌套一个新事务,如果没有事务,则与Propagation.REQUIRED一样。Propagation.SUPPORTS
:如果当前存在事务,则加入该事务,否则以非事务方式执行。Propagation.NOT_SUPPORTED
:以非事务方式执行,如果当前存在事务,挂起该事务。Propagation.MANDATORY
:必须在一个已有的事务中执行,否则抛出异常。Propagation.NEVER
:必须在没有事务的情况下执行,否则抛出异常。
注意
在同一个类中,对于
@Transactional
注解的方法调用,事务传播行为不会生效。这是因为 Spring 框架中使用代理模式实现了事务机制,在同一个类中的方法调用并不经过代理,而是通过对象的方法调用,因此@Transactional
注解的设置不会被代理捕获,也就不会产生任何事务传播行为的效果。