1、簡介javascript
Spring事務配置及相關說明詳見:http://www.javashuo.com/article/p-qlpxeono-kh.html。這裏說明spring事務的幾點注意:html
一、默認只會檢查回滾RuntimeException的異常。java
二、@Transactional註解只能做用於public的方法上,默認傳播行爲 Propagation.REQUIREDspring
三、service內部方法之間的調用,不會被spring攔截到,也即不會產生事務單元測試
2、坑點測試
主要的坑點就是在嵌套事務上,當service內部方法之間調用的時候,極可能會產生預期以外的效果。例以下例子:ui
saveUser保存用戶,若是過程出現異常,則執行saveMsg方法。this
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調用,並無通過代理對象,因此天然的事務配置的嵌套均無效。htm
解決策略:
一、saveMsg移動到另外一個service中,在UserServiceImpl中導入MsgService,saveUser中經過MsgService類去調用。
二、UserServiceImpl中注入本身,經過注入的自身service進行調用。