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
- Spring事務回滾情況Spring
- MySql事務無法回滾的原因有哪些MySql
- 關於Spring事務回滾的問題Spring
- ORACLE 死事務的回滾Oracle
- Spring Transaction詳解 – 手動回滾事務Spring
- Spring Data JPA中事務回滾意外RollbackExceptionSpringException
- SQL Server 事務及回滾事務SQLServer
- java 事務提交/回滾Java
- oracle檢視回滾的事務Oracle
- Spring中@Transactional事務回滾例項及原始碼Spring原始碼
- spring事務不回滾Spring
- sqlserver遇到回滾事務的操作策略SQLServer
- 【web】Spring中使用DataSourceTransactionManager手動提交或回滾事務WebSpring
- MySQL實現事務的提交和回滾MySql
- DBUNITS的單元測試事務回滾
- WebForm中C#事務回滾的例子WebORMC#
- spring事務增強,事務回滾如何判斷?希望在前端上有個提示Spring前端
- 關於事務回滾註解@Transactional
- Spring Transaction詳解 – 異常發生時的事務回滾機制Spring
- long長事務回滾的模擬與定位
- T-SQL——關於事務回滾的方式SQL
- 【Spring】一次線上@Transational事務註解未生效的原因探究Spring
- JDBC 事務(二)回滾到儲存點JDBC
- 關於ORACLE大型事務回滾的幾個點Oracle
- 在SQL SERVER中實現事務的部分回滾SQLServer
- Spring事務失效的一種原因(this呼叫)Spring
- spring boot 顯示處理事務回滾Spring Boot
- zt_Oracle事務rollback回滾時間估算Oracle
- 【spring】事務底層的實現流程Spring
- 使用FLASHBACK_TRANSACTION_QUERY查詢回滾事務SQLSQL
- 5分鐘探究Spring事務失效原因Spring
- spring 事務失效得另外原因:shiroSpring
- spring事務裡面開啟執行緒插入,報錯了是否會回滾?Spring執行緒
- spring事務失效的幾種場景以及原因Spring
- Spring Boot 事物回滾Spring Boot
- Spring的事物回滾問題Spring
- 客戶端登陸logout操作,事務回滾客戶端Go