Spring编程式事务和声明式事务

在 Spring 中,事务管理主要有两种方式:编程式事务声明式事务。它们的核心目标都是保证数据操作的原子性、一致性、隔离性和持久性(ACID),但实现方式和适用场景有显著区别。

编程式事务

编程式事务 是通过手动编写代码来控制事务的开启、提交、回滚等操作,开发者需要显式地管理事务的生命周期,核心类是 TransactionTemplate,它依赖 PlatformTransactionManager(事务管理器)来完成实际的事务操作。

java 复制代码
@Service
public class UserService {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Autowired
    private PlatformTransactionManager transactionManager;

    public void transferMoney(Long fromId, Long toId, int amount) {
        // 1. 定义事务属性(传播行为、隔离级别等)
        TransactionDefinition definition = new DefaultTransactionDefinition() {{
            setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
            setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
            setTimeout(30); // 超时时间 30 秒
        }};

        // 2. 开启事务
        TransactionStatus status = transactionManager.getTransaction(definition);

        try {
            // 执行数据库操作(扣钱)
            jdbcTemplate.update("UPDATE user SET balance = balance - ? WHERE id = ?", amount, fromId);
            // 执行数据库操作(加钱)
            jdbcTemplate.update("UPDATE user SET balance = balance + ? WHERE id = ?", amount, toId);

            // 3. 无异常则提交事务
            transactionManager.commit(status);
        } catch (Exception e) {
            // 4. 有异常则回滚事务
            transactionManager.rollback(status);
            throw new RuntimeException("转账失败", e);
        }
    }
}

声明式事务

声明式事务 是基于 AOP(面向切面编程),通过 @Transactional 注解或 XML 配置定义事务属性,在运行时动态生成代理对象,拦截目标方法并管理事务。需在 Spring 配置类中定义事务管理器(如 @EnableTransactionManagement 开启注解驱动,并注册 DataSourceTransactionManager)。

自调用失效 :同一类中,一个无事务方法调用另一个有事务的方法时,事务不会生效(因 Spring 事务基于 AOP 代理,自调用不会经过代理对象)解决:注入自身 Bean 或通过 AopContext.currentProxy() 获取代理对象调用。

@Transactional 可标注在 方法 上:

  • 标注在类上:表示该类中所有公共方法(public)都默认应用该事务配置。
  • 标注在方法上:表示该方法单独使用事务配置(方法级配置会覆盖类级配置)。

事务管理器(多数据源场景下需指定):value/transactionManager

事务传播行为(propagation):propagation = Propagation.REQUIRED(默认)如果当前已经存在事务 (即调用该方法的外层方法已有事务),则加入当前事务 ,方法与外层事务共用一个事务(同成功、同回滚)。如果当前没有事务 (外层方法无事务),则创建一个新的事务,方法在新事务中执行。

事务隔离级别(isolation):DEFAULT:使用数据库默认隔离级别(如 MySQL 默认为 REPEATABLE_READ)。

只读事务readOnly:默认false

事务超时时间time:(秒):默认-1无超时时间,超时后自动回滚。

回滚规则:默认情况下,事务仅在抛出 未捕获的 RuntimeExceptionError 时回滚; checked 异常(如 IOException)不会触发回滚,可过 rollbackFornoRollbackFor 自定义

PlatformTransactionManager

两种方式的底层都依赖Spring 框架的 PlatformTransactionManager 接口实现事务的具体操作(如提交、回滚),只是编程式需要手动触发,而声明式由 Spring 自动触发。

PlatformTransactionManager 负责管理事务的生命周期,包括:

  • 开启事务(getTransaction(...)
  • 提交事务(commit(...)
  • 回滚事务(rollback(...)

它是一个**抽象接口,**具体的事务管理逻辑由其实现类根据不同的资源类型(如 JDBC、JPA、Hibernate 等)实现。

实现类 适用场景 依赖资源
DataSourceTransactionManager 管理 JDBC 事务(最常用) javax.sql.DataSource
JpaTransactionManager 管理 JPA 事务 JPA EntityManagerFactory
HibernateTransactionManager 管理 Hibernate 事务(旧版本 Hibernate) Hibernate SessionFactory
JtaTransactionManager 管理分布式事务(跨多个资源,如多数据库) JTA 环境(如 Java EE 容器)
RabbitTransactionManager 管理 RabbitMQ 消息队列事务 RabbitMQ ConnectionFactory
相关推荐
武子康5 分钟前
大数据-241 离线数仓 - 实战:电商核心交易数据模型与 MySQL 源表设计(订单/商品/品类/店铺/支付)
大数据·后端·mysql
SimonKing8 分钟前
JetBrains 用户狂喜!这个 AI 插件让 IDE 原地进化成「智能编码助手」
java·后端·程序员
狂奔小菜鸡11 分钟前
Day39 | Java中更灵活的锁ReentrantLock
java·后端·java ee
NE_STOP13 小时前
MyBatis-配置文件解读及MyBatis为何不用编写Mapper接口的实现类
java
数据组小组14 小时前
免费数据库管理工具深度横评:NineData 社区版、Bytebase 社区版、Archery,2026 年开发者该选哪个?
数据库·测试·数据库管理工具·数据复制·迁移工具·ninedata社区版·naivicat平替
后端AI实验室18 小时前
用AI写代码,我差点把漏洞发上线:血泪总结的10个教训
java·ai
用户83071968408219 小时前
MySQL 查询优化 30 条封神技巧:用好索引,少耗资源,查询快到飞起
mysql
程序员清风20 小时前
小红书二面:Spring Boot的单例模式是如何实现的?
java·后端·面试
belhomme20 小时前
(面试题)Redis实现 IP 维度滑动窗口限流实践
java·面试
Be_Better20 小时前
学会与虚拟机对话---ASM
java