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

歡迎訪問 生活随笔!

生活随笔

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

javascript

Spring Data JPA 从入门到精通~事务的处理及其讲解

發布時間:2024/7/23 javascript 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring Data JPA 从入门到精通~事务的处理及其讲解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

默認 @Transactional 注解式事務

(1)@EnableTransactionManagement

正常情況下,我們是需要在 ApplicationConfig 類加上 @EnableTransactionManagement 注解才能開啟事務管理。通過 DataSource 的研究步驟 spring.factories 里面默認加載 TransactionAutoConfiguration 類,而我們看源碼,其里面已經加了此注解,默認采用的 AdviceMode.PROXY,所以默認情況的事務管理機制是代理方式的,通過添加 @Transactional 注解式配置方法,查看 SimpleJpaRepository:

@Repository @Transactional(readOnly = true) public class SimpleJpaRepository<T, ID> implements JpaRepository<T, ID>, JpaSpecificationExecutor<T> {...}

所以每個 Respository 的方法是都是有默認的只讀事務的。

(2)我們來查看一下 @Transactional 源碼:

@Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface Transactional {@AliasFor("transactionManager")String value() default "";@AliasFor("value")String transactionManager() default "";Propagation propagation() default Propagation.REQUIRED;Isolation isolation() default Isolation.DEFAULT;int timeout() default TransactionDefinition.TIMEOUT_DEFAULT;boolean readOnly() default false;Class<? extends Throwable>[] rollbackFor() default {};String[] rollbackForClassName() default {};Class<? extends Throwable>[] noRollbackFor() default {};String[] noRollbackForClassName() default {}; }

@Transactional 注解中常用參數說明

參數名稱

功能描述

readOnly

rollbackFor

rollbackForClassName

noRollbackFor

noRollbackForClassName

propagation

isolation

timeout

transactionManager/value

(3)propagation:傳播行為

所謂事務的傳播行為是指,如果在開始當前事務之前,一個事務上下文已經存在,此時有若干選項可以指定一個事務性方法的執行行為。

可以看 org.springframework.transaction.annotation.Propagation 枚舉類中定義了 7 個表示傳播行為的枚舉值:

public enum Propagation { REQUIRED(0), SUPPORTS(1), MANDATORY(2), REQUIRES_NEW(3), NOT_SUPPORTED(4), NEVER(5), NESTED(6); }

  • REQUIRED:如果當前存在事務,則加入該事務;如果當前沒有事務,則創建一個新的事務。
  • SUPPORTS:如果當前存在事務,則加入該事務;如果當前沒有事務,則以非事務的方式繼續運行。
  • MANDATORY:如果當前存在事務,則加入該事務;如果當前沒有事務,則拋出異常。
  • REQUIRES_NEW:創建一個新的事務,如果當前存在事務,則把當前事務掛起。
  • NOT_SUPPORTED:以非事務方式運行,如果當前存在事務,則把當前事務掛起。
  • NEVER:以非事務方式運行,如果當前存在事務,則拋出異常。
  • NESTED:如果當前存在事務,則創建一個事務作為當前事務的嵌套事務來運行;如果當前沒有事務,則該取值等價于REQUIRED。

設置方法:通過使用propagation屬性設置,例如:

@Transactional(propagation = Propagation.REQUIRED)

(4)Isolation 隔離級別

隔離級別是指若干個并發的事務之間的隔離程度,與我們開發時候主要相關的場景包括:臟讀取、重復讀、幻讀。

我們可以看 org.springframework.transaction.annotation.Isolation 枚舉類中定義了四個表示隔離級別的值:

public enum Propagation {REQUIRED(0),SUPPORTS(1),MANDATORY(2),REQUIRES_NEW(3),NOT_SUPPORTED(4),NEVER(5),NESTED(6); }
  • DEFAULT:這是默認值,表示使用底層數據庫的默認隔離級別,對大部分數據庫而言,通常這值就是READ_COMMITTED。
  • READ_UNCOMMITTED:該隔離級別表示一個事務可以讀取另一個事務修改但還沒有提交的數據。該級別不能防止臟讀和不可重復讀,因此很少使用該隔離級別。
  • READ_COMMITTED:該隔離級別表示一個事務只能讀取另一個事務已經提交的數據。該級別可以防止臟讀,這也是大多數情況下的推薦值。
  • REPEATABLE_READ:該隔離級別表示一個事務在整個過程中可以多次重復執行某個查詢,并且每次返回的記錄都相同。即使在多次查詢之間有新增的數據滿足該查詢,這些新增的記錄也會被忽略。該級別可以防止臟讀和不可重復讀。
  • SERIALIZABLE:所有的事務依次逐個執行,這樣事務之間就完全不可能產生干擾,也就是說,該級別可以防止臟讀、不可重復讀以及幻讀,但是這將嚴重影響程序的性能。通常情況下也不會用到該級別。

