You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SpringBoot中@Transactional注解的实际应用场景及示例解析

关于@Transactional注解的全面解析:概念、场景与示例

一、核心概念

@Transactional是Spring框架提供的声明式事务管理注解,本质是通过AOP代理自动完成事务的开启、提交、回滚流程,不用手动编写JDBC事务的conn.setAutoCommit(false)、commit()、rollback()这类代码。

事务的核心价值是保证数据一致性:一组关联的数据库操作,要么全部执行成功,要么全部回滚到操作前的状态,绝对不允许出现“部分成功、部分失败”的中间状态。

二、实际业务应用场景

以下是日常开发中最常见的使用场景:

  • 资金转账:用户A向用户B转账时,需要同时执行“扣减A的余额”和“增加B的余额”两个操作。如果其中任何一步失败,必须把已经执行的操作回滚,避免出现钱凭空消失或多出来的情况。
  • 订单与库存联动:创建订单时,要同步扣减对应商品的库存。如果订单创建失败(比如数据库报错、参数非法),库存必须恢复,不能出现“库存扣了但订单没生成”的异常情况。
  • 批量数据操作:比如批量导入100条用户数据,只要有一条数据不符合规则或插入失败,所有已经导入的数据都要回滚,保证数据库里的用户数据是完整且符合要求的。
  • 跨表/跨库业务操作:一次业务操作涉及多个表(比如同时修改用户表和日志表)或多个数据库的修改,必须用事务保证所有操作的原子性。

三、代码示例(转账场景)

业务层代码

@Service
public class TransferService {

    @Autowired
    private UserAccountDao userAccountDao;

    // 声明事务:默认发生RuntimeException时自动回滚
    @Transactional
    public void transfer(Long fromUserId, Long toUserId, BigDecimal amount) {
        // 第一步:扣减转出用户的余额
        userAccountDao.decreaseBalance(fromUserId, amount);

        // 模拟业务异常,测试事务回滚(实际开发中可能是数据库操作失败、参数校验不通过等)
        // if (amount.compareTo(new BigDecimal("1000")) > 0) throw new RuntimeException("单笔转账金额不能超过1000");

        // 第二步:增加转入用户的余额
        userAccountDao.increaseBalance(toUserId, amount);
    }
}

DAO层代码(基于Spring Data JPA)

@Repository
public interface UserAccountDao extends JpaRepository<UserAccount, Long> {

    @Modifying
    @Query("UPDATE UserAccount u SET u.balance = u.balance - :amount WHERE u.id = :userId")
    void decreaseBalance(@Param("userId") Long userId, @Param("amount") BigDecimal amount);

    @Modifying
    @Query("UPDATE UserAccount u SET u.balance = u.balance + :amount WHERE u.id = :userId")
    void increaseBalance(@Param("userId") Long userId, @Param("amount") BigDecimal amount);
}

四、关键注意事项

  • 回滚规则:默认只对RuntimeException和Error触发回滚,如果需要对检查型异常(比如IOException)也回滚,要设置@Transactional(rollbackFor = Exception.class)。
  • 方法权限:注解必须加在public方法上,Spring的AOP代理默认不会拦截非public方法,导致事务不生效。
  • 内部调用陷阱:如果在同一个类中调用带@Transactional的方法,AOP代理不会生效,事务不会触发。解决方法是把事务方法抽到单独的类中,或者通过ApplicationContext获取代理对象调用。

内容的提问来源于stack exchange,提问作者Shefat-Hasnain

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 00:35:28