Spring事务管理

Spring事务

  • Java EE应用的传统事务有两种策略:全局事务和局部事务。全局事务由应用服务器管理,需要底层服务器的JTA支持。局部事务和底层所采用的持久化技术有关,当采用JDBC持久化技术时,需要使用Connection对象来操作事务。
  • 全局事务可以跨多个事务性资源(比如说多个数据库和消息队列);使用局部事务,应用服务器不需要参与事务管理,因此不能保证多个事务性资源的事务正确性。
全局事务和局部事务
  • 局部事务 如果当前事务只有一个RM参与其中,就称当前事务为局部事务。比如在当前事务中只对一个数据库进行更新,或者只向一个数据库进行更新,或者只向一个消息队列中发送消息的情况,都属于局部事务。这是没有必要引入TP Monitor来协调管理多个RM之间的事务处理,可以使用RM内置的事务支持
  • 全局事务 整个事务处理过程中,有多个RM参与。TP Monitor采用两阶段提交,第一部分,应用程序提交后,需要TP Monitor调配;第二部分直接由TM统一调配

  • 局部事务支持 事务管理的具体处理方式,会随着使用的数据访问技术的不同而不同

  • 全局事务/分布式事务支持 分布式事务管理,主要是通过JTA(Java Transaction)或者JCA提供支持的
事务抽象

PlatformTransactionManager是整个事务抽象策略的顶层接口,具体实施则由相应的PlatformTransactionManager实现类来执行

  • 通常事务管理放在Service层,而将数据逻辑放在DAO层,当要保证两个DAO数据访问方法在同一个事务中,我们要保证使用的是同一个java.sql.Connection
  • 这样会导致数据访问和事务管理之间通过sql.Connection直接耦合
  • 具体操作:在事务开始前取得一个java.sql.Connection,将该Connection绑定到当前线程,数据访问对象可以在该线程获得Connection实例,从而完成数据访问工作
  • TransactionResourceManager存放java.sql.Connection事务资源

具体接口 Spring事务抽象包括3个主要接口,如图所示: 

  • PlatformTransactionManager负责界定事务边界,是Spring事务的核心组件。TransactionDefinition负责定义事务的相关属性,包括隔离级别、传播行为、超时时间和是否为只读事务。PlatformTransactionManager根据TransactionDefinition的属性定义来开启相关事务。事务开启之后到事务结束期间的事务状态由TransactionStatus负责。

  • PlatformTransactionManager有三个方法,其源码为:

public interface PlatformTransactionManager{
    //获得事务的方法
    TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;
    //事务提交方法
    void commit(TransactionStatus status) throws TransactionException;
    //事务回滚方法
    void rollback(TransactionStatus status) throws TransactionException;
}
事务的属性

事务的属性主要定义在TransactionDefinition中,包括: - 事务的隔离级别 - 事务的传播行为 - 事务的超时时间 - 是否为只读事务

事务的隔离级别

TransactionDefinition内定义了五个常量用于标志可供选择的隔离级别:

  • ISOLATION_DEFAULT:表示使用数据库默认的隔离级别,通常情况下是READ COMMITTED(提交读/不可重复读),但是MySQL的是REPEATABLE READ(可重复读)。
  • ISOLATION_READ_UNCOMMITTED:对应READ UNCOMMITTED(未提交读)隔离级别,会有脏读、不可重复读和幻读问题。
  • ISOLATION_READ_COMMITTED:对应READ COMMITTED(提交读)隔离级别,会有不可重复读和幻读问题。
  • ISOLATION_REPEATABLE_READ:对应REPEATABLE READ(可重复读)隔离级别,会有幻读问题。
  • ISOLATION_SERIALIZABLE:对应SERIALIZABLE(可串行化)隔离级别,可以避免脏读、幻读和不可重复读,但是并行效率最低。
事务的传播行为

Spring事务的传播行为表示整个事务处理过程所跨越的业务对象,将以什么样的行为参与事务。比如,当有FoobarService调用FooService和BarService两个方法的时候,FooService的业务方法和BarService的业务方法可以指定它们各自的传播行为。

TransactionDefinition提供了以下七种可供选择的事务传播行为:

  • PROPAGATION_REQUIRED:如果当前存在一个事务,则加入当前事务。如果当前不存在事务,则创建一个新事务。总之,要至少保证在一个事务中运行。通常作为默认的事务传播行为。
  • PROPAGATION_SUPPORTS:如果当前存在事务,则加入当前事务。如果当前不存在事务,则直接执行。
  • PROPAGATION_MANDATORY:强制要求当前存在一个事务,如果当前不存在事务,则直接抛出异常。如果某个方法需要事务支持,但自身又不管理事务提交或回滚,那么比较适用该传播行为。
  • PROPAGATION_REQUIRED_NEW:不管当前是否存在事务,都会创建新的事务。如果当前存在事务,则将当前事务挂起。如果某个业务对象所做的事情不想影响到外层事务,则适合该传播行为。
  • PROPAGATION_NOT_SUPPORT:不支持当前事务,要求在没有事务的情况下执行。如果当前存在事务,当前事务原则上将被挂起,但这要看对应的PlatformTransactionManager实现类是否支持事务的挂起。
  • PROPAGATION_NEVER:永远不需要当前存在事务,如果当前存在事务,则直接抛出异常。
  • PROPAGATION_NESTED:如果当前存在事务,则在当前事务中创建一个嵌套事务。如果当前不存在事务,则创建一个新事务,在新事务中执行。
PROPAGATION_REQUIRED_NEW与PROPAGATION_NESTED区别
  • 在当前存在事务的情况下,PROPAGATION_NESTED创建的是内嵌事务,是寄生于外层事务的,内部事务的内容也是属于外部事务的内容,其不能独立于外部事务存在,它的地位低于外层事务,并且不会挂起外层事务,内嵌事务运行的时候,外层事务的状态也是active状态。而PROPAGATION_REQUIRED_NEW创建的事务与外部事务是同级的,二者独立存在而互不干扰,并且PROPAGATION_REQUIRED_NEW创建新事务后会将当前事务挂起。该传播行为是Spring独有的。其需要特定的PlatformTransactionManager实现类支持。
  • 应用场景:可以将一个大的事务划分为多个小的事务来处理,并且外层事务可以根据内部嵌套事务的执行结果

TransactionStatus代表事务本身,它提供了简单的控制事务执行和查询事务状态的方法,其源码:

public interface TransactionStatus{
        //判断事务是否为新建的事务
        boolean isNewTransaction();
        //设置事务回滚
        void setRollbackOnly();
        //查询事务是否已有回滚标志
        boolean isRollbackOnly();
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值