学习笔记084——Spring中 @Transactional 和 TransactionTemplate 的使用和区别

1、@Transactional

‌@Transactional注解是声明式事务管理方式‌,通过注解即可管理事务,无需手动编写事务模板代码,适用于简单的事务操作和需要快速实现事务管理的场景。

优点

  1. 代码简洁:通过注解即可管理事务,无需手动编写事务模板代码,减少侵入性。
  2. 集中管理:事务配置(传播行为、隔离级别、回滚规则等)集中到注解中,方便维护。
  3. AOP支持:基于Spring AOP实现,天然支持事务的传播行为和嵌套事务。
  4. 统一异常回滚:默认对RuntimeExceptionError回滚,可通过rollbackFor/noRollbackFor配置。

缺点

  1. 隐式控制:事务边界由代理机制隐式管理,调试和理解复杂场景时可能不够直观。
  2. 自调用问题:同类内的方法调用(如this.method())会绕过代理,导致@Transactional失效。
  3. 异常处理敏感:默认只回滚非受检异常(如RuntimeException),需显式配置受检异常(如SQLException)。
  4. 粒度限制:事务只能作用于方法级别,无法在代码块级别更细粒度控制。

使用

@Service 
public class UserService { 
    
    @Autowired 
    private UserRepository userRepository; 
    
    @Transactional 
    public void createUser(User user) { 
        userRepository.save(user); 
        // 模拟异常 
        if (true) { 
            throw new RuntimeException("模拟异常"); 
        } 
    } 
}

2、TransactionTemplate

‌TransactionTemplate是Spring提供的编程式事务管理工具‌,通过代码显式控制事务的开启、提交和回滚,适用于需要动态或复杂事务逻辑的场景。

优点

  1. 显式控制:事务代码完全由开发者手动编写,事务边界清晰可见。
  2. 灵活控制:可以在代码块级别控制事务(例如:在循环中部分提交事务)。
  3. 精细异常处理:直接在代码中处理异常,可灵活决定回滚或提交。
  4. 避免代理问题:不受Spring AOP代理机制限制(如自调用问题)。

缺点

  1. 代码冗余:需要显式编写事务模板代码,侵入性较高。
  2. 维护成本:事务逻辑分散在代码中,可能增加维护难度。
  3. 事务传播配置复杂:需要手动处理事务传播行为(例如嵌套事务)。

使用

@Service
@Slf4j
public class TransactionTemplateDemo {

    @Resource
    private UserRepository userRepository;

    @Resource
    private TransactionTemplate transactionTemplate;


    // 1、execute(TransactionCallback<T> action)
    // 功能:执行包含事务的代码块,支持返回值。
    public void demo() {
        transactionTemplate.execute((status) -> {
            try {
                //执行方法
                save();
                //制造异常
                int i = 1 / 0;
                return true;
            } catch (Exception e) {
                log.error("保存失败", e);
                //回滚
                status.setRollbackOnly();
                log.info("数据回滚~");
                return false;
            }
        });
    }


    // 2、executeWithoutResult(Consumer<TransactionStatus> action)
    // 功能:执行包含事务的代码块,支持返回值。
    public void demo2() {
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
                try {
                    //执行方法
                    save();
                    save2();
                } catch (Exception e) {
                    log.error("保存失败", e);
                    //回滚
                    transactionStatus.setRollbackOnly();
                    log.info("数据回滚~");
                }
            }
        });
    }




    public void save() {
        User user = new User();
        user.setUsername("张三");
        user.setPassword("123456");
        user.setRegdate(new Date());
        userRepository.save(user);
        log.info("保存成功");
    }


    public void save2() {
        User user = new User();
        user.setUsername("张三");
        user.setPassword("123456");
        userRepository.save(user);
        log.info("保存成功");
    }

}

3、注意事项

  1. 异常处理
    • @Transactional默认回滚RuntimeExceptionError,需通过rollbackFor配置其他异常。
    • TransactionTemplate需在代码中显式捕获异常并调用status.setRollbackOnly()
  2. 事务传播行为
    • @Transactional可通过propagation属性配置(如Propagation.REQUIRES_NEW)。
    • TransactionTemplate需通过TransactionDefinition手动配置。
  3. 性能:两者性能差异可忽略,优先考虑代码可维护性。
### Spring框架中 `@Transactional` 注解与 `TransactionTemplate` 的区别及用法场景 #### 一、定义与特性 - **`@Transactional` 注解** 属于声明式事务管理的一部分,用于简化事务管理的配置工作。此注解可以应用于接口定义类定义处以及公共方法上[^1]。 - **`TransactionTemplate`** 是一种编程式的事务管理工具,提供了一种模板模式来执行事务性的操作。相比直接使用 `PlatformTransactionManager` 更为简便,但仍需编写额外代码来进行事务逻辑封装[^2]。 #### 二、主要差异 | 对比项 | @Transactional 注解 | TransactionTemplate | |--|---------------------------------------------------------|---------------------------------------------------| | 实现方式 | 利用了Spring AOP技术,在运行期动态创建代理对象 | 需要在业务逻辑内部显式调用来启动/结束事务 | | 方法可见性 | 应仅作用于public修饰的方法 | 不受限于访问权限 | | 同一类内调用情况 | 若非事务方法调用带@Transactional标注的方法,则后者事务不生效;反之则事务有效 | 总能正常运作 | | 跨服务层调用表现 | 正常情况下能够按照预期触发事务 | 类似地保持良好性能 | #### 三、适用场合 - 当希望减少侵入性提高可读性时,应优先考虑采用带有 `@Transactional` 的声明式风格; - 如果遇到复杂的嵌套事务需求或是需要更细粒度控制的情况,那么借助 `TransactionTemplate` 进行程序化处理可能是更好的选择。 ```java // 使用 @Transactional 示例 @Service class MyService { @Autowired private AnotherService anotherService; @Transactional(readOnly = false, propagation = Propagation.REQUIRED) public void performOperation() { // 执行数据库更新等操作... anotherService.doSomething(); } } // 使用 TransactionTemplate 示例 @Service class MyOtherService { @Autowired private PlatformTransactionManager txManager; public void executeWithTx(){ new TransactionTemplate(txManager).execute(status -> { try{ // 执行受保护的操作 return null; } catch (Exception e){ status.setRollbackOnly(); throw e; } }); } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值