# Spring Boot事務
Spring Boot的事務機制與spring的事務一致。只需要在方法上添加`@Transactional`注解即可。
## 一個在Service層的例子(聲明式)
```java
@Override
@Transactional
public long save(User user) {
// 參數校驗
Assert.notNull(user,"用戶不能為空");
Assert.isTrue(user.getId() == 0, "用戶id非法,必須為0");
Assert.hasLength(user.getName(), "用戶名稱不能為空");
Assert.notNull(user.getBirthDay(),"用戶生日不能為空");
Assert.notNull(user.getRegisterDate(),"用戶注冊時間不能為空");
// 新增
long pk = userDao.save(user);
// 打印主鍵
System.out.println(pk);
// 造成異常
double result = 1 / 0;
return pk;
}
```
## @Transactional屬性說明
- `isolation`:用于指定事務的隔離級別。默認為底層事務的隔離級別。
- `noRollbackFor`:指定遇到指定異常時強制不回滾事務。
- `noRollbackForClassName`:指定遇到指定多個異常時強制不回滾事務。該屬性可以指定多個異常類名。
- `propagation`:指定事務的傳播屬性。
- `readOnly`:指定事務是否只讀。表示這個事務只讀取數據但不更新數據,這樣可以幫助數據庫引擎優化事務。若真的是一個只讀取的數據庫應設置 `readOnly=true`
- `rollbackFor`:指定遇到指定異常時強制回滾事務。
- `rollbackForClassName`:指定遇到指定多個異常時強制回滾事務。該屬性可以指定多個異常類名。
- `timeout`:指定事務的超時時長。
> 當然,你也可以使用編程式事務,只需要注入spring的事務模板即可
## Spring 事務傳播行為
- `PROPAGATION_REQUIRED` : 表示當前方法必須運行在事務中。如果當前事務存在,方法將會在該事務中運行。否則,會啟動一個新的事務, **Spring 默認使用**
- `PROPAGATION_SUPPORTS` : 表示當前方法不需要事務上下文,但是如果存在當前事務的話,那么該方法會在這個事務中運行
- `PROPAGATION_MANDATORY` :表示該方法必須在事務中運行,如果當前事務不存在,則會拋出一個異常
- `PROPAGATION_REQUIRED_NEW` : 表示當前方法必須運行在它自己的事務中。一個新的事務將被啟動。如果存在當前事務,在該方法執行期間,當前事務會被掛起。如果使用 `JTATransactionManager` 的話,則需要訪問 `TransactionManager`
- `PROPAGATION_NOT_SUPPORTED` : 表示該方法不應該運行在事務中。如果存在當前事務,在該方法運行期間,當前事務將被掛起。如果使用 `JTATransactionManager` 的話,則需要訪問 `TransactionManager`
- `PROPAGATION_NEVER` : 表示當前方法不應該運行在事務上下文中。如果當前正有一個事務在運行,則會拋出異常
- `PROPAGATION_NESTED` : 表示如果當前已經存在一個事務,那么該方法將會在嵌套事務中運行。嵌套的事務可以獨立于當前事務進行單獨地提交或回滾。如果當前事務不存在,那么其行為與`PROPAGATION_REQUIRED`一樣。注意各廠商對這種傳播行為的支持是有所差異的。可以參考資源管理器的文檔來確認它們是否支持嵌套事務