spring的7种事物的传播行为

@Transaction注解

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
33
34
35
36
37
38
39
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional {
//与value互为别名(互为别名的属性值必须设置默认值;互为别名不能同时设置)
@AliasFor("transactionManager")
String value() default "";
@AliasFor("value")
String transactionManager() default "";

//事物传播行为(默认值Propagation.REQUIRED如果有事务, 那么加入事务, 没有的话新建一个)
Propagation propagation() default Propagation.REQUIRED;

//事物隔离级别
Isolation isolation() default Isolation.DEFAULT;

//事物超时设置
int timeout() default TransactionDefinition.TIMEOUT_DEFAULT;

//设置当前事物是否为只读事物
boolean readOnly() default false;

//当方法中抛出指定异常数组中的异常时,则进行事务回滚
//@Transactional(rollbackFor={RuntimeException.class, Exception.class})
Class<? extends Throwable>[] rollbackFor() default {};

//当方法中抛出指定异常名称数组中的异常时,则进行事务回滚。
//@Transactional(rollbackForClassName={"RuntimeException","Exception"})
String[] rollbackForClassName() default {};

//当方法中抛出指定异常数组中的异常时,不进行事务回滚。
//@Transactional(noRollbackFor={RuntimeException.class, Exception.class})
Class<? extends Throwable>[] noRollbackFor() default {};

//当方法中抛出指定异常名称数组中的异常时,不进行事务回滚。
//@Transactional(noRollbackForClassName={"RuntimeException","Exception"})
String[] noRollbackForClassName() default {};
}

注意

  • 该注解中的方法Transaction#propagation()说明了事物的传播行为返回的是枚举类型Propagation

  • @Transactional 只能被应用到public方法上否则没有事物功能

  • @Transactional 注解可以被应用于接口定义和接口方法

  • Spring团队的建议是你在具体的类(或类的方法)上使用 @Transactional 注解,而不要使用在类所要实现的任何接口上。你当然可以在接口上使用 @Transactional 注解,但是这将只能当你设置了基于接口的代理时它才生效。因为注解是不能继承的,这就意味着如果你正在使用基于类的代理时,那么事务的设置将不能被基于类的代理所识别,而且对象也将不会被事务代理所包装(将被确认为严重的)。

事物的传播行为Propagation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public enum Propagation {
//如果有事务, 那么加入事务, 没有的话新建一个(默认)
REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED),

//如果当前调用有事物则使用事物,如果当前调用没有事物则不使用事物
SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS),

//必须在一个已有的事务中执行,否则抛出异常
MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY),

//不管是否存在事务,都创建一个新的事务,原来的挂起,新的执行完毕,继续执行老的事务
REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW),

//如果当前有事物将事物挂起,自己不使用事物进行数据库操作
NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED),

//必须在一个没有的事务中执行,否则抛出异常(与Propagation.MANDATORY相反)
NEVER(TransactionDefinition.PROPAGATION_NEVER),

//支持当前事务,如果当前事务存在,则执行一个嵌套事务,当前事务提交时嵌套事物才能提交;如果当前没有事务,就新建一个事务。
NESTED(TransactionDefinition.PROPAGATION_NESTED);
}

事物隔离级别Isolation

1
2
3
4
5
6
7
8
9
10
11
12
public enum Isolation {
//使用数据库默认的隔离级别
DEFAULT(TransactionDefinition.ISOLATION_DEFAULT),
//读未提交(脏读、不可重复读、幻读)
READ_UNCOMMITTED(TransactionDefinition.ISOLATION_READ_UNCOMMITTED),
//不可重复读(解决:脏读/未解决:不可重复读、幻读)
READ_COMMITTED(TransactionDefinition.ISOLATION_READ_COMMITTED),
//可重复读(mysql默认使用的隔离级别)(解决:脏读、不可重复读/未解决:幻读)
REPEATABLE_READ(TransactionDefinition.ISOLATION_REPEATABLE_READ),
//串行化(解决所有问题)
SERIALIZABLE(TransactionDefinition.ISOLATION_SERIALIZABLE);
}

事物的基本要素(ACID)

原子性(Atomicity)

  • 事务开始后所有操作,要么全部做完,要么全部不做,不可能停滞在中间环节。事务执行过程中出错,会回滚到事务开始前的状态,所有的操作就像没有发生一样。也就是说事务是一个不可分割的整体,就像化学中学过的原子,是物质构成的基本单位。

一致性(Consistency)

  • 事务开始前和结束后,数据库的完整性约束没有被破坏 。比如A向B转账,不可能A扣了钱,B却没收到。

隔离性(Isolation)

  • 同一时间,只允许一个事务请求同一数据,不同的事务之间彼此没有任何干扰。

持久性(Durability)

  • 事务完成后,事务对数据库的所有更新将被保存到数据库,不能回滚。

事物的并发问题

脏读

  • 事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据

不可重复读

  • 事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致。

幻读

  • 系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。

注意

1
注意:不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表。

如果本文对你有所帮助,请赏我1个铜板买喵粮自己吃,您的支持是我最大的动力!!!