Spring事務傳播行為中可能的坑點


一、簡介

  Spring事務配置及相關說明詳見:https://www.cnblogs.com/eric-fang/p/11052304.html。這里說明spring事務的幾點注意:

  1、默認只會檢查回滾RuntimeException的異常。

  2、@Transactional注解只能作用於public的方法上,默認傳播行為 Propagation.REQUIRED

  3、service內部方法之間的調用,不會被spring攔截到,也即不會產生事務

二、坑點

  主要的坑點就是在嵌套事務上,當service內部方法之間調用的時候,很可能會產生預期之外的效果。例如下例子:

    saveUser保存用戶,如果過程出現異常,則執行saveMsg方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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進行調用。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM