程序笔记   发布时间:2022-07-19  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了关于Mysql事务,你必须知道的几个知识点!大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

transaction事务

上期我们讲到了jpa的常用操作,查询、更新、删除等,但是如果在操作数据库事务时发生异常,数据会回滚吗?下面我们来看个例子

UserController新增如下代码:

@GetMapping("save1")

public String save1(){
    User user = new User();
    user.setDptId(1L);
    user.setName("a");
    user.setAge(18L);
    user.setEmail("a@a.com");
    user.setHeadImg("headImg1");

    thiS.UserJpa.save(user);
    //模拟发生了异常
    System.out.println(1/0);
    return "ok";
}@H_944_14@

使用postman请求

localhost:8080/user/save1@H_944_14@

执行之后可以看到java后台报错了,postman前台也报出来错误,但是数据却保存进去了,数据新增了一条记录

关于Mysql事务,你必须知道的几个知识点!

说明即使发生了异常,数据还是会保存进去数据库,那应该怎么办呢?试试在save1方法上加一个@transactional的注解。

我们再执行一次。发现错误也报出来了,但是数据库并没有将新数据插入进去,最新的还是上一次的id为7的记录,那么 transactional注解是干嘛的呢?

@transactional是声明式事务管理编程中使用的注解

  1. 该注解是添加在实现类或者接口实现方法上,而不能放在接口中
  2. 需要注意的是这个注解只对public方法生效

如下是该注解的属性,我们需要关注重点关注的是rollBACk-for和propagation两个属性。

属性名说明
name 当在配置文件中有多个 transactionManager , 可以用该属性指定选择哪个事务管理器。
propagation 事务的传播行为,默认值为 requIRED。
isolation 事务的隔离度,默认值采用 DEFAULT。
timeout 事务的超时时间,默认值为-1。如果超过该时间限制但事务还没有完成,则自动回滚事务。
read-only 指定事务是否为只读事务,默认值为 false;为了忽略那些不需要事务的方法,比如读取数据,可以设置 read-only 为 true。
rollBACk-for 用于指定能够触发事务回滚的异常类型,如果有多个异常类型需要指定,各类型之间可以通过逗号分隔。
no-rollBACk- for 抛出 no-rollBACk-for 指定的异常类型,不回滚事务。

rollBACk-for:只有执行的异常才回滚。但是我们刚刚的程序并没有指定异常,那是默认的是遇到什么样的异常会回滚呢?

  1. 将userController中的代码稍作修改,手动throw new Exception("test")@H_944_14@,再执行下postman,发现@R_675_10757@了,并没有回滚。
  2. 接着我们将注解修改为@transactional(rollBACkFor = Exception.class)@H_944_14@,再执行postman,事务却回滚了,并没有提交,什么原因?
  3. spring的@transactional@H_944_14@注解可以很方便的开启事务,但是默认只在遇到运行时异常@H_944_14@和Error@H_944_14@时才会回滚,非运行时异常不回滚,即Exception@H_944_14@的子类中,除了RuntimeException@H_944_14@及其子类,其他的类默认不回滚。
  4. 而rollBACkFor属性可以解决这个问题,rollBACkFor = Exception.class@H_944_14@表示Exception@H_944_14@及其子类的异常都会触发回滚,同时不影响Error@H_944_14@的回滚。

propagation:这个用得最广的需求就是业务出错了,但是日志必须提交到数据库。怎么处理?来看下面的代码。

新增Logservice类

@service

public class Logservice {
    @resource
    private UserJpa userJpa;

    @transactional(propagation = Propagation.requIRES_NEW)
    public void saveLog(){
        User user = new User();
        user.setDptId(1L);
        user.setName("log");
        user.setAge(18L);
        user.setEmail("log@log.com");
        user.setHeadImg("log");

        thiS.UserJpa.save(user);
        System.out.println("log");
    }
}@H_944_14@

新增Userservice类:

@service

public class Userservice {
    @resource
    private UserJpa userJpa;
    @resource
    private Logservice logservice;

    @transactional(rollBACkFor = Exception.class)
    public void saveBiz() throws Exception {
        System.out.println("save2");
        User user = new User();
        user.setDptId(1L);
        user.setName("biz");
        user.setAge(18L);
        user.setEmail("biz@biz.com");
        user.setHeadImg("biz");

        thiS.UserJpa.save(user);

        //模拟保存日志
        this.logservice.saveLog();
        //模拟发生了异常
        throw new Exception("test1");
    }
}@H_944_14@

UserController新增代码

@GetMapping("save2")

public String save2() throws Exception {
    //模拟业务操作
    thiS.Userservice.saveBiz();
    return "ok";
}@H_944_14@

postman执行下,是不是只有log的那条记录插入进去了?biz的没有插入进去。

注意:同一个业务类里面 , 即使声明为 Propagation.requIRES_NEW@H_944_14@也不会新启一个事务。必须调用另一个类的Propagation.requIRES_NEW@H_944_14@方法才行。所以样例中是使用Userservice@H_944_14@里面调用另一个类Logservice@H_944_14@中的saveLog@H_944_14@的方法。

更多原创阅读:点击

大佬总结

以上是大佬教程为你收集整理的关于Mysql事务,你必须知道的几个知识点!全部内容,希望文章能够帮你解决关于Mysql事务,你必须知道的几个知识点!所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。