放在接口上,那么接口的实现类中所有 public 都被 spring 自动加上事务
放在类上,那么当前类以及其下无限级子类中所有 pubilc 方法将被 spring 自动加上事务
注意:@Transaction 只对 public 方法有效
@Transactional 的配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33public Transactional {
// 通过 bean name 指定事务管理器
String value() default "";
// 同 value 属性
String transactionManager() default "";
// 指定传播行为
Propagation propagation() default Propagation.REQUIRED;
// 指定隔离级别
Isolation isolation() default Isolation.DEFAULT;
// 指定超时时间(单位秒)
int timeout() default -1;
// 是否只读事务
boolean readOnly() default false;
// 方法在发生指定异常时回滚,默认是所有异常都回滚
Class<? extends Throwable>[] rollbackFor() default {};
// 方法在发生指定异常名称时回滚,默认是所有异常都回滚
String[] rollbackForClassName() default {};
// 方法在发生指定异常时不回滚,默认是所有异常都回滚
Class<? extends Throwable>[] noRollbackFor() default {};
// 方法在发生指定异常名称时不回滚,默认是所有异常都回滚
String[] noRollbackForClassName() default {};
}Isolation 隔离级别
DEFAULT
——数据库默认隔离级别,MySQL 是可重复读,Oracle 是已提交读READ_UNCOMMITTED
——未提交读:事务读取其他事务未提交的数据READ_COMMITTED
——已提交读:事务读取最新的其他事务已提交的数据REPEATABLE_READ
——可重复读:事务读取该事务开始的时间点的其他事务已提交的数据SERIALIZABLE
——可序列化:所有事务只能一个接一个串行执行,不能并发
可能发生的问题:
脏读
——事务 T1 读取了已被事务 T2 更新但还没有提交的数据,若 T2 回滚,T1 读取到的就是无效内容不可重复读
——事务 T1 读取一个数据两次,在第一次和第二次之间,T2 更新了该数据,导致 T1 第二次读取到的数据不同幻读
——事务 T1 读取若干行数据两次,在第一次和第二次之间,T2 新增或删除该数据集,导致 T1 第二次读取到的数据条数不同
幻读与不可重复读之间的区别是幻读强调的是新增或删除,而不可重复读强调的是修改。
类型 脏读 不可重复读 幻读 未提交读 √ √ √ 已提交读 × √ √ 可重复读 × × √ 可序列化 × × × Propagation 传播行为
REQUIRED
——默认传播行为,需要事务,如果当前存在事务,就沿用当前事务,否则新建一个事务运行子方法SUPPORTS
——支持事务,如果当前存在事务,就沿用当前事务,如果不存在,则继续采用无事务的方式运行子方法MANDATORY
——必须使用事务,如果当前没有事务,则会抛出异常,如果存在当前事务 就沿用当前事务REQUIRES_NEW
——无论当前事务是否存在,都会创建新事务运行方法NOT_SUPPORTED
——不支持事务,当前存在事务时,将挂起事务,运行方法NEVER
——不支持事务,如果当前方法存在事务,则抛出异常,否则继续使用无事务机制运行NESTED
——外围主事务回滚,子事务一定回滚,而内部子事务可以单独回滚而不影响外围主事务和其他子事务。