转载

Spring事务解析

事务特性

原子性(Atomicity):事务是一个原子操作,由一系列动作组成。事务的原子性确保动作要么全部完成,要么完全不起作用。

一致性(Consistency):一旦事务完成(不管成功还是失败),系统必须确保它所建模的业务处于一致的状态,而不会是部分完成部分失败。在现实中的数据不应该被破坏。

隔离性(Isolation):可能有许多事务会同时处理相同的数据,因此每个事务都应该与其他事务隔离开来,防止数据损坏。

持久性(Durability):一旦事务完成,无论发生什么系统错误,它的结果都不应该受到影响,这样就能从任何系统崩溃中恢复过来。通常情况下,事务的结果被写到持久化存储器中。

核心接口:PlatformTransactionManager 事务管理器

Spring事务解析

Spring并 不直接管理事务,只有当数据库支持事务时,Spring才支持事务 ,Spring只不过简化了开发人员实现事务的步骤,Spring提供了多种事务管理器,他们将事务管理的职责委托给Hibernate或者JTA等 持久化机制所提供的相关平台框架的事务 来实现。

PlatformTransactionManager 事务管理器:

Spring事务管理器的接口是org.springframework.transaction.PlatformTransactionManager,通过这个接口,Spring为各个平台如JDBC、Hibernate等都提供了对应的事务管理器,但是具体的实现就是各个平台自己的事情了。此接口的内容如下:

Spring事务解析

三个方法分别是:

  • 由TransactionDefinition得到TransactionStatus对象
  • 提交
  • 回滚

TransactionStatus 事务状态 :

PlatformTransactionManager中有个getTransaction(TransactionDefinition var1)方法,这个方法返回的是TransactionStatus对象,然后程序根据返回的对象来获取事务状态,然后进行相应的操作。

Spring事务解析

几个方法分别是:

  • 是否是新事务
  • 是否有保存点
  • 设置回滚点 
  • 是否刷新
  • 是否完成

TransactionDefinition 基本事务属性的定义:

事务属性可以理解成事务的一些基本配置,描述了事务策略如何应用到方法上。事务属性包含了5个方面,如图所示:

Spring事务解析

Spring事务解析

方法分别是:

  • 获取事务传播行为
  • 获取隔离级别
  • 获取超时时间
  • 是否只读
  • 获取配置事务名称

传播行为: 事务的第一个方面是传播行为(propagation behavior),当事务方法被另一个事务方法调用时,必须指定事务应该如何传播。

Spring定义了七种传播行为:

这里以A业务和B业务之间如何传播事务为例说明:

①、PROPAGATION_REQUIRED : 默认值 ,A如果有事务,B将使用该事务;如果A没有事务,B将创建一个新的事务。

②、PROPAGATION_SUPPORTS:A如果有事务,B将使用该事务;如果A没有事务,B将以非事务执行。

③、PROPAGATION_MANDATORY:A如果有事务,B将使用该事务;如果A没有事务,B将抛异常。

④、PROPAGATION_REQUIRES_NEW :如果A有事务,将A的事务挂起,B创建一个新的事务;如果A没有事务,B创建一个新的事务。

⑤、PROPAGATION_NOT_SUPPORTED :如果A有事务,将A的事务挂起,B将以非事务执行;如果A没有事务,B将以非事务执行。

⑥、PROPAGATION_NEVER :如果A有事务,B将抛异常;如果A没有事务,B将以非事务执行。

⑦、PROPAGATION_NESTED :A和B底层采用保存点机制,形成嵌套事务。

传播行为: 事务的第一个方面是传播行为(propagation behavior),当事务方法被另一个事务方法调用时,必须指定事务应该如何传播。

隔离级别:定义了一个事务可能受其他并发事务影响的程度。

并发事务引起的问题:

①、脏读(Dirty reads)——脏读发生在一个事务读取了另一个事务改写但尚未提交的数据时。如果改写在稍后被回滚了,那么第一个事务获取的数据就是无效的。

②、不可重复读(Nonrepeatable read)——不可重复读发生在一个事务执行相同的查询两次或两次以上,但是每次都得到不同的数据时。这通常是因为另一个并发事务在两次查询期间进行了更新。

③、幻读(Phantom read)——幻读与不可重复读类似。它发生在一个事务(T1)读取了几行数据,接着另一个并发事务(T2)插入了一些数据时。在随后的查询中,第一个事务(T1)就会发现多了一些原本不存在的记录。

注意:不可重复读重点是修改,而幻读重点是新增或删除。

在 Spring 事务管理中,为我们定义了如下的隔离级别:

后端数据库默认

Spring 中实现事务的方式

Spring 提供了两种方式实现事务: ①声明式,②编程式。

编程式事务: 允许用户在代码中精确定义事务的边界。

声明式事务: (基于AOP)有助于用户将操作与事务规则进行解耦。简单地说,编程式事务侵入到了业务代码里面,但是提供了更加详细的事务管理;而声明式事务由于基于AOP,所以既能起到事务管理的作用,又可以不影响业务代码的具体实现。

声明式事务:

声明式事务管理只需要用到@Transactional 注解和@EnableTransactionManagement(开启事务管理功能)。它是基于 Spring AOP 实现的,并且通过注解实现,实现起来简单,对原有代码没有入侵性。

事务的切面有两个主要职责:

在’before’时,切面提供一个调用点,来决定被调用业务方法应该在正在进行事务的范围内运行,还是开始一个新的独立事务。

在’after’时,切面需要确定事务被提交,回滚或者继续运行。

@Transactional注解不起作用的集中情况:

①Transactional注解标注方法修饰符为非public时,@Transactional注解将会不起作用。

②在类内部调用调用类内部@Transactional标注的方法。这种情况下也会导致事务不开启。

Spring事务解析

③事务方法内部捕捉了异常,没有抛出新的异常,导致事务操作不会进行回滚。

④ 异常类型是不是unchecked异常。如果我想check异常也想回滚怎么办,注解上面写明异常类型即可。@Transactional(rollbackFor=Exception.class)

原文  https://juejin.im/post/5d58f1eb6fb9a06b2548e38f
正文到此结束
Loading...