業務中須要sping 事物獨立的解決方案

先貼一下基礎知識,事物的七種傳播行爲

一、PROPAGATION_REQUIRED:若是當前沒有事務,就建立一個新事務,若是當前存在事務,就加入該事務,該設置是最經常使用的設置。java

二、PROPAGATION_SUPPORTS:支持當前事務,若是當前存在事務,就加入該事務,若是當前不存在事務,就以非事務執行。‘sql

三、PROPAGATION_MANDATORY:支持當前事務,若是當前存在事務,就加入該事務,若是當前不存在事務,就拋出異常。this

四、PROPAGATION_REQUIRES_NEW:建立新事務,不管當前存不存在事務,都建立新事務。spa

五、PROPAGATION_NOT_SUPPORTED:以非事務方式執行操做,若是當前存在事務,就把當前事務掛起。.net

六、PROPAGATION_NEVER:以非事務方式執行,若是當前存在事務,則拋出異常。設計

七、PROPAGATION_NESTED:若是當前存在事務,則在嵌套事務內執行。若是當前沒有事務,則執行與PROPAGATION_REQUIRED相似的操做。code

實體User,對應表t_user

@Entity
public class User {
	private Long id;
	......
}

Service 層結構以下

ServiceA中有controller直接調用的方法,insert操做 和 update操做的方法事務

@Service
public class UserServiceA {
	@Autowired
	private UserServiceB userServiceB;

	// controller層直接調用的方法
	public void operateUserMethod(User user) {
		// insert
		this.addUser(user);
		
		// update
		this.updateUser(1L);
		
		// delete
		userServiceB.deleteUser(2L);
		
	}

	public void addUser(User user) {
		......
	}
	
	public void updateUser(Long id) {
		......
	}

}

 ServiceB中,只有delete操做的方法get

@Service
public class UserServiceB {

	public void deleteUser(Long id) {
		......
	}
}

狀況一:任何@Transactional註解都不添加,那麼不管ServiceA 和 ServiceB中的方法,每個Dao操做,每條sql語句,都是一個獨立的事物it

狀況二:只在operateUserMethod(User user) 方法上加@Transactional,此Service頂層方法中調用的全部操做,都在同一事物內

狀況三:只在ServiceA中的 insert 和update方法上加@Transactional註解,controller直接調用insertUser、updateUser時,能夠作到insert 和update 事物獨立。 但當controller調用operateUserMethod(User user) 方法時,頂層方法無註解,insert 和 update的事物也不會生效

不在controller寫過多的邏輯,在Service層進行 事物分離的方案:

須要獨立的表操做,獨立到一個Service類中,Service結構設計以下:

@Service
public class UserServiceA {
	@Autowired
	private UserServiceB userServiceB;

	// controller層直接調用的方法
	public void operateUserMethod(User user) {
		// insert
		userServiceB.addUser(user);
		
		// update
		userServiceB.updateUser(1L);
		
		// delete
		userServiceB.deleteUser(2L);
		
	}
}
@Service
public class UserServiceB {

	@Transactional
	public void deleteUser(Long id) {
		......
	}
	
	@Transactional
	public void addUser(User user) {
		......
	}
	@Transactional
	public void updateUser(Long id) {
		......
	}
}

這樣 ServiceB.deleteUser() 、ServiceB.addUser()、ServiceB.updateUser() 才作到了事物分離,不一樣ServiceA中互不影響

注意:

  • 狀況三中出現的,同一Service中 頂層未加註解,調用的其餘方法上的事物註解,不生效

  • 下面這中Propagation.NESTED是在已有的事物中開啓嵌套內部事物,內部事物回滾時,回滾到外部事物的saveOption。外部事物回滾,外部事物 和 內部事物所有回滾。那commit的關係呢???

  • @Transactional(propagation = Propagation.NESTED, rollbackFor = RuntimeException.class)
相關文章
相關標籤/搜索