設定方法為通過使用 isolation 屬性設置,例如:

@Transactional(isolation = Isolation.DEFAULT)

(5)所以 Spring Boot 的這種默認機制,只需要在我們用事務時,在方法上或者此方法的類上加上 @Transactional注解即可。

而實際工作中,我們一般都要在 Service 層的某些方法上加事務,以保證整個方法的事務。示例如下:

@Transactional(rollbackOn = Exception.class) public void saveUserInfo() throws Exception {userCustomerRepository.save(new UserCustomerEntity("jackzhang@mail.com","jackzhang"));userRepository.save(new UserInfoEntity("jack_test","name"));throw new Exception("test");......//此方法體有多個repository的調用,模擬異常,事務會回滾的 }

(6)注意的幾點

  • @Transactional 只能被應用到 public 方法上,對于其他非 public 的方法,如果標記了 @Transactional 也不會報錯,但方法沒有事務功能。
  • 用 spring 事務管理器,由 spring 來負責數據庫的打開、提交、回滾,默認遇到運行期例外(throw new RuntimeException("注釋");)會回滾,即遇到不受檢查(unchecked)的例外時回滾;而遇到需要捕獲的例外(throw new Exception("注釋");)不會回滾,即遇到受檢查的例外(就是非運行時拋出的異常,編譯器會檢查到的異常叫受檢查例外或說受檢查異常)時,需我們指定方式來讓事務回滾要想所有異常都回滾,要加上 @Transactional( rollbackFor={Exception.class,其他異常}),如果讓 unchecked 例外不回滾:@Transactional(notRollbackFor=RunTimeException.class)。
  • @Transactional 注解應該只被應用到 public 可見度的方法上。如果你在 protected、private 或者 package-visible 的方法上使用 @Transactional 注解,它也不會報錯,但是這個被注解的方法將不會展示已配置的事務設置。
  • @Transactional 注解可以被應用于接口定義和接口方法、類定義和類的 public 方法上。然而,請注意僅僅 @Transactional 注解的出現不足于開啟事務行為,它僅僅是一種元數據,能夠被可以識別 @Transactional 注解和上述的配置適當的具有事務行為的 beans 所使用。上面的例子中,其實正是 元素的出現開啟了事務行為。
  • Spring 團隊的建議是你在具體的類(或類的方法)上使用 @Transactional 注解,而不要使用在類所要實現的任何接口上。當然可以在接口上使用 @Transactional 注解,但是這將只能當你設置了基于接口的代理時它才生效。因為注解是不能繼承的,這就意味著如果你正在使用基于類的代理時,那么事務的設置將不能被基于類的代理所識別,而且對象也將不會被事務代理所包裝(將被確認為嚴重的)。因此,請接受 Spring 團隊的建議并且在具體的類上使用 @Transactional 注解。
  • 事務有兩種配置方法,一種是我們現在說的顯式的注解式事務,當我們注解式事務下,不加注解 service 方法上是沒有任何事務的。還有一種是隱式事務,ASPECTJ 的思路配置方法,所以不是沒有加 @Transactional 注解就一定沒有事務。

聲明式事務,又叫隱式事務,或者叫 ASPECTJ 事務

配置方法:

在實際工作中,每個方法都讓我們加上 @Transactional 注解,可能工作量有點大,也有時候會忘,所以經常看到有開發團隊配置攔截式事務。雖然 spring 官方不太推薦。只需要在我們的項目中新增一個類 AspectjTransactionConfig 即可,如下:

@Configuration @EnableTransactionManagement public class AspectjTransactionConfig {public static final String transactionExecution = "execution (* com.jackzhang.example..service.*.*(..))";@Autowiredprivate PlatformTransactionManager transactionManager;@Beanpublic DefaultPointcutAdvisor defaultPointcutAdvisor() {//指定一般要攔截哪些類AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();pointcut.setExpression(transactionExecution);//配置advisorDefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor();advisor.setPointcut(pointcut);//指定不同的方法用不通的策略Properties attributes = new Properties();attributes.setProperty("get*", "PROPAGATION_REQUIRED,-Exception");attributes.setProperty("add*", "PROPAGATION_REQUIRED,-Exception");attributes.setProperty("save*", "PROPAGATION_REQUIRED,-Exception");attributes.setProperty("update*", "PROPAGATION_REQUIRED,-Exception");attributes.setProperty("delete*", "PROPAGATION_REQUIRED,-Exception");//創建InterceptorTransactionInterceptor txAdvice = new TransactionInterceptor(transactionManager, attributes);advisor.setAdvice(txAdvice);return advisor;} }

這樣我們的 Service 就會自動擁有了事務,可以加 @Transactional 來覆蓋全局的配置。

總結

以上是生活随笔為你收集整理的Spring Data JPA 从入门到精通~事务的处理及其讲解的全部內容,希望文章能夠幫你解決所遇到的問題。

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