一、事務隔離級別:
數據庫事務的隔離級別有4個,由低到高依次為Read uncommitted、Read committed、Repeatable read、Serializable,這四個級別可以逐個解決臟讀、不可重復讀、幻讀這幾類問題。
1. ISOLATION_READ_UNCOMMITTED:這是事務最低的隔離級別,它充許令外一個事務可以看到這個事務未提交的數據。
這種隔離級別會產生臟讀,不可重復讀和幻像讀。
2. ISOLATION_READ_COMMITTED:保證一個事務修改的數據提交后才能被另外一個事務讀取。另外一個事務不能讀取該事務未提交的數據
3. ISOLATION_REPEATABLE_READ:這種事務隔離級別可以防止臟讀,不可重復讀。但是可能出現幻像讀。
它除了保證一個事務不能讀取另一個事務未提交的數據外,還保證了避免下面的情況產生(不可重復讀)。
4. ISOLATION_SERIALIZABLE:這是花費最高代價但是最可靠的事務隔離級別。事務被處理為順序執行。
除了防止臟讀,不可重復讀外,還避免了幻像讀
5. DEFAULT :這是一個PlatfromTransactionManager默認的隔離級別,這個默認隔離級別是與具體的數據庫相關的
采取的是具體數據庫的默認隔離級別
Mysql 默認:可重復讀 Oracle 默認:讀已提交
二、事務傳播行為:
1.PROPAGATION_REQUIRED – 支持當前事務,如果當前沒有事務,就新建一個事務。這是最常見的選擇。
2.PROPAGATION_SUPPORTS – 支持當前事務,如果當前沒有事務,就以非事務方式執行。
3.PROPAGATION_MANDATORY – 支持當前事務,如果當前沒有事務,就拋出異常。
4.PROPAGATION_REQUIRES_NEW – 新建事務,如果當前存在事務,把當前事務掛起。
5.PROPAGATION_NOT_SUPPORTED – 以非事務方式執行操作,如果當前存在事務,就把當前事務掛起。
6.PROPAGATION_NEVER – 以非事務方式執行,如果當前存在事務,則拋出異常。
7.PROPAGATION_NESTED – 如果當前存在事務,則在嵌套事務內執行。如果當前沒有事務,則進行與PROPAGATION_REQUIRED類似的操作。
備注:常用的兩個事務傳播屬性是1和4,即PROPAGATION_REQUIRED,PROPAGATION_REQUIRES_NEW
三、項目中使用@Transactional管理事務注意事項
1. 有事物方法調用其他無事物方法時,調用的方法也在事物范圍內。如被調用方法也有@Transactional,則看該注解具體配置的事物傳播級別,默認為propagation=Propagation.NOT_SUPPORTED,包含事物。 2.使用了@Transactional的方法A,對不同類里面使用了@Transactional的方法B調用,B代碼不回滾A進行回滾
比如有一個類Test,它的一個方法A,A調用其它類的方法B(B的@Transactional 的 propagation 屬性為 Propagation.REQUIRES_NEW),假設B方法執行完成無異常 接下來繼續執行a方法報了異常,那么只會回滾a方法 B中的代碼則不會回滾
3. 無事物方法調用本類有事物方法時,被調用方法的事物不生效。原因為spring的@Transactional事務生效的一個前提是進行方法調用前經過攔截器TransactionInterceptor,而本類方法的調用為this.方法(),未經過攔截器處理。 比如:比如有一個類Test,它的一個方法A,A再調用Test本類的方法B(不管B是否public還是private),但A沒有聲明注解事務,而B有。則外部調用A之后,B的事務是不會起作用的。(經常在這里出錯)
解決方案(分兩步): ①(當前類名)AopContext.currentProxy().需調用方法(); ②在spring配置文件中添加,<aop:aspectj-autoproxy expose-proxy="true"/> 4. @Transactional 注解只能應用到 public 可見度的方法上。 5. Spring團隊建議在具體的類(或類的方法)上使用 @Transactional 注解,而不要使用在類所要實現的任何接口上。在接口上使用 @Transactional 注解,只能當你設置了基於接口的代理時它才生效。因為注解是 不能繼承的。 6. @Transactional注解默認只能處理error和RuntimeException及其子類等unchecked異常,要想處理checked異常(編譯時異常)則需要配置為rollbackFor=RuntimeException.class。