javascript
Spring Boot JPA 中transaction的使用
文章目錄
- @Transactional的實現
- @Transactional的使用
- Transaction的傳播級別
- REQUIRED
- SUPPORTS
- MANDATORY
- NEVER
- NOT_SUPPORTED
- REQUIRES_NEW
- NESTED
- Transaction的隔離級別
- READ_UNCOMMITTED
- READ_COMMITTED
- REPEATABLE_READ
- SERIALIZABLE
Spring Boot JPA 中transaction的使用
transaction是我們在做數據庫操作的時候不能回避的一個話題,通過transaction,我們可以保證數據庫操作的原子性,一致性,隔離性和持久性。
本文我們將會深入的探討Spring Boot JPA中@Transactional注解的使用。
通過@Transactional注解,我們可以設置事物的傳播級別和隔離級別,同時可以設置timeout, read-only, 和 rollback等特性。
@Transactional的實現
Spring通過創建代理或者操縱字節碼來實現事物的創建,提交和回滾操作。如果是代理模式的話,Spring會忽略掉@Transactional的內部方法調用。
如果我們有個方法callMethod,并標記它為@Transactional,那么Spring Boot的實現可能是如下方式:
createTransactionIfNecessary(); try {callMethod();commitTransactionAfterReturning(); } catch (exception) {completeTransactionAfterThrowing();throw exception; }@Transactional的使用
@Transactional使用起來很簡單,可以放在class上,可以放在interface上,也可以放在方法上面。
如果放在方法上面,那么該方法中的所有public方法都會應用該Transaction。
如果@Transactional放在private方法上面,則Spring Boot將會忽略它。
Transaction的傳播級別
傳播級別Propagation定義了Transaction的邊界,我們可以很方便的在@Transactional注解中定義不同的傳播級別。
下面我們來分別看一下Transaction的傳播級別。
REQUIRED
REQUIRED是默認的傳播級別,下面的兩種寫法是等價的:
@Transactionalpublic void deleteBookWithDefaultTransaction(Long id) {bookRepository.deleteBookById(id);}@Transactional(propagation = Propagation.REQUIRED)public void deleteBookWithRequired(Long id) {}Spring會檢測現在是否有一個有效的transaction。如果沒有則創建,如果有transaction,則Spring將會把該放方法的業務邏輯附加到已有的transaction中。
我們再看下REQUIRED的偽代碼:
if (isExistingTransaction()) {if (isValidateExistingTransaction()) {validateExisitingAndThrowExceptionIfNotValid();}return existing; } return createNewTransaction();SUPPORTS
在SUPPORTS的情況下,Spring首先會去檢測是否有存在Transaction,如果存在則使用,否則不會使用transaction。
我們看下代碼怎么使用:
@Transactional(propagation = Propagation.SUPPORTS)public void deleteBookWithSupports(Long id) {}SUPPORTS的實現偽代碼如下:
if (isExistingTransaction()) {if (isValidateExistingTransaction()) {validateExisitingAndThrowExceptionIfNotValid();}return existing; } return emptyTransaction;MANDATORY
在MANDATORY情況下,Spring先會去檢測是否有一個Transaction存在,如果存在則使用,否則拋出異常。
我們看下代碼怎么使用:
@Transactional(propagation = Propagation.MANDATORY)public void deleteBookWithMandatory(Long id) {}MANDATORY的實現邏輯如下:
if (isExistingTransaction()) {if (isValidateExistingTransaction()) {validateExisitingAndThrowExceptionIfNotValid();}return existing; } throw IllegalTransactionStateException;NEVER
如果是NEVER的情況下,如果現在有一個Transaction存在,則Spring會拋出異常。
使用的代碼如下:
@Transactional(propagation = Propagation.NEVER)public void deleteBookWithNever(Long id) {}實現邏輯代碼如下:
if (isExistingTransaction()) {throw IllegalTransactionStateException; } return emptyTransaction;NOT_SUPPORTED
如果使用的是NOT_SUPPORTED,那么Spring將會首先暫停現有的transaction,然后在非transaction情況下執行業務邏輯。
我們這樣使用:
@Transactional(propagation = Propagation.NOT_SUPPORTED)public void deleteBookWithNotSupported(Long id) {}REQUIRES_NEW
當REQUIRES_NEW使用時,Spring暫停當前的Transaction,并創建一個新的。
我們看下代碼怎么使用:
@Transactional(propagation = Propagation.REQUIRES_NEW)public void deleteBookWithRequiresNew(Long id){}相應的實現代碼如下:
if (isExistingTransaction()) {suspend(existing);try {return createNewTransaction();} catch (exception) {resumeAfterBeginException();throw exception;} } return createNewTransaction();NESTED
NESTED顧名思義,是嵌套的Transaction,Spring首先檢查transaction是否存在,如果存在則創建一個savepoint,如果我們的程序拋出異常的時候,transaction將會回滾到該savepoint。如果沒有transaction,NESTED的表現和REQUIRED一樣。
我們看下怎么使用:
@Transactional(propagation = Propagation.NESTED)public void deleteBookWithNested(Long id){}Transaction的隔離級別
隔離級別就是我們之前提到的原子性,一致性,隔離性和持久性。隔離級別描述了改動對其他并發者的可見程度。
隔離級別主要是為了防止下面3個并發過程中可能出現的問題:
READ_UNCOMMITTED
READ_UNCOMMITTED是隔離級別中最低的級別。這個級別下,并發的3個問題都可能出現。
我們這樣使用:
@Transactional(isolation = Isolation.READ_UNCOMMITTED)public void deleteBookWithReadUncommitted(Long id){}READ_COMMITTED
READ_COMMITTED可以防止臟讀。
我們看下代碼:
@Transactional(isolation = Isolation.READ_COMMITTED)public void deleteBookWithReadCommitted(Long id){}REPEATABLE_READ
REPEATABLE_READ可以防止臟讀和不可重復讀。
使用的代碼如下:
@Transactional(isolation = Isolation.REPEATABLE_READ)public void deleteBookWithRepeatableRead(Long id){}SERIALIZABLE
SERIALIZABLE是最嚴格的基本,可以防止臟讀,不可重復讀和幻讀。
我們看下怎么使用:
@Transactional(isolation = Isolation.SERIALIZABLE)public void deleteBookWithSerializable(Long id){}本文的例子可以參考https://github.com/ddean2009/learn-springboot2/tree/master/springboot-transaction
更多精彩內容且看:
- 區塊鏈從入門到放棄系列教程-涵蓋密碼學,超級賬本,以太坊,Libra,比特幣等持續更新
- Spring Boot 2.X系列教程:七天從無到有掌握Spring Boot-持續更新
- Spring 5.X系列教程:滿足你對Spring5的一切想象-持續更新
- java程序員從小工到專家成神之路(2020版)-持續更新中,附詳細文章教程
更多教程請參考 flydean的博客
總結
以上是生活随笔為你收集整理的Spring Boot JPA 中transaction的使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java并发中的Synchronized
- 下一篇: gradle idea java ssm