1.事务的传播行为
- Require:支持当前事务,如果没有事务,就建一个新的,这是最常见的;
- Supports:支持当前事务,如果当前没有事务,就以非事务方式执行;
- Mandatory:支持当前事务,如果当前没有事务,就抛出异常;
- RequiresNew:新建事务,如果当前存在事务,把当前事务挂起;
- NotSupported:以非事务方式执行操作,如果当前存在事务,就把事务挂起;
- Never:以非事务方式执行,如果当前存在事务,则抛出异常。
- Nested:新建事务,如果当前存在事务,把当前事务挂起。与RequireNew的区别是与父事务相关,且有一个savepoint。
其中,Require、Supports、NotSupported、Never两个看文字也就能了解,就不多说了。而Mandatory是要求所有的操作必须在一个事务里,较Require来说,对事务要求的更加严格。
RequireNew:当一个Require方法A调用RequireNew方法B时,B方法会新new一个事务,并且这个事务和A事务没有关系,也就是说B方法出现异常,不会导致A的回滚,同理当B已提交,A再出现异常,B也不会回滚。
Nested:这个和RequireNew的区别是B方法的事务和A方法的事务是相关的。只有在A事务提交的时候,B事务都会提交。也就是说当A发生异常时,A、B事务都回滚,而当B出现异常时,B回滚,而A回滚到savepoint
RequireNew:当一个Require方法A调用RequireNew方法B时,B方法会新new一个事务,并且这个事务和A事务没有关系,也就是说B方法出现异常,不会导致A的回滚,同理当B已提交,A再出现异常,B也不会回滚。
Nested:这个和RequireNew的区别是B方法的事务和A方法的事务是相关的。只有在A事务提交的时候,B事务都会提交。也就是说当A发生异常时,A、B事务都回滚,而当B出现异常时,B回滚,而A回滚到savepoint
2.事务的隔离级别
- Serializable:最严格的级别,事务串行执行,资源消耗最大;
- Repeatable Read:保证了一个事务不会修改已经由另一个事务读取但未提交(回滚)的数据。
- Read Committed:大多数主流数据库的默认事务等级,保证了一个事务不会读到另一个并行事务已经修改但未提交的数据。适用于大多数系统。
- Read Uncommitted:保证了读取过程中不会读取到非法数据。
3.@Transactional
注解
@Transactional
注解是用来指定接口、类或方法必须拥有事务语义的元数据。 如:“当一个方法开始调用时就开启一个新的只读事务,并停止掉任何现存的事务”。 默认的 @Transactional
设置如下:
-
事务传播设置是
PROPAGATION_REQUIRED
-
事务隔离级别是
ISOLATION_DEFAULT
-
事务是 读/写
-
事务超时默认是依赖于事务系统的,或者事务超时没有被支持。
-
任何
RuntimeException
将触发事务回滚,但是任何 checkedException
将不触发事务回滚
这些默认的设置当然也是可以被改变的。 @Transactional
注解的各种属性设置总结如下:
属性 | 类型 | 描述 |
---|---|---|
传播性 | 枚举型:Propagation | 可选的传播性设置 |
隔离性 | 枚举型:Isolation | 可选的隔离性级别(默认值:ISOLATION_DEFAULT ) |
只读性 | 布尔型 | 读写型事务 vs. 只读型事务 |
超时 | int型(以秒为单位) | 事务超时 |
回滚异常类(rollbackFor) | 一组 Class 类的实例,必须是Throwable 的子类 | 一组异常类,遇到时 必须 进行回滚。默认情况下checked exceptions不进行回滚,仅unchecked exceptions(即RuntimeException 的子类)才进行事务回滚。 |
回滚异常类名(rollbackForClassname) | 一组 Class 类的名字,必须是Throwable 的子类 | 一组异常类名,遇到时 必须 进行回滚 |
不回滚异常类(noRollbackFor) | 一组 Class 类的实例,必须是Throwable 的子类 | 一组异常类,遇到时 必须不 回滚。 |
不回滚异常类名(noRollbackForClassname) | 一组 Class 类的名字,必须是Throwable 的子类 | 一组异常类,遇到时 必须不 回滚 |