springboot开启事务和mysql的事务的关系

事务的理解

注解 开启事务的方式
启动类 增加 @enableTransactionManagement
在想要开启事务的方法上面增加 @Transactional
事务其实就是针对数据库的操作,也就是在一个数据库当中开启一个事务后,该事务遵从acid的原则、存在四种隔离级别(存在事务的传播性,这个是在框架整合mysql应用当中的需求)。
今天这篇文章主要是针对 原子性 即要么操作全部成功(提交)要么全部失败(回撤)的介绍,通常文章在讲事务的时候,只是根据框架本身来解释,本篇文章结合了,事务在数据库中的表现来讲解。下面以mysql为例。

事务在mysql中的表现

在这里插入图片描述
上图是在mysql当中去开启一个事务,begin之后,就开启了一个线程,直到去执行commit;该事务将一直存在。

并且在该事务提交之前,其他事务是没法看到本次事务的所有操作的。因为mysql的隔离级别是可重复读的级别。而如果在该事务提交之前,执行rollback操作,则把之前所有的操作全部取消,如下图:
在这里插入图片描述
可以看到rollback之后,重新执行查找操作,之前的修改和插入操作都取消了。
在这里插入图片描述
commit 之后所有的操作都执行成功 完成持久化。

事务在spring框架中的体现

当然了,刚才在mysql中开启事务,只是一个实例,在实际的开发过程中,是不会用到的。而是是要在spring整合mysql过程中,结合具体的业务来做事务的开启、回撤、提交,当然了此时也存在传播性的。

以下做具体介绍

网上大部分的过于spring开启事务的实例都是在 serviceImp当中的方法去开启的,但是其实放在哪个方法都可以,所以本篇文章把线程的开启放在controller的方法当中。在这里插入图片描述

这里做一下解释为什么之前要介绍mysql当中如何开启和结束事务,又为什么这里要把开启事务的注解不放在常规的serviceImp上面而是放在controller 的方法上面?

主要是想向广大读者解释,事务的本质到底是什么,本质上一个事务是:
1、应用跟数据库的一个连接,该连接就是给数据库一个指令,就是begin指令,让一个事务在mysql当中开启。
2、无论开始事务的注解指令(@Transactional)放在哪里,该方法下的所有跟数据库交互的sql执行,都是在一个事务当中的,(当然除非有新的传播隔离出现,这里先不讨论这种情况),直到该方法执行完毕,该事务就被提交。

事务demo的解析,结合mysql事务

还是用我的一个简单demo来分析事务,首先我把@Transactional放在了controller的某个方法上,那么根据上面的理论,该方法里面所有的操作都是在一个事务当中的,直到该方法被执行完毕,则自动commit。
先把所有的跟数据库交互找到:
在这里插入图片描述

