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

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進行調用。

相關文章
相關標籤/搜索