Spring 事务原理
基于AOP配合ThreadLocal实现.
这里强调一下Spring Aop 以及Spring 注解式注入在非Spring容器管理的类中是无效的.
因为Spring Aop是在运行时实现字节码增强,字节码增强有多种实现方法,请自行了解,原生AspectJ是编译时织入,但是需要特定的编译器.语法并没有Spring Aop好理解.
事务传播行为类型
PROPAGATION_REQUIRED
如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是 最常见的选择。
PROPAGATION_SUPPORTS
支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY
使用当前的事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW
新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED
以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER
以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED
如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与 PROPAGATION_REQUIRED类似的操作。
事务隔离级别
事务隔离级别的设置是为了解决脏读,不可重复读,幻读等问题的。
下面来看下这几个问题的描述。
脏读
一个事务a读取了另一个事务b改写还未提交的数据,如果另一个事务b回滚,事务a读取到的数据是无效的。
不可重复读
在同一个事务中,多次读取同一数据读取到的结果不同。比如事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果不一致。
幻读
一个事务读取了几行数据后,另一个事务插入了新的数据后,幻读就发生了。再后来的查询中,第一个事务就会发现一些原来没有的数据。比如系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。
注意事项:
一旦使用了spirng事务,无论是哪种传播方式,对应的方法都只会开启一个数据库connection。
不是使用事务时,每次开启一个事务。
为什么呢?因为一旦使用了事务都必须在一个connection中,至于spirng事务的传播性只是spring托管事务时处理机制。