• spring事务详解(二)简单样例


    系列目录

    spring事务详解(一)初探事务

    spring事务详解(二)简单样例

    spring事务详解(三)源码详解

    spring事务详解(四)测试验证

    spring事务详解(五)总结提高

    一、引子

    在Spring中,事务有两种实现方式:

    1. 编程式事务管理: 编程式事务管理使用底层源码可实现更细粒度的事务控制。spring推荐使用TransactionTemplate,典型的模板模式。
    2. 申明式事务管理: 添加@Transactional注解,并定义传播机制+回滚策略。基于Spring AOP实现,本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。

    二、简单样例

    需求:

    创建用户时,新建一个用户余额表。如果用户余额创建失败抛出异常,那么用户表也回滚,即要保证“新增用户+新增用户余额”一起成功 或 回滚。

    2.1 申明式事务管理

    如下图,只需要在service.impl层,业务方法上添加@Transactional注解,定义事务的传播机制为REQUIRED(不写这个参数,默认就是REQUIRED),遇到Exception异常就一起回滚。

    REQUIRED传播机制下:存在加入事务,不存在创建新事务。保证了当前方法中的所有数据库操作都在一个物理事务中,当遇到异常时会整个业务方法一起回滚。

     1 /**
     2      * 创建用户并创建账户余额
     3      *
     4      * @param name
     5      * @param balance
     6      * @return
     7      */
     8     @Transactional(propagation= Propagation.REQUIRED, rollbackFor = Exception.class)
     9     @Override
    10     public void addUserBalanceAndUser(String name, BigDecimal balance) {
    11         log.info("[addUserBalanceAndUser] begin!!!");
    12         //1.新增用户
    13         userService.addUser(name);
    14         //2.新增用户余额
    15         UserBalance userBalance = new UserBalance();
    16         userBalance.setName(name);
    17         userBalance.setBalance(new BigDecimal(1000));
    18         this.addUserBalance(userBalance);
    19         log.info("[addUserBalanceAndUser] end!!!");
    20     }

    2.2 编程式事务管理

    编程式事务管理,我们使用Spring推荐的transactionTemplate。我这里因为使用的是spring cloud的注解配置,实现用了自动配置类配置好了TransactionTemplate这个类型的bean.使用的时候直接注入bean使用即可(当然老式的xml配置也是一样的)。如下:

     1 /**
     2      * 创建用户并创建账户余额(手动事务,不带结果)
     3      *
     4      * @param name
     5      * @param balance
     6      * @return
     7      */
     8     @Override
     9     public void addUserBalanceAndUserWithinTT(String name, BigDecimal balance) {
    10         //实现一个没有返回值的事务回调
    11         transactionTemplate.execute(new TransactionCallbackWithoutResult() {
    12             @Override
    13             protected void doInTransactionWithoutResult(TransactionStatus status) {
    14                 try {
    15                     log.info("[addUserBalanceAndUser] begin!!!");
    16 
    17                     //1.新增用户
    18                     userService.addUser(name);
    19                     //2.新增用户余额
    20                     UserBalance userBalance = new UserBalance();
    21                     userBalance.setName(name);
    22                     userBalance.setBalance(new BigDecimal(1000));
    23                     userBalanceRepository.insert(userBalance);
    24                     log.info("[addUserBalanceAndUser] end!!!");
    25                     //注意:这里catch住异常后,设置setRollbackOnly,否则事务不会滚。当然如果不需要自行处理异常,就不要catch了
    26                 } catch (Exception e) {
    27                     // 异常回滚
    28                     status.setRollbackOnly();
    29                     log.error("异常回滚!,e={}",e);
    30                 }
    31 
    32             }
    33         });
    34     }

    注意:

    1.可以不用try catch,transactionTemplate.execute自己会捕捉异常并回滚。--》推荐

    2.如果有业务异常需要特殊处理,记得:status.setRollbackOnly(); 标识为回滚。--》特殊情况才使用

    三、总结

    spring支持的这两种方式都可以,个人认为大部分情况下@Transactional可以满足需要。

  • 相关阅读:
    07word转换pdf
    高德纳《计算机程序设计艺术》(The Art of Computer Programming)的作者
    DbVisualizer 8 解决中文乱码问题 (20120310 20:23)
    IT has never been easier or harder
    el表达式和s:property的区别
    df 和 du 命令详解
    dbvisualizer 8.0 破解(free>personal)
    ping 中的TTL查看操作系统
    netstat 监控TCP/IP网络
    ls l 命令
  • 原文地址:https://www.cnblogs.com/dennyzhangdd/p/9708499.html
Copyright © 2020-2023  润新知