Spring事務(wù)
Spring事務(wù)管理
注解
- 注解:
@Transactional - 位置: 業(yè)務(wù)(service)層的方法上、類上、接口上,而不是業(yè)務(wù)層的實現(xiàn)類
- 作用: 將當(dāng)前方法交給spring進行事務(wù)管理,方法執(zhí)行前,開啟事務(wù);成功執(zhí)行完畢,提交事務(wù);出現(xiàn)異常,回滾事務(wù)
代碼實踐
@Transactional
@Override
public void delete(Integer id) {
//1. 刪除部門
deptMapper.delete(id);
int i = 1/0; //模擬拋出異常
//2. 根據(jù)部門id,刪除部門下的員工信息
empMapper.deleteByDeptId(id);
}
// 部門接口類
@Transactional
public interface DeptService {
// CODE...
}
// 部門接口實現(xiàn)類
@Transactional
@Service
public class DeptServiceImpl implements DeptService {
// CODE...
}
Spring中配置開啟事務(wù)管理日志,開啟之后可以在調(diào)試窗口看到事務(wù)
# 開啟事務(wù)管理日志
logging:
level:
org.springframework.jdbc.support.JdbcTransactionManager: debug
事務(wù)角色
事務(wù)管理員:發(fā)起事務(wù)時,在Spring中通常指代業(yè)務(wù)層開啟事務(wù)的方法,負(fù)責(zé)發(fā)起事務(wù),決定事務(wù)的開始與提交/回滾
事務(wù)協(xié)調(diào)員:加入事務(wù)后,在Spring中通常指代數(shù)據(jù)層方法,也可以是業(yè)務(wù)層方法,負(fù)責(zé)參與已有事務(wù),在事務(wù)中執(zhí)行具體的數(shù)據(jù)庫操作或業(yè)務(wù)邏輯。
| 角色 | 含義 | 在 Spring 中的對應(yīng) | 舉例 |
|---|---|---|---|
| 事務(wù)管理員(Transaction Initiator) | 負(fù)責(zé)發(fā)起事務(wù),決定事務(wù)的開始與提交/回滾。 | 通常指 業(yè)務(wù)層方法(Service 層) 上聲明了 @Transactional 且事務(wù)傳播行為為 REQUIRED(默認(rèn))。 |
UserService.saveUser() 開啟事務(wù),調(diào)用 DAO 層操作。 |
| 事務(wù)協(xié)調(diào)員(Transaction Participant) | 負(fù)責(zé)參與已有事務(wù),在事務(wù)中執(zhí)行具體的數(shù)據(jù)庫操作或業(yè)務(wù)邏輯。 | 通常是 數(shù)據(jù)訪問層(DAO 層) 或其他 被同一事務(wù)包裹的業(yè)務(wù)方法。 這些方法通常也是 @Transactional(propagation = REQUIRED) 或 SUPPORTS,從而加入現(xiàn)有事務(wù)。 |
UserRepository.insert() 在已有事務(wù)中執(zhí)行 SQL,不單獨提交。 |
示例代碼:
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
@Autowired
private LogService logService;
@Transactional // 事務(wù)管理員
public void registerUser(User user) {
userRepository.save(user); // 事務(wù)協(xié)調(diào)員
logService.logRegistration(user); // 若 logService 使用 REQUIRED,也為協(xié)調(diào)員
}
}
@Service
public class LogService {
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void logRegistration(User user) {
// 新事務(wù),成為自己的事務(wù)管理員
// 不影響外層 registerUser() 的事務(wù)
}
}
事務(wù)屬性--回滾
rollbackFor
默認(rèn)情況下,只有出現(xiàn) RuntimeException 才回滾異常。rollbackFor屬性用于控制出現(xiàn)何種異常類型,回滾事務(wù)。
@Transactional(rollbackFor = Exception.class) // 回滾
default boolean saveBatch(Collection<T> entityList) {
return saveBatch(entityList, DEFAULT_BATCH_SIZE);
}
表格一覽
| 屬性 | 作用 | 示例 |
|---|---|---|
| readOnly | 設(shè)置是否為只讀事務(wù) | readOnly=true 只讀事務(wù) |
| timeout | 設(shè)置事務(wù)超時時間 | timeout = -1(永不超時) |
| rollbackFor | 設(shè)置事務(wù)回滾異常(class) | rollbackFor = |
| rollbackForClassName | 設(shè)置事務(wù)回滾異常(String) | 同上格式為字符串 |
| noRollbackFor | 設(shè)置事務(wù)不回滾異常(class) | noRollbackFor = |
| noRollbackForClassName | 設(shè)置事務(wù)不回滾異常(String) | 同上格式為字符串 |
| propagation | 設(shè)置事務(wù)傳播行為 | …… |
事務(wù)屬性--傳播行為
| 屬性值 | 含義 |
|---|---|
| REQUIRED | 【默認(rèn)值】需要事務(wù),有則加入,無則創(chuàng)建新事務(wù) |
| REQUIRES_NEW | 需要新事務(wù),無論有無,總是創(chuàng)建新事務(wù) |
| SUPPORTS | 支持事務(wù),有則加入,無則在無事務(wù)狀態(tài)中運行 |
| NOT_SUPPORTED | 不支持事務(wù),在無事務(wù)狀態(tài)下運行,如果當(dāng)前存在已有事務(wù),則掛起當(dāng)前事務(wù) |
| MANDATORY | 必須有事務(wù),否則拋異常 |
| NEVER | 必須沒事務(wù),否則拋異常 |
| NESTED | 如果當(dāng)前事務(wù)存在,則在嵌套事務(wù)中執(zhí)行,內(nèi)層事務(wù)以來外層事務(wù),如果外層失敗,則會回滾內(nèi)層,內(nèi)層失敗不影響外層。 |
代碼實踐
@Transactional
public void a() {
//......
userService.b();
//......
}
@Transactional(propagation = Propagation.REQUIRED)
public void b() {
//......
}
常用事務(wù)傳播行為
REQUIRED:大部分情況下都是用該傳播行為即可。
REQUIRES_NEW:當(dāng)我們不希望事務(wù)之間相互影響時,可以使用該傳播行為。比如:下訂單前需要記錄日志,不論訂單保存成功與否,都需要保證日志記錄能夠記錄成功。

浙公網(wǎng)安備 33010602011771號