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无超时时间,超时后自动回滚。

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

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
相关推荐
逃逸线LOF7 分钟前
服务网关Gateway
java·运维·gateway
灿飞屋33 分钟前
Kotlin与Java虚拟机四:函数
java·python·kotlin·安卓·android jetpack
老纪的技术唠嗑局39 分钟前
把 seekdb 塞进 iOS App:让混合检索嵌入手机
数据库
ClouGence1 小时前
开源数据库管理工具 CloudDM 新版本发布,支持 OpenSearch、IoTDB 数据源
数据库·开源
阡陌数智1 小时前
Claude API新版本重大变更与安全升级指南
java·linux·安全
徐小黑ACG2 小时前
Redis-基础
数据库·redis·缓存
火山引擎开发者社区2 小时前
案例实践 | 让 Agent 读懂业务口径:ContextSearch 在广告数据查询中的实践
数据库
学长毕设3 小时前
基于SpringBoot的野生动物公益保护平台设计与实现-附源码
java·spring boot·后端
10年前端老司机3 小时前
Milvus 8种检索能力实践
数据库·python·agent
aiks_yuan4 小时前
MySQL 深分页 LIMIT 越翻越慢怎么办:300 万行实测 OFFSET、延迟关联和 keyset 的耗时差距(MySQL 8.2)
mysql