一、簡介
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進行調用。