日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Spring Boot JPA 中transaction的使用

發布時間:2024/2/28 javascript 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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個并發過程中可能出現的問題:

  • 臟讀: 讀取一個transaction還沒有提交的change
  • 不可重復讀:在一個transaction修改數據庫中的某行數據時,另外一個transaction多次讀取同一行數據,獲取到的不同的值。
  • 幻讀: 在一個transaction添加或者刪除數據庫的數據時,另外一個transaction做范圍查詢,獲得了不同的數據行數。
  • 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的使用的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。