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指定抛出任何异常时,即回滚事务。