springboot 事务 抛出异常_SpringBoot 快速开启事务(附常见坑点)

本文介绍了如何在SpringBoot中快速开启事务,包括引入依赖、配置数据源、编写代码以及测试事务。重点讨论了事务回滚的规则,特别是在遇到检测异常时默认不回滚的情况,以及在业务层捕获异常后事务失效的问题。建议在使用@Transactional注解时理解其属性,避免事务管理的坑点。
摘要由CSDN通过智能技术生成

作者:yizhiwazi
链接:https://www.jianshu.com/p/380a9d980ca5

序言:此前,我们主要通过XML配置Spring来托管事务。在SpringBoot则非常简单,只需在业务层添加事务注解(@Transactional )即可快速开启事务。虽然事务很简单,但对于数据方面是需要谨慎对待的,识别常见坑点对我们开发有帮助。

1. 引入依赖

  org.springframework.boot spring-boot-starter-web org.mybatis.spring.boot mybatis-spring-boot-starter 1.3.1mysql mysql-connector-java runtimeorg.springframework.boot spring-boot-starter-test test

2. 添加配置

主要是配置数据源和开启Mybatis的自动驼峰映射

@SpringBootApplicationpublic class MybatisTransactionApplication { public static void main(String[] args) { //1.初始化 SpringApplication application= new SpringApplication(MybatisTransactionApplication.class); //2.添加数据源 Map map = new HashMap<>(); map.put("spring.datasource.url","jdbc:mysql://localhost:3306/socks?useSSL=false"); map.put("spring.datasource.username","root"); map.put("spring.datasource.password","root"); //3.开启驼峰映射 (Such as account_id ==> accountId) map.put("mybatis.configuration.map-underscore-to-camel-case",true); application.setDefaultProperties(map); //4.启动应用 application.run(args); }}

3. 添加数据库记录

打开 Navicat 的查询窗口,然后执行以下SQL:

DROP TABLE IF EXISTS `account`;CREATE TABLE `account` ( `account_id` varchar(30) , `account_name` varchar(30), `balance` decimal(20,2), PRIMARY KEY (`account_id`));insert into account values ('1','admin','1000.25');

执行完毕后,可以查询到账户数据,如图:

0edccb1e629f527e108a1f9e60574ec1.png

4. 编写代码

以操作账户金额为例,模拟正常操作金额提交事务,以及发生异常回滚事务。
其中控制层代码如下:

package com.hehe.controller;@RestControllerpublic class AccountController { @SuppressWarnings("all") @Autowired AccountService accountService; @GetMapping("/") public Account getAccount() { //查询账户 return accountService.getAccount(); } @GetMapping("/add") public Object addMoney() { try { accountService.addMoney(); } catch (Exception e) { return "发生异常了:" + accountService.getAccount(); } return getAccount(); }}

在业务层使用 @Transactional 开启事务,执行数据库操作后抛出异常。具体代码如下:

package com.hehe.service;@Servicepublic class AccountService { @SuppressWarnings("all") @Autowired AccountMapper accountMapper; public Account getAccount() { return accountMapper.getAccount(); } @Transactional public void addMoney() throws Exception { //先增加余额 accountMapper.addMoney(); //然后遇到故障 throw new RuntimeException("发生异常了.."); }}

数据库层就很简单了,我们通过注解来实现账户数据的查询,具体如下:

package com.hehe.mapper;@Mapperpublic interface AccountMapper { @Select("select * from account where account_id=1") Account getAccount(); @Update("update account set balance = balance+100 where account_id=1") void addMoney();}

其中 Account 实体对象如下:

package com.hehe.pojo;public class Account { private String accountId; private String accountName; private BigDecimal balance; // Override toString Method .. // Getter & Setters ..}

5. 测试事务

启动应用,访问 http://localhost:8080 ,可以看到账户数据,如下:

3c84d6f2b96caa47b35e35b8f2a15e56.png

然后访问 http://localhost:8080/add ,可以看到账户余额并没有增加,如下: 也就是说事务开启成功,数据得到回滚。

69df5148423818fa81c39ccc7d6b066c.png

6. 常见坑点

使用事务注解@Transactional 之前,应该先了解它的相关属性,避免在实际项目中踩中各种各样的坑点。

常见坑点1:遇到检测异常时,事务默认不回滚。

例如下面这段代码,账户余额依旧增加成功,并没有因为后面遇到SQLException(检测异常)而进行事务回滚!!

 @Transactional public void addMoney() throws Exception { //先增加余额 accountMapper.addMoney(); //然后遇到故障 throw new SQLException("发生异常了.."); }

原因分析:因为Spring的默认的事务规则是遇到运行异常(RuntimeException及其子类)和程序错误(Error)才会进行事务回滚,显然SQLException并不属于这个范围。如果想针对检测异常进行事务回滚,可以在@Transactional 注解里使用
rollbackFor 属性明确指定异常。例如下面这样,就可以正常回滚:

 @Transactional(rollbackFor = Exception.class) public void addMoney() throws Exception { //先增加余额 accountMapper.addMoney(); //然后遇到故障 throw new SQLException("发生异常了.."); }

常见坑点2: 在业务层捕捉异常后,发现事务不生效。

这是许多新手都会犯的一个错误,在业务层手工捕捉并处理了异常,你都把异常“吃”掉了,Spring自然不知道这里有错,更不会主动去回滚数据。例如:下面这段代码直接导致增加余额的事务回滚没有生效。

 @Transactional public void addMoney() throws Exception { //先增加余额 accountMapper.addMoney(); //谨慎:尽量不要在业务层捕捉异常并处理 try { throw new SQLException("发生异常了.."); } catch (Exception e) { e.printStackTrace(); } }

不要小瞧了这些细节,往前暴露异常很大程度上很能够帮我们快速定位问题,而不是经常在项目上线后出现问题,却无法刨根知道哪里报错。

推荐做法:若非实际业务要求,则在业务层统一抛出异常,然后在控制层统一处理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值