在这里插入图片描述
![在这里插入图片描述](https://img-blog.csdnimg.cn/56fab2df015c4b829f30f373ce6e46ac.png忽略所有的查找语句,就盯着增删改语句,会发现一共有三条sql,分别是
update sys_user set username= ‘1234’ where user_id=4;在这里插入图片描述

update sys_user set username= ‘12’ where user_id=2;
update sys_user set username= ‘11111111111111111111111’ where user_id=1;

因为事务说到底是跟数据库的交互,所以这里要在mysql中开启线程来把该方法的sql演绎出来,如下图:

在这里插入图片描述
事务当中的sql语句是根据 事务开启的方法的自然顺序执行下来的,可以看到最后一条语句,由于设置的value的长度已经超过该字段的最大长度,所以发生了运行时异常报错。根据事务的原则,一个事务要么全部成功要么全部失败,所以这里报错之后,会给mysql一个rollback操作,随后该事务就直接执行commit,本事务就完全结束了。
在这里插入图片描述

至此一个事务在mysql当中的完整执行就结束了,总结一下就是出现异常就会rollback,随后直接commit。没有异常就是正常的 commit。

事务何时需要rollback

那么根据上述实例,在实际的开发当中,我们需要把握rollback的时机,才能保证事务按照我们业务的要求来执行。
1、首先 默认只在遇到运行时异常和Error时才会回滚rollback,当然运行时异常,RuntimeException是一个大类,具体的异常分类如下图:
在这里插入图片描述
先回忆下java的异常模型,Throwable是最顶层的父类,有Error和Exception两个子类。
Error表示严重的错误(如OOM等);
Exception可以分为运行时异常(RuntimeException及其子类)和非运行时异常(Exception的子类中,除了RuntimeException及其子类之外的类)。

非运行时异常是检查异常(checked exceptions),一定要try catch,因为这类异常是可预料的,编译阶段就检查的出来;
Error和运行时异常是非检查异常(unchecked exceptions),不需要try catch,因为这类异常是不可预料的,编辑阶段不会检查,没必要检查,也检查不出来。

下面的demo是对 抛出非运行时异常 事务不会回滚的示例:
在这里插入图片描述
在这里插入图片描述

可以根据理论得出结论,由于捕获到的异常是IOException,所以除了执行失败的最后一条sql之外,其余两条的sql都执行成功,完成了持久化(上面的图给错了,应该是要抛出IOException)。

可以看到,只有在发生RuntimeException 或者其下面的子类的异常的时候才会发生rollback,那如果发生了其他的非运行时异常怎么办呢?解决方法如下图:
在这里插入图片描述
在@Transational 增加限制rollbackFor = Exception.class ,此时Exception下面所有的异常,即运行时异常和非运行时异常的抛出都会进行回滚。

事务的传播

刚才我们一直是在一个事务同一个传播级别下执行的三条sql,还是利用刚才的demo,因为抛出了异常,所以会导致整个事务回滚,也就是所有的sql执行都无效。那么如果在实际的业务中,某个sql不依赖其他sql是否执行成功的话,那么就需要设置新的隔离级别了。

我们这时候给在第一条sql执行之前设置 REQUIRES_NEW的隔离级别,也就是无论之前的方法是否存在事务我都开启一个新的事务来执行,如下图:
在这里插入图片描述
此时,虽然第三条sql语句的执行抛出异常,但是因为第一条sql语句的执行被分配到了新的事务当中,所以第一条sql执行成功,当然后两条依然会回滚。

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot开启MySQL事务可以通过以下步骤实现: 1. 首先,在你的Spring Boot应用的配置文件(如application.properties或application.yml)中添加MySQL数据库的连接信息,包括数据库URL、用户名和密码。 2. 创建一个标注了`@Transactional`注解的方法或类。这个注解可以应用在方法级别或类级别,用于开启事务。当方法或类上标注了`@Transactional`注解时,Spring会自动管理这些方法或类的事务。 3. 在需要开启事务的方法中,可以使用各种数据库操作的注解(如`@Insert`、`@Update`、`@Delete`等),或者使用JdbcTemplate进行数据库操作。 4. 在执行数据库操作的方法上,如果抛出了异常,Spring会自动回滚事务。如果方法执行成功,则事务会被提交。 下面是一个示例代码: ```java @Service public class UserService { @Autowired private JdbcTemplate jdbcTemplate; @Transactional public void createUser(String username, String password) { // 执行数据库操作,插入用户信息 jdbcTemplate.update("INSERT INTO user(username, password) VALUES (?, ?)", username, password); } } ``` 在上述示例中,通过`@Transactional`注解标注了`createUser`方法,该方法会在插入用户信息时开启事务。如果插入过程中出现异常,事务会被回滚,保证数据的一致性。 需要注意的是,为了使用事务管理,你需要在Spring Boot应用的依赖中添加`spring-boot-starter-data-jpa`或`spring-boot-starter-jdbc`等相关依赖。同时,确保在配置文件中正确配置了MySQL数据库连接信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值