文章目录
- 一. 事务
- Spring中的事务实现
- 编程式事务
- 声明式事务@Transactional
- @Transactional作用
- @Transactional详解
- 1. rollbackFor
- 2. 事务隔离级别
- mysql事务隔离级别
- Spring事务隔离级别
- 3. 事务传播机制
- 什么是事务传播机制
- 事务传播机制有哪些
- Spring事务传播机制使用
- REQUIRED(加入事务)
- REQUIRES_NEW(新建事务)
- NEVER(不支持当前事务,抛异常)
- NESTED(嵌套事务)
一. 事务
Spring中的事务实现
编程式事务
提交:
@RequestMapping("/user")
@RestController
public class UserController {
//JDBC事务管理器
@Autowired
private DataSourceTransactionManager dataSourceTransactionManager;
//定义事务属性
@Autowired
private TransactionDefinition transactionDefinition;
@Autowired
private UserInfoService userInfoService;
@RequestMapping("/registry")
public String registry(String name, String password){
//开启事务
TransactionStatus transactionStatus = dataSourceTransactionManager
.getTransaction(transactionDefinition);
//用户注册
userInfoService.registryUser(name,password);
//提交事务
dataSourceTransactionManager.commit(transactionStatus);
return "注册成功";
}
}
回滚:
数据库中并没有添加
声明式事务@Transactional
添加依赖:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
</dependency>
添加注解:
@RequestMapping("/user")
@RestController
public class UserController {
@Autowired
private UserInfoService userInfoService;
@Transactional
@RequestMapping("/registry")
public String registry(String name, String password) {
userInfoService.registryUser(name, password);
return "注册成功";
}
抛出异常:
事务回滚, 没有提交, 数据库没有添加数据
@Transactional作用
异常被捕获住:
会提交
如果想要异常被捕获了, 但是事务依然回滚, 有两种方式:
- 重新抛出异常
- 手动回滚事务
@Transactional详解
1. rollbackFor
@Transactional默认只在遇到运行时异常RuntimeException和Error时才会回滚, 非运行时异常不回滚
如果我们需要让所有异常都回滚, 需要配置@Transactional注解中的rollbackFor属性, 通过rollbackFor这个属性指定出现何种异常类型时事务进行回滚
2. 事务隔离级别
mysql事务隔离级别
Spring事务隔离级别
Spring事务隔离级别可以通过@Transactional中的isolation属性进行设置
3. 事务传播机制
什么是事务传播机制
事务传播机制就是:多个事务⽅法存在调⽤关系时,事务是如何在这些⽅法间进⾏传播的
事务隔离级别是解决多个书屋同时调用一个数据库的问题
事务传播机制解决的是一个事务在多个节点(方法)中的传递问题
事务传播机制有哪些
@Transactinal注解致辞书屋传播是指的设置, 通过propagation属性来指定传播行为
Spring事务传播机制使用
REQUIRED(加入事务)
@RestController
@RequestMapping("/propaga")
public class PropagationController {
@Autowired
private UserInfoService userInfoService;
@Autowired
private LogInfoService logInfoService;
@RequestMapping("/r1")
@Transactional(propagation = Propagation.REQUIRED)
public String r1(String name, String password){
//用户注册
userInfoService.registryUser(name, password);
//记录操作日志
logInfoService.insertLog(name, "用户注册");
return "r1";
}
}
@Service
public class UserInfoService {
@Autowired
private UserInfoMapper userInfoMapper;
@Transactional(propagation = Propagation.REQUIRED)
public void registryUser(String name, String password){
userInfoMapper.insert(name, password);
}
}
@Service
public class LogInfoService {
@Autowired
private LogInfoMapper logInfoMapper;
@Transactional(propagation = Propagation.REQUIRED)
public void insertLog(String name, String op){
//出现异常
int a = 10/0;
logInfoMapper.insertLog(name,op);
}
}
只创建了一个事务, 并且事务并没有提交, 数据库中也没有更新数据
流程描述:
- r1⽅法开始事务
- ⽤⼾注册,插⼊⼀条数据(执⾏成功)(和r1使⽤同⼀个事务)
- 记录操作⽇志,插⼊⼀条数据(出现异常,执⾏失败)(和r1使⽤同⼀个事务)
- 因为步骤3出现异常,事务回滚.步骤2和3使⽤同⼀个事务,所以步骤2的数据也回滚了
REQUIRES_NEW(新建事务)
将事务传播机制改成Propagation.REQUIRES_NEW
用户数据插入成功, 日志表数据发生异常, 插入失败
NEVER(不支持当前事务,抛异常)
程序执行报错
NESTED(嵌套事务)
r1事务可以认为是⽗事务,嵌套事务是⼦事务.⽗事务出现异常,⼦事务也会回滚,⼦事务出现异常,如
果不进⾏处理,也会导致⽗事务回滚
NESTED和REQUIRED的区别
在LogInfoService中进行捕获异常, 并进行当前事务回滚
发现 用户表提交成功, 但是日志表提交失败
由于LogInfoService已经捕获了异常, 所以不会导致r1父事务回滚, r1正常提交