SpringTx

我们知道诸如MySQL、Oracle、SQLServer等这类大型关系型数据库系统具有事务和事务隔离级别的概念,我们的Java程序一般都是通过JDBC操作数据库,比如开启事务、提交事务、设置隔离级别等,在JDBC接口中也有这些概念的定义。如果直接使用JDBC操作数据库,那么我们就需要调用相关的API,手动处理这些操作。不过在Spring中,框架提供了事务管理器TransactionManager功能。我们在配置文件中配置好事务管理器,当框架从数据源中获取JDBC的Connection对象并进行一些操作时,Spring会自动通过AOP拦截管理事务操作,合理使用Spring事务管理器能大大简化我们代码的编写。

相关概念

事务隔离级别:关系型数据库的事务具有隔离级别这一概念,JDBC作为一个通用的抽象接口,也定义了相关隔离级别的常量值,这部分源码可以在java.sql.Connection类中找到。

事务隔离级别 说明
TRANSACTION_NONE 代表JDBC驱动不支持事务,一般不会用到该项。
TRANSACTION_READ_UNCOMMITTED 允许脏读,不可重复读和幻读。
TRANSACTION_READ_COMMITTED 不可脏读,但允许不可重复读和幻读。
TRANSACTION_REPEATABLE_READ 不可脏读和不可重复读,但允许幻读。
TRANSACTION_SERIALIZABLE 不可脏读,不可重复读,幻读。

注:MySQL数据库默认的事务隔离级别为REPEATABLE_READ

事务传播属性:Spring框架中的事务管理器支持该配置,用于声明在多个声明了事务的方法互相调用时,事务如何在方法间传播。

事务传播属性 说明
PROPAGATION_REQUIRED 支持当前事务,如果当前没有事务就新建,最常用,默认。
PROPAGATION_SUPPORTS 支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY 支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW 新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER 以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED 如果当前存在事务,则在嵌套事务内执行;如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。

引入SpringTx相关依赖

如果你是手动搭建的传统Spring工程,使用事务管理器需要引入SpringTx的依赖库,我们这里使用的是Spring6版本,SpringTx的版本号一般与Spring框架保持一致。

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
    <version>6.2.17</version>
</dependency>

至于SpringBoot工程,我们完全不需要显式引入SpringTx,且在非多数据源情况下也通常不需要任何额外配置,事务管理器默认就是配置好的。

配置事务管理器

在Spring工程中,配置事务管理器的写法如下,事务管理器Bean使用ref引用了数据源Bean作为参数,事务管理器的相关功能就会在该数据源上生效。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/tx
       http://www.springframework.org/schema/tx/spring-tx.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 这里省略数据源配置 -->
    <bean id="dataSource" class="...">...</bean>

    <!-- 事务管理器 -->
    <bean id="transactionManager"
          class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!-- 声明式事务注解扫描 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>
</beans>

使用声明式事务

Spring中最常用的就是声明式事务,用法如下。

@Service("testService")
@Transactional(rollbackFor = Exception.class)
public class TestServiceImpl implements TestService {
    // ... 具体实现相关代码
}

代码中,我们使用了@Transactional标注了一个类,这标明其方法执行时,默认就会以声明的事务隔离级别和传播属性执行。rollbackFor = Exception.class指定抛出任何异常时,即回滚事务。

作者:Gacfox
版权声明:本网站为非盈利性质,文章如非特殊说明均为原创,版权遵循知识共享协议CC BY-NC-ND 4.0进行授权,转载必须署名,禁止用于商业目的或演绎修改后转载。