Spring 事务管理三种实现方式详解
作者:一只大袋鼠
本文主要讲解了Spring事务的三种配置方式,以转账操作为例,通俗易懂,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
一、前言
在上一篇博客中,我们学习了 Spring JdbcTemplate 实现转账操作。但是:如果转账过程中程序报错,钱会只扣不加,造成数据错误!
所以必须使用 Spring 事务管理,保证转账要么全部成功,要么全部失败。本文讲解 Spring 事务 3 种配置方式,基于转账案例,通俗易懂,适合新手学习。
二、事务核心 API
Spring 事务管理的核心接口:
- PlatformTransactionManager:平台事务管理器
- DataSourceTransactionManager:JDBC / MyBatis 专用实现类
- TransactionDefinition:事务定义(隔离级别、传播行为)
三、环境说明
Maven 依赖(pom.xml)
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.qcby</groupId>
<artifactId>spring-aop-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!-- Spring核心 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.31</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.31</version>
</dependency>
<!-- 注解支持 -->
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>
<!-- 日志 -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<!-- 测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.3.31</version>
<scope>test</scope>
</dependency>
<!-- 数据库 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
<!-- AOP 相关 -->
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.3.31</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.3</version>
</dependency>
</dependencies>
</project>配置文件:application.properties 存放数据库连接信息
jdbc.driverClassName=com.mysql.cj.jdbc.Driver jdbc.url=jdbc:mysql:///spring_db?useSSL=false&serverTimezone=UTC jdbc.username=root jdbc.password=123456
数据库表结构
CREATE TABLE account(
name VARCHAR(20),
money DOUBLE
);
-- 初始化数据
INSERT INTO account VALUES ('熊大',1000),('熊二',500);四、✨ 方式一:XML 声明式事务
1、原理
基于 AOP 切面,在 XML 中配置事务规则,对业务方法进行增强。
2、完整 XML 配置
<?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:aop="http://www.springframework.org/schema/aop"
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/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 加载配置 -->
<context:property-placeholder location="classpath:application.properties"/>
<!-- 连接池 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!-- 1. 事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 2. 事务通知 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="pay" isolation="DEFAULT" propagation="REQUIRED"/>
<tx:method name="find*" read-only="true"/>
</tx:attributes>
</tx:advice>
<!-- 3. AOP 切面配置 -->
<aop:config>
<aop:advisor advice-ref="txAdvice" pointcut="execution(* com.qcby.demo4.AccountServiceImpl.pay(..))"/>
</aop:config>
<!-- Dao & Service -->
<bean id="accountDao" class="com.qcby.demo4.AccountDaoImpl">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="accountService" class="com.qcby.demo4.AccountServiceImpl">
<property name="accountDao" ref="accountDao"/>
</bean>
</beans>3、业务代码
// Service
public class AccountServiceImpl implements AccountService {
private AccountDao accountDao;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
@Override
public void pay(String out, String in, double money) {
accountDao.outMoney(out, money);
// int i = 1 / 0; 开启异常,事务回滚
accountDao.inMoney(in, money);
}
}五、✨ 方式二:XML + 注解事务
1、步骤
- 开启注解扫描
- 开启事务注解驱动
- 在 Service 上加
@Transactional
2、XML 配置
<?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/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 注解扫描 -->
<context:component-scan base-package="com.qcby.demo5"/>
<context:property-placeholder location="classpath:application.properties"/>
<!-- 连接池 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!-- 事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- JdbcTemplate -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 开启事务注解 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>3、Service 事务注解
@Service
@Transactional(isolation = Isolation.DEFAULT)
public class AccountServiceImpl implements AccountService {
@Autowired
private AccountDao accountDao;
@Override
public void pay(String out, String in, double money) {
accountDao.outMoney(out, money);
// int a = 1/0; 报错自动回滚
accountDao.inMoney(in, money);
}
}六、✨ 方式三:纯注解事务(完全无 XML)
1、配置类
@Configuration
@ComponentScan("com.qcby.demo6")
@EnableTransactionManagement // 开启事务
public class SpringConfig {
@Bean
public DataSource dataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("com.mysql.cj.jdbc.Driver");
ds.setUrl("jdbc:mysql:///spring_db?useSSL=false&serverTimezone=UTC");
ds.setUsername("root");
ds.setPassword("Zhen@777");
return ds;
}
@Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource){
return new JdbcTemplate(dataSource);
}
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource){
return new DataSourceTransactionManager(dataSource);
}
}2、Service 代码
@Service
@Transactional
public class AccountServiceImpl implements AccountService {
@Autowired
private AccountDao accountDao;
@Override
public void pay(String out, String in, double money) {
accountDao.outMoney(out, money);
accountDao.inMoney(in, money);
}
}七、测试代码(通用)
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext_tx.xml")
public class Demo4Test {
@Autowired
private AccountService accountService;
@Test
public void testPay(){
accountService.pay("熊大","熊二",100);
System.out.println("✅ 转账成功(事务已生效)");
}
}八、事务三种方式
| 方式 | 优点 |
|---|---|
| XML 声明式事务 | 无侵入、不修改代码 |
| XML + 注解事务 | 简单易用、最常用 |
| 纯注解事务 | 无配置文件、简洁 |
到此这篇关于Spring 事务管理三种实现方式详解的文章就介绍到这了,更多相关Spring 事务管理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
