在 Spring 中,我們可以透過 @Transactional
註解來啟用事務,此註解通常被用在方法或是類別上。
當類別上使用@Transactional
註解時,代表該類別和子類別的所有方法都設定為相同的事務屬性。如果在類別和方法上都使用了@Transactional
註解,方法使用的事務屬性會覆蓋類別所用的事務屬性。當某個方法或是類別使用了 @Transactional
,Spring 會自動幫助該方法或類別在資料庫操作時進行事務管理,確保符合ACID特性。
@Transactional
中常用的屬性有:
1. isolation:用於設定事務的隔離層級,控制多個事務執行時是否允許髒讀、重複讀取、幻讀等狀況。支援的層級如下:
- Isolation.READ_UNCOMMITTED
- Isolation.READ_COMMITTED
- Isolation.REPEATABLE_READ
- Isolation.SERIALIZABLE
2. propagation:用於設定事務傳播的類型,用於控制事務方法要如何與現有的事務進行互動(預設為 Propagation.REQUIRED
)。
3. readOnly:是否唯讀,如果 readOnly 值為 true,代表該事務只進行查詢操作,並不涉及資料的修改(預設為 false)。
4. timeout:事務逾時時間的設定,以秒為單位,假設事務執行的時間超過設定的時間,事務會自動回滾。
5. rollbackFor:當事務執行發生例外狀況時,事務會回滾
6. noRollbackFor:當事務執行發生例外狀況時,事務不會回滾
在方法上加入@Transactional
註解的範例如下:
@Transactional(isolation = Isolation.REPEATABLE_READ, timeout = 30, rollbackFor = Exception.class)
public int saveStudentScores(String serialNumber, StudentScore studentScore){
StudentInformation studentInformation = studentInformationRepository.getStudentBySerialNumber(serialNumber);
if(studentInformation != null){
StudentScores ss = new StudentScores();
ss.setSsSiId(studentInformation.getSiId());
ss.setSsExamId(studentScore.getExamId());
ss.setSsSubject(studentScore.getSubject());
ss.setSsScore(studentScore.getScore());
studentScoresRepository.saveAndFlush(ss);
return 0;
}
return 1;
}
我將 Day19 文章中新增學生考試成績的方法加上了 @Transactional
註解,設置的隔離級別為Isolation.REPEATABLE_READ
用於確保讀取資料的一致性,並設定了事務執行的時間為30秒,如果超過則會觸發超時,事務會回滾。此外,還設置了rollbackFor
屬性,當 Spring 捕獲到任何 Exception時,事務會回滾。