Spring全家桶Spring

Spring详解9.事务

2019-01-25  本文已影响1人  卢卡斯哔哔哔

1 Spring事务模板

1.1 JTA事务与JDBC事务

JTA 深度历险 - 原理与实现
JDBC事务和JTA事务的区别

1.2 事务管理抽象层

Spring事务管理抽象

Spring的事务管理抽象层主要包括3个接口:PlatformTransactionManager、TransactionDefinition、TransactionStatus。TransactionDefinition用于描述事务的隔离级别、超时时间、是否为只读事务和事务传播规则等控制事务具体行为的事务属性;PlatformTransactionManager根据TransactionDefinition提供的事务属性配置信息创建事务,并用TransactionStatus描述这个激活事务的状态。

TransactionDefinition

TransactionDefinition定义了Spring的事务属性,这些属性对事务管理控制的若干方面进行配置。

TransactionStatus

TransactionStatus代表一个事务的具体运行状态。事务管理器可以通过该接口获取事务运行期的状态信息,也可以通过该接口间接地回滚事务,它相比于在抛出异常时回滚事务的方式更具可控性。该接口继承于SavepointManager接口,SavepointManager接口基于JDBC3.0保存点的分段事务控制能力提供了嵌套事务的机制。

PlatformTransactionManager

该接口描述了事务管理这个概念,它定义了3个接口方法,它们是SPI(Service Provider Interface)高层次的接口方法。这些访问都没有和JNDI绑定在一起,可以像 Spring容器中普通的Bean一样对待PlatformTransactionManager实现者。

public interface PlatformTransactionManager {
    // 该方法根据事务定义信息从事务环境中返回一个已存在的事务,或者创建一个新的事务
    // 并用TransactionStatus描述这个事务的状态
    TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;
    // 根据事务的状态提交事务
    // 如果事务状态已经被标识为rollback-only,则该方法将执行一个回滚事务的操作
    void commit(TransactionStatus status) throws TransactionException;
    // 将事务回滚,当 commit方法抛出异常时,rollback方法会被隐式调用。
    void rollback(TransactionStatus status) throws TransactionException;
}

1.3 事务管理器的实现类

Spring将事务管理委托给底层具体的持久化实现框架来完成。因此,Spring为不同的持久化框架提供了PlatformTransactionManager接口的实现类,这样就可以通过Spring所提交的高级抽象对不同种类的事务实现使用相同的方式进行管理,而不用关心具体的实现。具体实现类如下所示:

事务 说明
JpaTransactionManager 使用JPA进行持久化时,使用该事务管理器
HibernateTransactionManager 使用 Hibernate X.0(X可为3,4,5)版本进行持久化时,使用该事务管理器
DataSourceTransactionManager 使用Spring JDBC或MyBatis等基于DataSource数据源的持久化技术时,使用该事务管理器
JdoTransactionManager 使用JDO进行持久化时,使用该事务管理器
JtaTransactionManager 具有多个数据源的全局事务使用该事务管理器

1.4 事务同步管理器

Spring将JDBC的Connection、Hibernate的Session等访问数据库的连接或会话对象统称为资源,这些资源在同一时刻是不能多线程共享的。为了让DAO、Service类可能做到singleton, Spring的事务同步管理器类TransactionSynchronizationManager使用ThreadLocal为不同事务线程提供了独立的资源副本,同时维护事务配置的属性和运行状态信息。不管用户使用的是编程式事务管理,还是声明式事务管理,都离不开事务同步管理器。

工具类

Spring框架为不同的持久化技术提供了一套从TransactionSynchronizationManager中获取对应线程绑定资源的工具类,这些工具类都提供了静态的方法,通过这些方法可以获取和当前线程绑定的资源,如下所示:

持久化技术 线程绑定资源获取工具
Spring JDBC或MyBatis DataSourceUtils
Hibernate HibernateSessionFactoryUtils
JPA EntityManagerUtils
JDO PersistenceManagerFactoryUtils
TransactionSynchronizationManager

Spring为不同的持久化技术提供了模板类,模板类在内部通过资源获取工具类间接访问TransactionSynchronizationManager中的线程绑定资源。所以,如果DAO使用模板类进行持久化操作,这些DAO就可以配置成singleton。如果不使用模板类,也可以直接通过资源获取工具类访问线程相关的资源。TransactionSynchronizationManager将DAO、 Service类中影响线程安全的所有“状态”统一抽取到该类中,并用 ThreadLocal进行替换,从此DAO(必须是基于模板类或资源获取工具类创建的DAO)和 Service(必须釆用 Spring事务管理机制)变成了线程安全的。

