当前位置 : 主页 > 编程语言 > java >

【SpringBoot】事务的使用(编程式、声明式)及 @Transactional 工作原理、失效处理

来源:互联网 收集:自由互联 发布时间:2022-09-02
@TOC 回顾 事务 事务的本质就是某个操作要么都成功, 要么都失败 事务在项目开发中十分重要, 涉及到数据一致性和完整性问题, 不能马虎 事务的ACID原则 原子性 一致性 隔离性, 多个业务

@TOC


回顾 事务

  • 事务的本质就是某个操作要么都成功, 要么都失败
  • 事务在项目开发中十分重要, 涉及到数据一致性和完整性问题, 不能马虎
  • 事务的ACID原则
  • 原子性
  • 一致性
  • 隔离性, 多个业务可能操作同一个资源, 防止数据损坏
  • 持久性, 事务一旦发生, 无论系统发生什么问题, 结果都不会再被影响, 被持久的写到存储器中

  • Spring 中事务的实现

    Spring 中的事务操作分为两类:

  • ⼿动操作事务
  • 声明式⾃动提交事务
  • 在开始讲解它们之前,咱们先来回顾事务在 MySQL 中是如何使⽤的?


    MySQL 中的事务使⽤(回顾)

    事务在 MySQL 有 3 个重要的操作:

  • 开启事务
  • 提交事务
  • 回滚事务
  • 它们对应的操作命令如下:

    -- 开启事务 start transaction; -- 业务执⾏ -- 提交事务 commit; -- 回滚事务 rollback;

    Spring 编程式事务(手动操作)

    Spring ⼿动操作事务和上⾯ MySQL 操作事务类似,它也是有 3 个重要操作步骤:

  • 开启事务(获取事务)getTransaction
  • 提交事务 commit
  • 回滚事务 rollback
  • SpringBoot 内置了两个对象:

    DataSourceTransactionManager ⽤来 获取事务(开启事务)、提交或 回滚事务

    TransactionDefinition 是 事务的属性

    获取事务的时候需要将 TransactionDefinition 传递进去从⽽获得⼀个事务 TransactionStatus

    实现代码如下:

    @RestController public class UserController { @Resource private UserService userService; // 注入 JDBC 事务管理器 @Resource private DataSourceTransactionManager dataSourceTransactionManager; // 注入 定义事务属性 @Resource private TransactionDefinition transactionDefinition; @RequestMapping("/sava") public Object save(User user) { // 开启事务 TransactionStatus transactionStatus = dataSourceTransactionManager .getTransaction(transactionDefinition); // 插⼊数据库 int result = userService.save(user); // 提交事务 dataSourceTransactionManager.commit(transactionStatus); // 回滚事务 dataSourceTransactionManager.rollback(transactionStatus); return result; } }

    从上述代码可以看出,以上代码虽然可以实现事务,但操作也很繁琐,有没有更简单的实现⽅法呢?请 看下⾯声明式事务。


    Spring 声明式事务(自动事务)

    声明式事务的实现很简单,只需要在需要的⽅法上添加 @Transactional 注解就可以实现了

    ⽆需⼿动 开启事务和提交事务,进⼊⽅法时⾃动开启事务,⽅法执⾏完会⾃动提交事务,如果中途发⽣了没有处理的异常会⾃动回滚事务

    具体实现代码如下:

    @RequestMapping("/save") @Transactional //开启事务 public Object save(User user) { int result = userService.save(user); return result; }

    接下⾥使⽤以下代码,分别设置 @Transactional 注解和不设置 @Transactional

    观察它们的执⾏区别:

    image-20220713113955918

    • 开启事务时,如果代码运行时发生异常会会进行回滚
    • 没有开启事务时,如果代码运行时发生异常不会进行回滚,代码依然会进行操作

    @Transactional 作⽤范围

    @Transactional 可以⽤来修饰⽅法或类:

  • 修饰⽅法时:需要注意只能应⽤到 public ⽅法上,否则不⽣效。推荐此种⽤法。
  • 修饰类时:表明该注解对该类中所有的 public ⽅法都⽣效。

  • @Transactional 参数说明

    image-20220713153427937


    注意事项

    @Transactional 在异常被捕获的情况下,不会进⾏事务⾃动回滚。

    验证以下代码是否会发⽣事务回滚:

    @RestController public class UserController { @Resource private UserService userService; @RequestMapping("/save") @Transactional public Object save(User user) { // 插⼊数据库 int result = userService.save(user); try { // 执⾏了异常代码(0不能做除数) int i = 10 / 0; } catch (Exception e) { System.out.println(e.getMessage()); } return result; } }

    事务不会自动回滚解决⽅案

    解决⽅案1:将捕获异常重新抛出

    对于捕获的异常,事务是会⾃动回滚的

    image-20220713165842088

    因此解决⽅案1就是可以将异常重新抛出,具体实 现如下:

    @RequestMapping("/save") @Transactional(isolation = Isolation.SERIALIZABLE) public Object save(User user) { // 插⼊数据库 int result = userService.save(user); try { // 执⾏了异常代码(0不能做除数) int i = 10 / 0; } catch (Exception e) { System.out.println(e.getMessage()); throw e; // 将异常重新抛出去 } return result; }

    解决⽅案2:手动回滚事务

    在⽅法中使⽤ TransactionAspectSupport.currentTransactionStatus( ) 可 以得到当前的事务

    设置回滚⽅法 setRollbackOnly 就可以实现回滚了

    image-20220713165905990

    具体实现代码如下:

    @RequestMapping("/save") @Transactional(isolation = Isolation.SERIALIZABLE) public Object save(User user) { // 插⼊数据库 int result = userService.save(user); try { // 执⾏了异常代码(0不能做除数) int i = 10 / 0; } catch (Exception e) { System.out.println(e.getMessage()); // ⼿动回滚事务 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); } return result; }

    @Transactional ⼯作原理

    @Transactional 是基于 AOP 实现的,AOP ⼜是使⽤动态代理实现的。

    如果⽬标对象实现了接⼝,默认 情况下会采⽤ JDK 的动态代理

    如果⽬标对象没有实现了接⼝,会使⽤ CGLIB 动态代理。

    @Transactional 在开始执⾏业务之前,通过代理先开启事务,在执⾏成功之后再提交事务。如果中途遇 到的异常,则回滚事务。


    @Transactional 实现思路预览:

    image-20220713164534896

    @Transactional 具体执⾏细节如下图所示:

    image-20220713164538860


    【文章原创作者:高防cdn http://www.juniucdn.com欢迎留下您的宝贵建议】
    网友评论