spring事务相关

目录

事务解决的问题

介绍事务的特性

事务的传播属性(Propagation)

事务的隔离级别(Isolation Level)

首先说明一下事务并发引起的三种情况

事务的隔离级别

@Transactional概念


 

事务解决的问题


事务可以保证要么同时(都)成功,要么同时(都)失败.


介绍事务的特性


            A    Atomicity        原子性,事务中的操作将会被视为一个整体不可分割的部分,要么都成功要么都失败.
            C    Consistency   一致性,事务执行前和执行后 数据的一致性应得以保证.例如tom账户减去100,相应的jerry账户就多出100;
            I      Isolation        隔离性,当同时存在多个事务的时候,事务之间应该不受干扰.
            D    Durability       持久性,事务一旦提交,数据会持久化到保存介质上.


事务的传播属性(Propagation)


Propagation支持7种不同的传播机制:
REQUIRED:如果存在一个事务,则支持当前事务。如果没有事务则开启一个新的事务。(默认属性)
SUPPORTS: 如果存在一个事务,支持当前事务。如果没有事务,则以非事务的执行。但是对于事务同步的事务管理                           器,PROPAGATION_SUPPORTS与不使用事务有少许不同。
NOT_SUPPORTED:总是非事务地执行,并挂起任何存在的事务。
REQUIRESNEW:总是开启一个新的事务。如果一个事务已经存在,则将这个存在的事务挂起。
MANDATORY:如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常。
NEVER:总是非事务地执行,如果存在一个活动事务,则抛出异常
NESTED:如果一个活动的事务存在,则运行在一个嵌套的事务中。如果没有活动事务,则按REQUIRED属性执行。

注: PROPAGATION_NESTED 与PROPAGATION_REQUIRES_NEW的区别:

它们非常 类似,都像一个嵌套事务,如果不存在一个活动的事务,都会开启一个新的事务。使用PROPAGATION_REQUIRES_NEW时,内层事务与外层事务就像两个独立的事务一样,一旦内层事务进行了提交后,外层事务不能对其进行回滚。两个事务互不影响。两个事务不是一个真正的嵌套事务。
使用PROPAGATION_NESTED时,外层事务的回滚可以引起内层事务的回滚。而内层事务的异常并不会导致外层事务的回滚,它是一个真正的嵌套事务(重点就在于那个save point)。

事务的隔离级别(Isolation Level)


首先说明一下事务并发引起的三种情况

1. Dirty Reads 脏读
        一个事务正在对数据进行更新操作,但是更新还未提交,另一个事务这时也来操作这组数据,并且读取了前一个事务还未提交的数据,而前一个事务如果操作失败进行了回滚,后一个事务读取的就是错误数据,这样就造成了脏读。
2. Non-Repeatable Reads 不可重复读
        一个事务多次读取同一数据,在该事务还未结束时,另一个事务也对该数据进行了操作,而且在第一个事务两次次读取之间,第二个事务对数据进行了更新,那么第一个事务前后两次读取到的数据是不同的,这样就造成了不可重复读。
3. Phantom Reads 幻像读
       第一个数据正在查询符合某一条件的数据,这时,另一个事务又插入了一条符合条件的数据,第一个事务在第二次查询符合同一条件的数据时,发现多了一条前一次查询时没有的数据,仿佛幻觉一样,这就是幻像读。
不可重复度和幻像读的区别
       非重复读是指同一查询在同一事务中多次进行,由于其他提交事务所做的修改,每次返回不同的结果集,此时发生不可重复读。
      幻像读是指同一查询在同一事务中多次进行,由于其他提交事务所做的插入操作,每次返回不同的结果集,此时发生幻像读。
      表面上看,区别就在于不可重复读能看见其他事务提交的修改和删除,而幻像能看见其他事务提交的插入。

事务的隔离级别

1. READ_UNCOMMITTED (读未提交)
这是事务最低的隔离级别,它允许另外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读。
2. READ_COMMITTED (读已提交)
保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。这种事务隔离级别可以避免脏读出现,但是可能会出现不可重复读和幻像读。
3. REPEATABLE_READ (可重复读)
这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了不可重复读。
4. SERIALIZABLE(串行化)
这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读外,还避免了幻像读。
MYSQL: 默认为REPEATABLE_READ级别;SQLSERVER: 默认为READ_COMMITTED

@Transactional概念

Spring中的@Transactional基于动态代理的机制,提供了一种透明的事务管理机制。
事务传播行为定义:
@Transactional(propagation=Propagation.REQUIRED)  
事务超时设置:
@Transactional(timeout=30) //默认是30秒
事务隔离级别定义:
@Transactional(isolation = Isolation.REPEATABLE_READ)

@Transactional注意事项:
1.在需要事务管理的地方加@Transactional 注解。@Transactional 注解可以被应用于接口定义和接口方法、类定义和类的 public 方法上。
2.@Transactional 注解只能应用到 public 可见度的方法上。 如果你在 protected、private 或者 package-visible 的方法上使用@Transactional 注解,它也不会报错, 但是这个被注解的方法将不会展示已配置的事务设置。
3.注意仅仅 @Transactional 注解的出现不足于开启事务行为,它仅仅 是一种元数据。必须在配置文件中使用配置元素,才真正开启了事务行为。
4.通过 元素的 “proxy-target-class” 属性值来控制是基于接口的还是基于类的代理被创建。如果 “proxy-target-class” 属值被设置为 “true”,那么基于类的代理将起作用(这时需要CGLIB库cglib.jar在CLASSPATH中)。如果 “proxy-target-class” 属值被设置为 “false” 或者这个属性被省略,那么标准的JDK基于接口的代理将起作用。
5.Spring团队建议在具体的类(或类的方法)上使用 @Transactional 注解,而不要使用在类所要实现的任何接口上。在接口上使用 @Transactional 注解,只能当你设置了基于接口的代理时它才生效。因为注解是 不能继承 的,这就意味着如果正在使用基于类的代理时,那么事务的设置将不能被基于类的代理所识别,而且对象也将不会被事务代理所包装。
6.@Transactional 的事务开启 ,或者是基于接口的 或者是基于类的代理被创建。所以在同一个类中一个方法调用另一个方法有事务的方法,事务是不会起作用的。

 

 

 

 

 

 

阅读更多
换一批

没有更多推荐了,返回首页