06_Spring 事物失效

1, 事務註解的方法要用pulbic聲明, private聲明會失效
理由: CGLIB通過繼承方式實現代理類,private方法在子類不可見,自然也就無法進行事務增強

@Transactional
private void createUserPrivate(UserEntity entity) {}

2, 不能調用同類裏的事物方法. 必須通過調用事物增強的代理類 的目標方法才能生效。

事務是基於動態代理實現的, 調用類裏面的方法 self.createUserPublic() (調用的是UserService.createUserPublic()) 就得不到增強了, 必須要調用代理類的方法纔會增強(使用到事物)

  **代理類增強:  開啓事物
               目標方法
               提交事物/ 回滾事物** 
public UserService{
	public int createUserWrong2(String name) {
	try {
		this.createUserPublic(new UserEntity(name));
	} catch (Exception ex) {
		log.error("create user failed because {}", ex.getMessage());
	}
		return userRepository.findByName(name).size();
	} 
}


/
/標記了@Transactionalpublic方法
@Transactional
public void createUserPublic(UserEntity entity) {
	userRepository.save(entity);
if (entity.getName().contains("test"))
	throw new RuntimeException("invalid username!");
}

3, try…catch 處理過的異常 不會回滾

//異常無法傳播出方法,導致事務無法回滾
@Transactional
public void createUserWrong1(String name) {
try {
	userRepository.save(new UserEntity(name));
	throw new RuntimeException("error");
} catch (Exception ex) {
	log.error("create user failed", ex);
}
}

4, 受檢異常回滾 @Transactional(rollbackFor = Exception.class),默認不回滾受檢異常

有這麼一個場景:一個用戶註冊的操作,會插入一個主用戶到用戶表,還會註冊一個關聯的子用戶。我們希望將子用戶註冊的數據庫操作作爲一個獨立事務來處理,即使失敗也不會影響主流程,即不影響主用戶的註冊。

1, 子用戶創建使用開啓新事物(propagation = Propagation.REQUIRES_NEW)
2, 在創建用戶方法中 子用戶創建用try…catch處理異常

@Autowired
private UserRepository userRepository;
@Autowired
private SubUserService subUserService;

@Transactional
public void createUserWrong(UserEntity entity) {
	createMainUser(entity);
	try{
	// 子用戶創建, try..catch後出現異常, 主用戶創建不會回滾
		subUserService.createSubUserWithExceptionWrong(entity);
	}catch (Exception ex) {
	
	}
} 

private void createMainUser(UserEntity entity) {
	userRepository.save(entity);
	log.info("createMainUser finish");
}

@Service
@Slf4j
public class SubUserService {
	@Autowired
	private UserRepository userRepository;
	
	// (propagation = Propagation.REQUIRES_NEW)必須要開啓新的事務, 不然與主用戶創建在同一事務中, 會一起回滾
	@Transactional(propagation = Propagation.REQUIRES_NEW)
	public void createSubUserWithExceptionWrong(UserEntity entity) {
		log.info("createSubUserWithExceptionWrong start");
		userRepository.save(entity);
		throw new RuntimeException("invalid status");
}
}

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章