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