SpringBoot 2.0 基础案例(十二):基于转账案例,演示事务管理操作

一、事务管理简介 

1、基本概念

一组业务操作ABCD,要么全部成功,要么全部不成功。

2、特性:ACID

原子性:整体

一致性:完成

隔离性:并发

持久性:结果

3、隔离问题

脏读:一个事务读到另一个事务没有提交的数据

不可重复读:一个事务读到另一个事务已提交的数据(update

虚读(幻读):一个事务读到另一个事务已提交的数据(insert)

4、隔离级别

read uncommitted:读未提交。

read committed:读已提交。解决脏读。

repeatable read:可重复读。解决:脏读、不可重复读。

serializable :串行化。都解决,单事务。

二、Spring管理事务 

1、顶级接口

SpringBoot 2.0 基础案例(十二):基于转账案例,演示事务管理操作

1)PlatformTransactionManager

平台事务管理器,spring要管理事务,必须使用事务管理器进行事务配置时,必须配置事务管理器。

2)TransactionDefinition

事务详情(事务定义、事务属性),spring用于确定事务具体详情,

例如:隔离级别、是否只读、超时时间

进行事务配置时,必须配置详情。spring将配置项封装到该对象实例

3)TransactionStatus

事务状态,spring用于记录当前事务运行状态。例如:是否有保存点,事务是否完成。

spring底层根据状态进行相应操作。

2、事务状态

SpringBoot 2.0 基础案例(十二):基于转账案例,演示事务管理操作

3、事务定义

SpringBoot 2.0 基础案例(十二):基于转账案例,演示事务管理操作

PROPAGATION_REQUIRED , required , 必须  【默认值】
支持当前事务,A如果有事务,B将使用该事务。
如果A没有事务,B将创建一个新的事务。
PROPAGATION_SUPPORTS ,supports ,支持
支持当前事务,A如果有事务,B将使用该事务。
如果A没有事务,B将以非事务执行。
PROPAGATION_MANDATORY,mandatory ,强制
支持当前事务,A如果有事务,B将使用该事务。
如果A没有事务,B将抛异常。
PROPAGATION_REQUIRES_NEW , requires_new ,必须新的
如果A有事务,将A的事务挂起,B创建一个新的事务
如果A没有事务,B创建一个新的事务
PROPAGATION_NOT_SUPPORTED ,not_supported ,不支持
如果A有事务,将A的事务挂起,B将以非事务执行
如果A没有事务,B将以非事务执行
PROPAGATION_NEVER ,never,从不
如果A有事务,B将抛异常
如果A没有事务,B将以非事务执行
PROPAGATION_NESTED ,nested ,嵌套
A和B底层采用保存点机制,形成嵌套事务。
掌握:PROPAGATION_REQUIRED、PROPAGATION_REQUIRES_NEW、PROPAGATION_NESTED

三、SpringBoot2.0管理事务 

基于转账的案例演示,基于druid连接池配置。druid连接池在文章如下。

SpringBoot2.0 基础案例(07):集成Druid连接池,配置监控界面

1、新建转账表

CREATE TABLE account(
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50),
money INT
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO account(username,money) VALUES('jack','10000');
INSERT INTO account(username,money) VALUES('rose','10000');
SELECT * FROM account;

2、基于事务手动管理器

该配置用于测试事务的手动管理。

/**
* 事物管理器
*/

@Bean(name = "transactionManager")
public PlatformTransactionManager transactionManager (DruidDataSource dataSource){
LOGGER.info("【transactionManager 初始化...】");
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
transactionManager.setDataSource(dataSource);
return transactionManager;
}
/**
* 创建事物手动管理模板
*/

@Bean(name = "transactionTemplate")
public TransactionTemplate transactionTemplate(PlatformTransactionManager transactionManager)
LOGGER.info("【transactionTemplate 初始化...】")
;
TransactionTemplate transactionTemplate = new TransactionTemplate() ;
transactionTemplate.setTransactionManager(transactionManager);
return transactionTemplate;
}

