1. 程式人生 > 程式設計 >Spring事務傳播行為問題解決

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進行呼叫。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。