鍍金池/ 問答/Java  數(shù)據(jù)庫/ spring service方法拋出runtimeException但不回滾

spring service方法拋出runtimeException但不回滾

定義了一個(gè)service:UserService其中有個(gè)方法定義如下:

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void saveException(User user){
    userDao.save(user);
    throw new RuntimeException("異常");
}

如果我在Controller層直接調(diào)用這個(gè)方法,是可以進(jìn)行回滾的,但如果我把這個(gè)方法再包一層,如下:


public void saveInnerException() {
    User user1 = new User();
    user1.setName("李四");
    this.saveException(user1);
}    

saveInnerException還是在同一個(gè)service中,并且這個(gè)方法沒有加事務(wù),這個(gè)時(shí)候,如果Controller層調(diào)用saveInnerException方法,事務(wù)會進(jìn)行提交,這個(gè)很奇怪,發(fā)生了異常,應(yīng)該回滾才對。
我又進(jìn)行了另外的測試,這次我重新定義了一個(gè)service:UserService2,里邊有個(gè)非事務(wù)方法,如下:

public void test(){
    User user = new User();
    user.setName("李四");
    userService.saveException(user);
}   

如果Controller調(diào)用UserService2的test方法,這時(shí)事務(wù)就會回滾了。同樣是多了一層調(diào)用,結(jié)果為什么不一樣?

回答
編輯回答
拼未來

不奇怪,
默認(rèn)Spring事務(wù)只會從public方法,并且被外部類調(diào)用時(shí)才會有效(觸發(fā)),大概原理是用了代理調(diào)用時(shí),調(diào)用前后分別執(zhí)行了對應(yīng)的事務(wù)處理邏輯。
如果是內(nèi)部調(diào)用,則無法正常的通過代理方式執(zhí)行,也即事務(wù)的相關(guān)處理沒有作用。
同樣的還有一些其他的通過代理實(shí)現(xiàn)的,如@Async

2018年6月16日 22:19
編輯回答
入她眼

問題出在saveInnerException方法里的this
你不信單步調(diào)試跟蹤下,你會發(fā)現(xiàn)this就是個(gè)普通實(shí)例而不是aop增強(qiáng)過的

2017年8月25日 14:53