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
相关推荐
小马哥编程3 小时前
【软考架构】案例分析-系统设计与建模:数据流图DFD与数据字典
java·数据库·架构·统一建模语言
人类二号3 小时前
MySQL安装及启用(社区版)
数据库·mysql
伊布拉西莫4 小时前
spring-ai advisors 使用与源码分析
java·人工智能·spring
Maruko3104 小时前
【无标题】
java
青衫码上行4 小时前
【Java Web学习 | 第三篇】CSS(2) - 元素显示模式
java·前端·学习
StarRocks_labs4 小时前
告别 Hadoop,拥抱 StarRocks!政采云数据平台升级之路
大数据·数据库·starrocks·hadoop·存算分离
小王不爱笑1324 小时前
Maven 进阶与私服架构
java·架构·maven
重整旗鼓~4 小时前
32.图片上传功能
java·redis
菜鸡儿齐4 小时前
ThreadLocal介绍
java·开发语言