Spring事務不能回滾的深層次原因
開頭總述
Spring在同一個類中呼叫function,事務會失效。
Spring事務是基於AOP代理來實現的。而AOP是使用JDK動態代理來實現的。
例如:
/**
* 父類呼叫子類
* 子類失敗,不能影響父類
*
* 預期效果:child回滾,parent插入成功
* 第一次試驗 真實效果:都插入成功,child方法因為try catch導致事務未起作用。
*/
第一次試驗
@Override
@Transactional
public void insertParent(){
try {
insertChild();
} catch (Exception e) {
// TODO: handle exception
}
user.setName("parent_5");
user.setAge((byte)1);
userMapper.insertSelective(user);
}
@Override
@Transactional(propagation=Propagation.REQUIRES_NEW)
public void insertChild(){
user.setName("child_5");
user.setAge((byte)1);
userMapper.insertSelective(user);
int i=1/0;
}
執行結果
原因分析
child方法被try catch住了,同時事務未生效。
Spring事務不能回滾,根源是類內部呼叫是不走代理物件Proxy的。this.child走的是真實物件(真實物件)。導致child上的事務無效,先執行insert語句,執行成功以後才丟擲異常。異常被parent中的try catch捕獲到。不影響parent方法的執行。
第二次試驗
@Override
@Transactional
public void insertParent(){
user.setName("parent_7");
user.setAge((byte)1);
userMapper.insertSelective(user);
insertChild();
}
@Override
@Transactional(propagation=Propagation.REQUIRES_NEW)
public void insertChild(){
user.setName("child_7");
user.setAge((byte)1);
userMapper.insertSelective(user);
int i=1/0;
}
執行結果
原因分析
去掉try catch,child方法丟擲異常,導致回滾。同時異常向上拋,導致parent方法也回滾。
child方法的事務失效,相當於child方法中的code挪到了parent方法中,也類似於在parent中丟擲異常。
解決方案
AOP需要先暴露出來。
<!-- 開啟切面-->
<!-- 暴露AOP代理到ThreadLocal -->
<aop:aspectj-autoproxy expose-proxy="true"></aop:aspectj-autoproxy>
獲取AOP代理需要從AOP的上下文來獲取。得到當前AopProxy,然後通過AOP代理來呼叫child方法。
@Override
@Transactional
public void insertParent(){
try {
/**
* AopContext.currentProxy()就類似於JDK代理中的
* Proxy.newInstance得到的Proxy物件
* UserService proxy=(UserService) AopContext.currentProxy();
* proxy.insertChild();
*/
((UserService)AopContext.currentProxy()).insertChild();
} catch (Exception e) {
// TODO: handle exception
}
user.setName("parent_7");
user.setAge((byte)1);
userMapper.insertSelective(user);
}
@Override
@Transactional(propagation=Propagation.REQUIRES_NEW)
public void insertChild(){
user.setName("child_7");
user.setAge((byte)1);
userMapper.insertSelective(user);
int i=1/0;
}
執行結果
相關文章
- 不能回滾的Redis事務還能用嗎Redis
- MySql事務無法回滾的原因有哪些MySql
- Spring Data JPA中事務回滾意外RollbackExceptionSpringException
- sqlserver遇到回滾事務的操作策略SQLServer
- spring事務增強,事務回滾如何判斷?希望在前端上有個提示Spring前端
- MySQL實現事務的提交和回滾MySql
- 關於事務回滾註解@Transactional
- T-SQL——關於事務回滾的方式SQL
- Spring事務失效的一種原因(this呼叫)Spring
- spring boot 顯示處理事務回滾Spring Boot
- 關於ORACLE大型事務回滾的幾個點Oracle
- spring 事務失效得另外原因:shiroSpring
- 【spring】事務底層的實現流程Spring
- Spring Boot 事物回滾Spring Boot
- 客戶端登陸logout操作,事務回滾客戶端Go
- Spring的事物回滾問題Spring
- spring事務裡面開啟執行緒插入,報錯了是否會回滾?Spring執行緒
- 5分鐘探究Spring事務失效原因Spring
- spring事務失效的幾種場景以及原因Spring
- openGauss 子事務併發回滾流程最佳化
- 命令(XA ROLLBACK) 讓儲存叢集回滾GT 的事務分支
- Spring IOC 原理深層解析Spring
- Spring宣告式事務純xml模式回顧SpringXML模式
- Oracle vs PostgreSQL,研發注意事項(3)- 事務回滾之UPDATE操作解析OracleSQL
- 發現深層次的bug——業務測試 1、業務測試簡介
- 為什麼catch了異常,但事務還是回滾了?
- 日常Bug排查-應用Commit報錯事務並沒有回滾MIT
- Springboot事務失效原因Spring Boot
- Spring的事務管理Spring
- spring事務Spring
- Spring 事務Spring
- Spring事務專題(四)Spring中事務的使用、抽象機制及模擬Spring事務實現Spring抽象
- spring原始碼解析 (七) 事務底層原始碼實現Spring原始碼
- Spring的事務管理(二)宣告式事務管理Spring
- Spring 中的事務管理Spring
- 聊聊spring事務的propagationSpring
- spring事務的傳播Spring
- Spring 事務管理Spring