3、封装转账接口

接口方法

public interface AccountService {
/**
* 汇款
*/

void out (String outer , Integer money);
/**
* 收款
*/

void in (String inner , Integer money);
}

接口实现

@Service
public class AccountServiceImpl implements AccountService {
@Resource
private JdbcTemplate jdbcTemplate ;
public void out(String outer, Integer money) {
String sql = "update account set money = money - ? where username = ?";
jdbcTemplate.update(sql, money,outer);
}
public void in(String inner, Integer money) {
String sql = "update account set money = money + ? where username = ?";
jdbcTemplate.update(sql, money,inner);
}
}

4、封装三个测试接口

测试接口

public interface TradeService {
/**
* 转账交易:没有事务管理
*/

void trade1(String outer ,String inner ,Integer money);
/**
* 转账交易:手动管理事务
*/

void trade2(String outer ,String inner ,Integer money);
/**
* 转账交易:注解管理事务
*/

void trade3(String outer ,String inner ,Integer money);
}

接口实现

@Service
public class TradeServiceImpl implements TradeService {

@Resource
private AccountService accountService ;
@Resource
private TransactionTemplate transactionTemplate ;

@Override
public void trade1(String outer, String inner, Integer money) {
accountService.out(outer, money);
// 抛出异常
int i = 1/0;
accountService.in(inner, money);
}

@Override
public void trade2(String outer, String inner, Integer money) {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
public void doInTransactionWithoutResult(TransactionStatus arg0) {
accountService.out(outer, money);
// 抛出异常
int i = 1/0;
accountService.in(inner, money);
}
});
}

@Transactional(value="transactionManager",propagation= Propagation.REQUIRED)
@Override
public void trade3(String outer, String inner, Integer money) {
accountService.out(outer, money);
// 抛出异常
int i = 1/0;
accountService.in(inner, money);
}
}

5、编写测试类

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = TransactionApplication.class)
public class TradeTest {
@Resource
private TradeService tradeService ;
/**
* 没有事务管理
* jack 减少了1000块钱,但是rose没得到1000块钱
* 1 jack 9000
* 2 rose 10000
*/

@Test
public void testTrade1 (){
tradeService.trade1("jack", "rose", 1000);
}
/**
* 手动管理事务
* 1 jack 10000
* 2 rose 10000
*/

@Test
public void testTrade2 (){
tradeService.trade2("jack", "rose", 1000);
}
/**
* 注解管理事务
* 1 jack 10000
* 2 rose 10000
*/

@Test
public void testTrade3 (){
tradeService.trade3("jack", "rose", 1000);
}
}

四、源代码地址 

GitHub地址:知了一笑
https://github.com/cicadasmile/spring-boot-base
地址:知了一笑
https://gitee.com/cicadasmile/spring-boot-base

SpringBoot 2.0 基础案例(十二):基于转账案例,演示事务管理操作

原文 

https://mp.weixin.qq.com/s?__biz=MzU4Njg0MzYwNw==&mid=2247483858&idx=1&sn=30cf36583725d1f59f4c8b8efb2a79d1&chksm=fdf4556aca83dc7ca84d70ab7754a9e1ca0cdbdb97dac75b77d78e0f124e9c0ebadf5a72ba56&token=90298312&lang=zh_CN

本站部分文章源于互联网,本着传播知识、有益学习和研究的目的进行的转载,为网友免费提供。如有著作权人或出版方提出异议,本站将立即删除。如果您对文章转载有任何疑问请告之我们,以便我们及时纠正。

PS:推荐一个微信公众号: askHarries 或者qq群:474807195,里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

转载请注明原文出处:Harries Blog™ » SpringBoot 2.0 基础案例(十二):基于转账案例,演示事务管理操作

赞 (0)
分享到:更多 ()

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址