spring 事务管理
事务特性
确保数据的完整性和一致性
- 原子性(Atomicity):事务是一个原子操作,由一系列动作组成.事务的原子性确保动作要么全部完成,要么完全不起作用.
- 一致性(Consistency):一旦事务完成(不管成功还是失败),系统必须确保它所建模的业务处于一致的状态,而不会是部分完成部分失败.在现实中的数据不应该被破坏.
- 隔离性(Isolation):可能有许多事务会同时处理相同的数据,因此每个事务都应该与其他事务隔离开来,防止数据损坏.
- 持久性(Durability):一旦事务完成,无论发生什么系统错误,它的结果都不应该受到影响,这样就能从任何系统崩溃中恢复过来.通常情况下,事务的结果被写到持久化存储器中.
Spring 事务的隔离级别
在TransactionDefinition
接口中定义了五个不同的事务隔离级别
- ISOLATION_DEFAULT
这是一个 PlatfromTransactionManager 默认的隔离级别,使用数据库默认的事务隔离级别.另外四个与 JDBC 的隔离级别相对应 - ISOLATION_READ_UNCOMMITTED
这是事务最低的隔离级别,它允许另外一个事务可以看到这个事务未提交的数据.这种隔离级别会产生脏读,不可重复读和幻像读 - ISOLATION_READ_COMMITTED
保证一个事务修改的数据提交后才能被另外一个事务读取.另外一个事务不能读取该事务未提交的数据.这种事务隔离级别可以避免脏读出现,但是可能会出现不可重复读和幻像读 - ISOLATION_REPEATABLE_READ
这种事务隔离级别可以防止脏读/不可重复读.但是可能出现幻像读.它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免不可重复读 - ISOLATION_SERIALIZABLE
这是花费最高代价但是最可靠的事务隔离级别,事务被处理为顺序执行.除了防止脏读,不可重复读外,还避免了幻像读
Spring 事务的传播属性
在TransactionDefinition
接口中定义了七个事务传播行为
- PROPAGATION_REQUIRED
如果存在一个事务,则支持当前事务.如果没有事务则开启一个新的事务. - PROPAGATION_SUPPORTS
如果存在一个事务,支持当前事务.如果没有事务,则非事务的执行.但是对于事务同步的事务管理器,PROPAGATION_SUPPORTS
与不使用事务有少许不同. - PROPAGATION_MANDATORY
如果已经存在一个事务,支持当前事务.如果没有一个活动的事务,则抛出异常. - PROPAGATION_REQUIRES_NEW
总是开启一个新的事务.如果一个事务已经存在,则将这个存在的事务挂起. - PROPAGATION_NOT_SUPPORTED
总是非事务地执行,并挂起任何存在的事务. - PROPAGATION_NEVER
总是非事务地执行,如果存在一个活动事务,则抛出异常 - PROPAGATION_NESTED
如果一个活动的事务存在,则运行在一个嵌套的事务中.如果没有活动事务, 则按TransactionDefinition.PROPAGATION_REQUIRED
属性执行
@Transactiona 注解
@Transactional
默认情况下会对运行期例外(RunTimeException)进行事务回滚.这个例外是 unchecked
-
让 checked 例外也回滚:在方法前加上
@Transactional(rollbackFor=Exception.class)
-
让 unchecked 例外不回滚:在方法前加上
@Transactional(notRollbackFor=RunTimeException.class)
-
不需要事务管理的(只查询的)方法:
@Transactional(propagation=Propagation.NOT_SUPPORTED)
-
还可以加上:
@Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true)
,这样就做成一个只读事务可以提高效率
注意 如下代码片段 d1 调用 d2 方法,其中 d1 中 userDao.insert(userPO)
执行成功 d2 中 userDao.insert2(userPO)
执行失败
- 情况一:
d2 没有@Transactional
注解 (标记 3)
d1 catch 没有 throw 异常 (标记 2)
这时 userDao.insert 不会 rollback
控制台没有异常信息 - 情况二:
d2 有@Transactional
注解 (标记 3)
d1 catch 没有 throw 异常 (标记 2)
这时 userDao.insert 会 rollback
控制台异常信息:org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only
原因:
情况二 中 spring 切面在 在执行 d2 后 优先 catch 住了异常 并进行 throw 所以整个方法回滚,
而在情况一 中 d2 异常但是 没有抛出异常 所以不会触发 rollback
1 |
|