MyBatisPlus+Spring实现声明式事务的方法实现
事务介绍
数据库的事务(Transaction)是一种机制、一个操作序列,包含了一组数据库操作命令。事务把所有的命令作为一个整体一起向系统提交或撤销操作请求,即这一组数据库命令要么都执行,要么都不执行,因此事务是一个不可分割的工作逻辑单元。
在数据库系统上执行并发操作时,事务是作为最小的控制单元来使用的,特别适用于多用户同时操作的数据库系统。例如,航空公司的订票系统、银行、保险公司以及证券交易系统等。
情景模拟
业务:转账业务
角色:转账方、收款方
完成事物:转账过程中出现意外时,将数据库回滚
一、新建数据库
对于精度比较高的东西,比如money,建议使用decimal类型,不要考虑float,double, 因为他们容易产生误差,numeric和decimal同义,numeric将自动转成decimal。
二、新建Spring项目
三、在pom.xml中导入依赖
导入MyBatisPlus相关依赖
<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.3.1</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency>
四、配置数据源
根据自己的情况配置
spring: datasource: driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://localhost:3306/jdbctest?useSSL=true&useUnicode=true&characterEncoding=utf-8 username: root password: 123
五、创建实体类
package demo.entity; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.math.BigDecimal; @TableName("acount") @Data @AllArgsConstructor @NoArgsConstructor public class Account { @TableId(type = IdType.AUTO) private Integer id; private String name; private BigDecimal money; }
六、创建Mapper
package demo.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import demo.entity.Account; import org.apache.ibatis.annotations.Mapper; @Mapper public interface AccountMapper extends BaseMapper<Account> { }
七、创建Service
AccountService
package demo.service; import com.baomidou.mybatisplus.extension.service.IService; import demo.entity.Account; import java.math.BigDecimal; public interface AccountService extends IService<Account> { boolean transfer(String source, String target, BigDecimal money); }
AccountServiceImpl
package demo.service.impl; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import demo.entity.Account; import demo.mapper.AccountMapper; import demo.service.AccountService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; @Service public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> implements AccountService { @Autowired private AccountMapper accountMapper; private Integer i1; private Integer i2; public boolean transfer(String source, String target, BigDecimal money) { //获取汇款方 QueryWrapper<Account> wrapper1 = new QueryWrapper<>(); wrapper1.eq("name", source); Account one1 = accountMapper.selectOne(wrapper1); QueryWrapper<Account> wrapper2 = new QueryWrapper<>(); wrapper2.eq("name", target); Account one2 = accountMapper.selectOne(wrapper2); one1.setMoney(one1.getMoney().subtract(money)); //十进制减法 i1 = accountMapper.updateById(one1); one2.setMoney(one2.getMoney().add(money)); //十进制加法 i2 = accountMapper.updateById(one2); if (i1 > 0 && i2 > 0) { return true; } return false; } }
TestController
package demo.controller; import demo.service.AccountService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.math.BigDecimal; @RestController public class TestController { @Autowired private AccountService accountService; @RequestMapping("/test") public String test(){ String result = null; boolean b = accountService.transfer("A", "B", BigDecimal.valueOf(700D)); if(b){ result = "转账成功!"; } else { result = "转账异常!"; } return result; } }
上图代码为正常的转账过程情况,我通过postman发送请求时
显示结果正常,在数据库中,
数据显示正常。
八、声明式事务的实现
通过@Transactional注解实现事务的声明
在service的实现层中,A用户转出钱后,我添加一个模拟异常 int y = 1/0
通过事务的声明,让数据库实现回滚
将数据库的中的money数据初始为1000
package com.example.mabatistransaction.Service.impl; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.example.mabatistransaction.Mapper.AccountMapper; import com.example.mabatistransaction.Service.AccountService; import com.example.mabatistransaction.entity.Account; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; @Service public class AccountServiceImpl implements AccountService { @Autowired private AccountMapper accountMapper; @Transactional @Override public boolean transferTo(String source, String target, BigDecimal money) { boolean isOK = false; //获取汇款方 QueryWrapper<Account> wrapper1 = new QueryWrapper<Account>(); wrapper1.eq("name", source); Account sourcePerson = accountMapper.selectOne(wrapper1); //获取收款方账户 QueryWrapper<Account> wrapper2 = new QueryWrapper<Account>(); wrapper2.eq("name", target); Account tatgetPerson = accountMapper.selectOne(wrapper2); //转账 //源账户取出700 sourcePerson.setMoney(sourcePerson.getMoney().subtract(money)); //进行十进制的减法 int a = accountMapper.updateById(sourcePerson); //模拟异常 int y = 1/0; //目标账户存入700 tatgetPerson.setMoney(tatgetPerson.getMoney().add(money)); //进行十进制加法 int b = accountMapper.updateById(tatgetPerson); //判断是否成功 if(a>0 && b>0){ isOK=true; } return isOK; } }
再次通过Postman发送请求
显示服务器异常,此时因为声明过事务,所以数据库的内容会回滚
但事务也有失效的场景,具体的失效场景如下图所示
到此这篇关于MyBatisPlus+Spring实现声明式事务的方法实现的文章就介绍到这了,更多相关MyBatisPlus Spring声明式事务内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
Mybatis 动态sql if 判读条件等于一个数字的案例
这篇文章主要介绍了Mybatis 动态sql if 判读条件等于一个数字的案例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧2020-11-11RestTemplate的DELETE及PUT等请求方法使用精讲
这篇文章主要为大家介绍了RestTemplate的DELETE及PUT等请求方法的使用精讲,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步2022-03-03
最新评论