Spring事務傳播行為問題解決
這篇文章主要介紹了Spring事務傳播行為問題解決,文中通過示例程式碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
一、簡介
Spring事務配置及相關說明詳見:https://www.jb51.net/article/177710.htm。這裡說明spring事務的幾點注意:
1、預設只會檢查回滾RuntimeException的異常。
2、@Transactional註解只能作用於public的方法上,預設傳播行為 Propagation.REQUIRED
3、service內部方法之間的呼叫,不會被spring攔截到,也即不會產生事務
二、坑點
主要的坑點就是在巢狀事務上,當service內部方法之間呼叫的時候,很可能會產生預期之外的效果。例如下例子:
saveUser儲存使用者,如果過程出現異常,則執行saveMsg方法。
public class UserServiceImpl implements UserService{ @Autowired private UserDao userDao; @Autowired private MsgDao msgDao; @Autowired private MsgService msgService; @Autowired private UserService userService; @Transactional(propagation = Propagation.REQUIRED) public void saveUser(User user) throws Exception { System.out.println(user.toString()); try { userDao.saveUser(user); int i = 1/0; // saveUser2(user); } catch (Exception e) { // msgService.saveMsg(); // this.saveMsg(); userService.saveMsg(); throw new RuntimeException(); } } @Transactional(propagation = Propagation.REQUIRES_NEW) public void saveMsg() { TbMsg msg = TbMsg.builder().name("xiaocao").msg("xiaoxiao").age(27).build(); msgDao.saveMsg(msg); } }
單元測試,呼叫saveUser方法,並沒有達到想要的效果(saveUser異常,SaveMsg隔離級別是REQUIRES_NEW,理論上應該能入庫)。
失敗原因即是上面第一節中說的:同一個service中的方法呼叫,不會產生新事務。Spring 事務的管理控制,主要是通過AOP的動態代理增強來實現的,目標物件本身並沒有任何的事務管理能力,都是通過代理物件動態增強功能去實現事務管理。在同一個service中的方法呼叫,相當於是目標物件本身的this呼叫,並沒有經過代理物件,所以自然的事務配置的巢狀均無效。
解決策略:
1、saveMsg移動到另一個service中,在UserServiceImpl中匯入MsgService,saveUser中通過MsgService類去呼叫。
2、UserServiceImpl中注入自己,通過注入的自身service進行呼叫。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。