共计 4364 个字符,预计需要花费 11 分钟才能阅读完成。
本文源码
GitHub 地址:知了一笑
https://github.com/cicadasmile/spring-boot-base
一、事务管理简介
1、事务基本概念
一组业务操作 ABCD,要么全部成功,要么全部不成功。
2、特性:ACID
原子性:整体
一致性:完成
隔离性:并发
持久性:结果
3、隔离问题
脏读:一个事务读到另一个事务没有提交的数据
不可重复读:一个事务读到另一个事务已提交的数据(update)
虚读(幻读):一个事务读到另一个事务已提交的数据(insert)
4、隔离级别
read uncommitted:读未提交。
read committed:读已提交。解决脏读。
repeatable read:可重复读。解决:脏读、不可重复读。
serializable:串行化。都解决,单事务。
二、Spring 管理事务
1、顶级接口
1)PlatformTransactionManager
平台事务管理器,spring 要管理事务,必须使用事务管理器进行事务配置时,必须配置事务管理器。
2)TransactionDefinition
事务详情(事务定义、事务属性),spring 用于确定事务具体详情,
例如:隔离级别、是否只读、超时时间 等
进行事务配置时,必须配置详情。spring 将配置项封装到该对象实例。
3)TransactionStatus
事务状态,spring 用于记录当前事务运行状态。例如:是否有保存点,事务是否完成。
spring 底层根据状态进行相应操作。
2、事务状态
3、事务定义
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
正文完
发表至:无分类
2019-07-17