版权声明:欢迎转载,标明出处 https://blog.csdn.net/mz4138/article/details/82668463
spring事物–代理的影响
本文章只讨论spring代理在事物中的影响。 列举出常见的事物失效的情况,以及如何处理
不是对spring事物传播机制的说明
接下来按两种方式讨论对事物的影响
1. 主方法被事物管理,包含事物方法
2. 主方法不被事物管理,包含事物方法
默认数据
id | title |
1 | title1 |
2 | title2 |
事务方法
普通提交与回滚
对于声明式事务的简单介绍
成功提交
@Transactional
public void normalCommit(){
Blog blogA = new Blog();
blogA.setId(1);
blogA.setTitle("normalCommit");
blogMapper.update(blogA);
}
id | title |
1 | normalCommit |
2 | title2 |
回滚
@Transactional
public void normalCommit(){
Blog blogA = new Blog();
blogA.setId(1);
blogA.setTitle("normalRollback");
blogMapper.update(blogA);
throw new RuntimeException("rollback exception");
}
id | title |
1 | title1 |
2 | title2 |
本地方法加入事物
加入回滚事物,事物回滚成功
@Transactional
@Override
public void normalGroup(){
normalRollback();
}
spring回滚边界
spring 事务管理器 默认回滚RuntimeException及其子类异常,如果不是则需要手动扩大回滚异常范围
不回滚
@Override
@Transactional
public void exceptionNotRollback() throws Exception {
Blog blogA = new Blog();
blogA.setId(1);
blogA.setTitle("exceptionNotRollback");
blogMapper.update(blogA);
throw new Exception("exception not rollback");
}
id | title |
1 | exceptionNotRollback |
2 | title2 |
回滚
@Transactional(rollbackFor = Exception.class)
@Override
public void exceptionRollback() throws Exception {
Blog blogA = new Blog();
blogA.setId(1);
blogA.setTitle("exceptionRollback");
blogMapper.update(blogA);
throw new Exception("exception not rollback");
}
id | title |
1 | title1 |
2 | title2 |
回滚部分内容
吃掉异常-全部提交
@Transactional
@Override
public void eatException() {
Blog blogA = new Blog();
blogA.setId(1);
blogA.setTitle("eat exception");
blogMapper.update(blogA);
// 吃掉异常,提交所有事务
try {
normalRoolbackB();
} catch (Exception e) {
}
}
@Transactional
public void normalRoolbackB() {
Blog blogA = new Blog();
blogA.setId(2);
blogA.setTitle("normalRoolbackB");
blogMapper.update(blogA);
throw new RuntimeException("rollback some local transaction");
}
数据内容:
id | title |
1 | eat exception |
2 | normalRoolbackB |
虽然出现了异常,但是没有回滚,而是全部提交
吃掉异常-回滚异常内容
@Transactional
@Override
public void notEatException() {
Blog blogA = new Blog();
blogA.setId(1);
blogA.setTitle("not eat exception");
blogMapper.update(blogA);
try {
// 开启事物
BlogTxServiceImpl blogTxService = (BlogTxServiceImpl) AopContext.currentProxy();
blogTxService.normalRoolbackB();
} catch (Exception e) {
// 吃掉异常,提交所有事务
}
}
通过AopContext.currentProxy()
获得当前代理对象,开启一个新的事物。
id | title |
1 | not eat exception |
2 | title2 |
非事务方法
公共调用方法:
//修改id=2的记录的title,然后抛出异常
@Transactional
public void normalRoolbackB() {
Blog blogA = new Blog();
blogA.setId(2);
blogA.setTitle("normalRoolbackB");
blogMapper.update(blogA);
throw new RuntimeException("rollback some local transaction");
}
包含事物方法-失效
@Override
public void notTxSimple() {
normalRoolbackB();
}
包含了事物,但是却没有效果。 这是用spring事物最容易迷惑的地方
id | title |
1 | title1 |
2 | normalRoolbackB |
包含事物方法-代理事物
@Override
public void notTxSimpleToSimple() {
BlogTxServiceImpl blogTxService = (BlogTxServiceImpl) AopContext.currentProxy();
blogTxService.normalRoolbackB();
}
获得代理事物,在非事物方法中开启事物
事物生效,回滚了数据
id | title |
1 | title1 |
2 | title2 |
总结
- 默认不会滚异常: RuntimeException 以及子类异常
- 本类调用时,开启独立事物需要用
AopContext.currentProxy()
获得当前代理对象,然后再去执行操作