一、簡介
Spring事務配置及相關說明詳見:https://www.cnblogs.com/eric-fang/p/11052304.html。這里說明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進行調用。