public abstract class TransactionSynchronizationManager {
    // 用于保存每个事务线程对应的Connection或Session等类型的资源
    private static final ThreadLocal<Map<Object, Object>> resources =
            new NamedThreadLocal<Map<Object, Object>>("Transactional resources");


    private static final ThreadLocal<Set<TransactionSynchronization>> synchronizations =
            new NamedThreadLocal<Set<TransactionSynchronization>>("Transaction synchronizations");

   // 用于保存每个事务线程对应事务的名称
    private static final ThreadLocal<String> currentTransactionName =
            new NamedThreadLocal<String>("Current transaction name");

    // 用于保存每个事务线程对应事务的read-only状态 
    private static final ThreadLocal<Boolean> currentTransactionReadOnly =
            new NamedThreadLocal<Boolean>("Current transaction read-only status");

    // 用于保存每个事务线程对应事务的隔离级别
    private static final ThreadLocal<Integer> currentTransactionIsolationLevel =
            new NamedThreadLocal<Integer>("Current transaction isolation level");
    // 用于保存每个事务线程对应事务的激活态
    private static final ThreadLocal<Boolean> actualTransactionActive =
            new NamedThreadLocal<Boolean>("Actual transaction active");
}

1.5 事务传播行为

当我们调用一个基于Spring的Service接口方法时,它将运行于Spring管理的事务环境中,Service接口方法可能会在内部调用其他的Service接口方法以共同完成一个完整的业务操作,因此就会产生服务接口方法嵌套调用的情况。Spring通过事务传播行为控制当前的事务如何传播到被嵌套调用的目标服务接口方法中。Spring在TransactionDefinition接口中规定了7种类型的事务传播行为,它们规定了事务方法和事务方法发生嵌套调用时事务如何进行传播,

事务传播行为类型 说明
PROPAGATION REQUIRED 如果当前没有事务,则新建一个事务;如果已经存在一个事务,则加入到这个事务中。这是最常见的选择
PROPAGATION SUPPORTS 支持当前事务。如果当前没有事务,则以非事务方式执行
PROPAGATION MANDATORY 使用当前的事务。如果当前没有事务,则抛出异常
PROPAGATION REQUIRES NEW 新建事务。如果当前存在事务,则把当前事务挂起
PROPAGATION NOT SUPPORTED 以非事务方式执行操作。如果当前存在事务,则把当前事务挂起
PROPAGATION NEVER 以非事务方式执行。如果当前存在事务,则抛出异常
PROPAGATION NESTED 如果当前存在事务,则在嵌套事务内执行;如果当前没有事务,则执行与PROPAGATION REQUIRED类似的操作

2 编程式的事务管理

Spring还是为编程式事务管理提供了模板类TransactionTemplate,它和那些持久化模板类一样是线程安全的,因此可以在多个业务类中共享一个TransactionTemplate实例进行事务管理。TransactionTemplate有两个主要的方法:

    @Bean
    @Autowired
    public TransactionTemplate transactionTemplate(PlatformTransactionManager platformTransactionManager) {
        // 设置事务管理器
        TransactionTemplate transactionTemplate = new TransactionTemplate();
        transactionTemplate.setTransactionManager(platformTransactionManager);
        return transactionTemplate;
    }

3 使用注解配置声明式事务

开启事务

使用注解@EnableTransactionManagement

在类或者方法上添加@Transactional
@Service
@Transactional
public class StudentService {
    @Autowired
    private StudentMapper studentMapper;

    public void updateStudent(long id, String name, int sex) {
        studentMapper.update(new StudentDomain(id, name, sex, null, null));
    }
}
@Transactional的属性
属性名 说明
propagation 事务传播行为,通过枚举类Propagation提供合法值。默认PROPAGATION_REQUIRED。
isolation 事务隔离级别,通过枚举类Isolation提供合法值。ISOLATION_DEFAULT。
readonly 事务读写性,布尔型。
timeout 超时时间,int型,以秒为单位。依赖于底层的事务系统的默认值
rollbackFor 一组异常类,遇到时进行回滚,多个异常之间可用逗号分隔
rollbackForClassName 一组异常类名,遇到时进行回滚,类型为String[]
noRollbackFor 一组异常类,遇到时不回滚
noRollbackForClassName 一组异常类名,遇到时不回滚,类型为String。
上一篇 下一篇

猜你喜欢

热点阅读