MyBatisPlus+Spring實(shí)現(xiàn)聲明式事務(wù)的方法實(shí)現(xiàn)
事務(wù)介紹
數(shù)據(jù)庫的事務(wù)(Transaction)是一種機(jī)制、一個操作序列,包含了一組數(shù)據(jù)庫操作命令。事務(wù)把所有的命令作為一個整體一起向系統(tǒng)提交或撤銷操作請求,即這一組數(shù)據(jù)庫命令要么都執(zhí)行,要么都不執(zhí)行,因此事務(wù)是一個不可分割的工作邏輯單元。
在數(shù)據(jù)庫系統(tǒng)上執(zhí)行并發(fā)操作時,事務(wù)是作為最小的控制單元來使用的,特別適用于多用戶同時操作的數(shù)據(jù)庫系統(tǒng)。例如,航空公司的訂票系統(tǒng)、銀行、保險公司以及證券交易系統(tǒng)等。
情景模擬
業(yè)務(wù):轉(zhuǎn)賬業(yè)務(wù)
角色:轉(zhuǎn)賬方、收款方
完成事物:轉(zhuǎn)賬過程中出現(xiàn)意外時,將數(shù)據(jù)庫回滾
一、新建數(shù)據(jù)庫
對于精度比較高的東西,比如money,建議使用decimal類型,不要考慮float,double, 因?yàn)樗麄內(nèi)菀桩a(chǎn)生誤差,numeric和decimal同義,numeric將自動轉(zhuǎn)成decimal。
二、新建Spring項(xiàng)目
三、在pom.xml中導(dǎo)入依賴
導(dǎo)入MyBatisPlus相關(guān)依賴
<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>
四、配置數(shù)據(jù)源
根據(jù)自己的情況配置
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
五、創(chuàng)建實(shí)體類
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; }
六、創(chuàng)建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> { }
七、創(chuàng)建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)); //十進(jìn)制減法 i1 = accountMapper.updateById(one1); one2.setMoney(one2.getMoney().add(money)); //十進(jìn)制加法 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 = "轉(zhuǎn)賬成功!"; } else { result = "轉(zhuǎn)賬異常!"; } return result; } }
上圖代碼為正常的轉(zhuǎn)賬過程情況,我通過postman發(fā)送請求時
顯示結(jié)果正常,在數(shù)據(jù)庫中,
數(shù)據(jù)顯示正常。
八、聲明式事務(wù)的實(shí)現(xiàn)
通過@Transactional注解實(shí)現(xiàn)事務(wù)的聲明
在service的實(shí)現(xiàn)層中,A用戶轉(zhuǎn)出錢后,我添加一個模擬異常 int y = 1/0
通過事務(wù)的聲明,讓數(shù)據(jù)庫實(shí)現(xiàn)回滾
將數(shù)據(jù)庫的中的money數(shù)據(jù)初始為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); //轉(zhuǎn)賬 //源賬戶取出700 sourcePerson.setMoney(sourcePerson.getMoney().subtract(money)); //進(jìn)行十進(jìn)制的減法 int a = accountMapper.updateById(sourcePerson); //模擬異常 int y = 1/0; //目標(biāo)賬戶存入700 tatgetPerson.setMoney(tatgetPerson.getMoney().add(money)); //進(jìn)行十進(jìn)制加法 int b = accountMapper.updateById(tatgetPerson); //判斷是否成功 if(a>0 && b>0){ isOK=true; } return isOK; } }
再次通過Postman發(fā)送請求
顯示服務(wù)器異常,此時因?yàn)槁暶鬟^事務(wù),所以數(shù)據(jù)庫的內(nèi)容會回滾
但事務(wù)也有失效的場景,具體的失效場景如下圖所示
到此這篇關(guān)于MyBatisPlus+Spring實(shí)現(xiàn)聲明式事務(wù)的方法實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)MyBatisPlus Spring聲明式事務(wù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
spring boot啟動出現(xiàn)Unable to start ServletWe
在使用SpringBoot時,啟動報錯可能源于多種原因,錯誤提示為缺少ServletWebServerFactory bean,初步分析可能是缺少spring-boot-starter-web依賴或@EnableAutoConfiguration注解,感興趣的可以了解一下2024-10-10Java中實(shí)現(xiàn)List分隔成子List詳解
大家好,本篇文章主要講的是Java中實(shí)現(xiàn)List分隔成子List詳解,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下2022-01-01Springboot啟動后立即某個執(zhí)行方法的四種方式
spring項(xiàng)目如何在啟動項(xiàng)目是執(zhí)行一些操作,在spring中能通過那些操作實(shí)現(xiàn)這個功能呢,下面這篇文章主要給大家介紹了關(guān)于Springboot啟動后立即某個執(zhí)行方法的四種方式,需要的朋友可以參考下2022-06-06Java實(shí)現(xiàn)九宮格的簡單實(shí)例
這篇文章主要介紹了 Java實(shí)現(xiàn)九宮格的簡單實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-06-06深入理解happens-before和as-if-serial語義
本文大部分整理自《Java并發(fā)編程的藝術(shù)》,溫故而知新,加深對基礎(chǔ)的理解程度。下面可以和小編來一起學(xué)習(xí)下2019-05-05詳解mybatis批量插入10萬條數(shù)據(jù)的優(yōu)化過程
這篇文章主要介紹了詳解mybatis批量插入10萬條數(shù)據(jù)的優(yōu)化過程,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04