最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring的編程式事務(wù)和聲明式事務(wù)詳解

 更新時間:2017年09月25日 14:34:20   作者:sutonline  
這篇文章主要介紹了Spring的編程式事務(wù)和聲明式事務(wù)的相關(guān)內(nèi)容,涉及Spring事務(wù)屬性、Spring事務(wù)的基本類等知識,需要的朋友可以了解下。

入口(了解一些基本概念)

Spring事務(wù)屬性(事務(wù)的屬性有哪些?)

我們都知道事務(wù)有開始,保存點,提交,回滾,隔離級別等屬性。那么Spring對于事務(wù)屬性定義有哪些呢?通過TransactionDefinition接口我們可以了解到:

public interface TransactionDefinition{ 
int getIsolationLevel(); 
int getPropagationBehavior(); 
int getTimeout(); 
boolean isReadOnly(); 
} 

獲取隔離級別

獲取傳播特性

獲取超時

獲取是否只讀

事務(wù)隔離級別

隔離離別也是通過TransactionDefinition接口定義的,代表并發(fā)事務(wù)的隔離程度。

隔離級別 描述
TransactionDefinition.ISOLATION_DEFAULT 這是默認(rèn)值,表示使用底層數(shù)據(jù)庫的默認(rèn)隔離級別。對大部分?jǐn)?shù)據(jù)庫而言,通常這值就是TransactionDefinition.ISOLATION_READ_COMMITTED
TransactionDefinition.ISOLATION_READ_UNCOMMITTED 該隔離級別表示一個事務(wù)可以讀取另一個事務(wù)修改但還沒有提交的數(shù)據(jù)。該級別不能防止臟讀和不可重復(fù)讀,因此很少使用該隔離級別
TransactionDefinition.ISOLATION_READ_COMMITTED 該隔離級別表示一個事務(wù)只能讀取另一個事務(wù)已經(jīng)提交的數(shù)據(jù)。該級別可以防止臟讀,這也是大多數(shù)情況下的推薦值
TransactionDefinition.ISOLATION_REPEATABLE_READ 該隔離級別表示一個事務(wù)在整個過程中可以多次重復(fù)執(zhí)行某個查詢,并且每次返回的記錄都相同。即使在多次查詢之間有新增的數(shù)據(jù)滿足該查詢,這些新增的記錄也會被忽略。該級別可以防止臟讀和不可重復(fù)讀。
TransactionDefinition.ISOLATION_SERIALIZABLE 所有的事務(wù)依次逐個執(zhí)行,這樣事務(wù)之間就完全不可能產(chǎn)生干擾,也就是說,該級別可以防止臟讀、不可重復(fù)讀以及幻讀。但是這將嚴(yán)重影響程序的性能。通常情況下也不會用到該級別。

* 事務(wù)傳播行為

所謂事務(wù)的傳播行為是指,如果在開始當(dāng)前事務(wù)之前,一個事務(wù)上下文已經(jīng)存在,此時有若干選項可以指定一個事務(wù)性方法的執(zhí)行行為。在TransactionDefinition定義中包括了如下幾個表示傳播行為的常量.

傳播行為 描述
TransactionDefinition.PROPAGATION_REQUIRED 如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒有事務(wù),則創(chuàng)建一個新的事務(wù)
TransactionDefinition.PROPAGATION_REQUIRES_NEW 創(chuàng)建一個新的事務(wù),如果當(dāng)前存在事務(wù),則把當(dāng)前事務(wù)掛起
TransactionDefinition.PROPAGATION_SUPPORTS 如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒有事務(wù),則以非事務(wù)的方式繼續(xù)運行
TransactionDefinition.PROPAGATION_NOT_SUPPORTED 以非事務(wù)方式運行,如果當(dāng)前存在事務(wù),則把當(dāng)前事務(wù)掛起
TransactionDefinition.PROPAGATION_NEVER 以非事務(wù)方式運行,如果當(dāng)前存在事務(wù),則拋出異常
TransactionDefinition.PROPAGATION_MANDATORY 如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒有事務(wù),則拋出異常
TransactionDefinition.PROPAGATION_NESTED 如果當(dāng)前存在事務(wù),則創(chuàng)建一個事務(wù)作為當(dāng)前事務(wù)的嵌套事務(wù)來運行;如果當(dāng)前沒有事務(wù),則該取值等價于TransactionDefinition.PROPAGATION_REQUIRED

* 事務(wù)超時

指定事務(wù)的最大運行時間。使用int指定,單位是秒。

* 事務(wù)的只讀屬性

事務(wù)的只讀屬性是指,對事務(wù)性資源進行只讀操作或者是讀寫操作。所謂事務(wù)性資源就是指那些被事務(wù)管理的資源,比如數(shù)據(jù)源、 JMS 資源,以及自定義的事務(wù)性資源等等。如果確定只對事務(wù)性資源進行只讀操作,那么我們可以將事務(wù)標(biāo)志為只讀的,以提高事務(wù)處理的性能。在 TransactionDefinition 中以 boolean 類型來表示該事務(wù)是否只讀。

* 事務(wù)的回滾規(guī)則

默認(rèn)出現(xiàn)RuntimeException就會回滾。如果沒有拋出任何異常,或者拋出了已檢查異常,則仍然提交事務(wù)。這通常也是大多數(shù)開發(fā)者希望的處理方式,也是 EJB 中的默認(rèn)處理方式。(這里個人理解的是已檢查異常,是我們定義的checkedException,包括我們自定義的異常和調(diào)用方法捕獲的異常)

Spring事務(wù)的三個基本類

Spring 框架中,涉及到事務(wù)管理的 API 大約有100個左右,其中最重要的有三個:TransactionDefinition、PlatformTransactionManager、TransactionStatus。所謂事務(wù)管理,其實就是“按照給定的事務(wù)規(guī)則來執(zhí)行提交或者回滾操作”。“給定的事務(wù)規(guī)則”就是用 TransactionDefinition 表示的,“按照……來執(zhí)行提交或者回滾操作”便是用 PlatformTransactionManager 來表示,而 TransactionStatus 用于表示一個運行著的事務(wù)的狀態(tài)。打一個不恰當(dāng)?shù)谋扔?,TransactionDefinition 與 TransactionStatus 的關(guān)系就像程序和進程的關(guān)系。

TransactionDefinition 定義事務(wù)的屬性

TransactionStatus 定義事務(wù)的狀態(tài)

public interface TransactionStatus{ 
boolean isNewTransaction(); 
void setRollbackOnly(); 
boolean isRollbackOnly(); 
} 

PlatformTransactionManager 就是各種事務(wù)平臺的實現(xiàn)接口

Public interface PlatformTransactionManager{ 
TransactionStatus getTransaction(TransactionDefinition definition) 
throws TransactionException; 
void commit(TransactionStatus status)throws TransactionException; 
void rollback(TransactionStatus status)throws TransactionException; 
} 

所以我們現(xiàn)在可以向下,spring的事務(wù)真正實現(xiàn)是PlatformTransactionManager的實現(xiàn)類,通過各種參數(shù)來符合TransactionDefinition和TransactionStatus的要求,最后根據(jù)我們編程的或者聲明的進行事務(wù)管理。

根據(jù)底層框架的不同(稍后我們看一下DataSourceTransactoinManager和HibernateTransactionManager的代碼,主要做了什么),Spring(或者其他框架)提供主要的實現(xiàn)如下:

DataSourceTransactionManager: 適合JDBC和ibatis

HibernateTransactionManager: 適合hibernate

JpaTransactionManager: 適用于使用JPA進行數(shù)據(jù)持久化操作的情況(更底層的一些)

適用于使用JPA進行數(shù)據(jù)持久化操作的情況

到這里基本概念終于結(jié)束了,我們可以介紹兩種類型的事務(wù)管理了

編程式事務(wù)管理

首先我們回想一下不適用spring事務(wù)管理時,hibernate事務(wù)的管理是怎么樣的? 大概是我們手動獲取session,獲取transaction,開始transaction,提交或者回滾,關(guān)閉session

那么我們使用spring的管理之后,事務(wù)本身控制還是交給持久框架自己管理。知識spring像一個代理人一樣,你告訴它,它之后轉(zhuǎn)化后告訴底層框架。

看個實際例子吧:

基于底層API的編程式事務(wù)管理

public class BankServiceImpl implements BankService {
  private BankDao bankDao;
  private TransactionDefinition txDefinition; // transaction定義是哪個 
  private PlatformTransactionManager txManager; //具體使用的txmanager
  ......
  public boolean transfer(Long fromId, Long toId, double amount) {
  //這里獲取事務(wù)狀態(tài)
  TransactionStatus txStatus = txManager.getTransaction(txDefinition);
  boolean result = false;
  try {
  result = bankDao.transfer(fromId, toId, amount);
  //提交事務(wù)
  txManager.commit(txStatus);
  } catch (Exception e) {
  result = false;
  //回滾
  txManager.rollback(txStatus);
  System.out.println("Transfer Error!");
  }
  return result;
  }
}

對應(yīng)的xml文件:

<bean id="bankService" class="footmark.spring.core.tx.programmatic.origin.BankServiceImpl">
  <property name="bankDao" ref="bankDao"/>
  <property name="txManager" ref="transactionManager"/>
  <property name="txDefinition">
    <bean class="org.springframework.transaction.support.DefaultTransactionDefinition">
  <property name="propagationBehaviorName" value="PROPAGATION_REQUIRED"/>
  </bean>
  </property>
</bean>

但是這種寫法和我們不適用spring的有何不同呢,最多是將事務(wù)層次提高了service層,不限于dao層,所以Spring做了改進:
基于TransactionTemplate的編程式事務(wù)管理

TransactionTemplate的execute方法提供一個內(nèi)部匿名類,用來我們寫transaction代碼,然后提供一個transactionStatus的參數(shù),這樣你可以控制回滾。這樣一來,我們就不用寫任何關(guān)于事務(wù)API的代碼了。格式大概是 Boolean b = transactionTempate.execute(new TransactionCallBack() { 執(zhí)行方法(TransactionStatus transactionStatus){} },當(dāng)執(zhí)行完成后返回一個boolean的值. 還有一個方法,就是不提供返回結(jié)果的。

public class BankServiceImpl implements BankService {
  private BankDao bankDao;
  private TransactionTemplate transactionTemplate;
  ......
  public boolean transfer(final Long fromId, final Long toId, final double amount) {
    //調(diào)用一個回調(diào)函數(shù)
    return (Boolean) transactionTemplate.execute(new TransactionCallback(){
  public Object doInTransaction(TransactionStatus status) {
    Object result;
    try {
      result = bankDao.transfer(fromId, toId, amount);
    } catch (Exception e) {
    status.setRollbackOnly();
    result = false;
    System.out.println("Transfer Error!");
    }
    return result;
    }
    });
  }
}

對應(yīng)的XML:

<bean id="bankService"
class="footmark.spring.core.tx.programmatic.template.BankServiceImpl">
  <property name="bankDao" ref="bankDao"/>
  <property name="transactionTemplate" ref="transactionTemplate"/>
</bean>

從結(jié)果來看,好像還是不夠簡單和清晰。下面我們來看聲明式事務(wù)管理,也是比較推薦的方式

聲明式事務(wù)管理

Spring的聲明式事務(wù)管理是基于AOP的,在方法前和后加上切點,用來打開事務(wù)和提交/回滾事務(wù)。

基于TransactionInterceptor的管理

最初,Spring 提供了 TransactionInterceptor 類來實施聲明式事務(wù)管理功能

<beans...>
  ......
  <bean id="transactionInterceptor"
  class="org.springframework.transaction.interceptor.TransactionInterceptor">
    <property name="transactionManager" ref="transactionManager"/>
    <property name="transactionAttributes">
      <props>
        //指定了方法,可以使用通配符
        <prop key="transfer">PROPAGATION_REQUIRED</prop>
      </props>
    </property>
  </bean>
  <bean id="bankServiceTarget"
  class="footmark.spring.core.tx.declare.origin.BankServiceImpl">
  <property name="bankDao" ref="bankDao"/>
  </bean>
  <bean id="bankService"
  class="org.springframework.aop.framework.ProxyFactoryBean">
    <property name="target" ref="bankServiceTarget"/>
    <property name="interceptorNames">
      <list>
        <idref bean="transactionInterceptor"/>
      </list>
    </property>
  </bean>
  ......
</beans>

首先,我們配置了一個 TransactionInterceptor 來定義相關(guān)的事務(wù)規(guī)則,他有兩個主要的屬性:一個是 transactionManager,用來指定一個事務(wù)管理器,并將具體事務(wù)相關(guān)的操作委托給它;另一個是 Properties 類型的 transactionAttributes 屬性,它主要用來定義事務(wù)規(guī)則,該屬性的每一個鍵值對中,鍵指定的是方法名,方法名可以使用通配符,而值就表示相應(yīng)方法的所應(yīng)用的事務(wù)屬性。

指定事務(wù)屬性的取值有較復(fù)雜的規(guī)則,這在 Spring 中算得上是一件讓人頭疼的事。具體的書寫規(guī)則如下:

傳播行為 [,隔離級別] [,只讀屬性] [,超時屬性] [不影響提交的異常] [,導(dǎo)致回滾的異常]

基于 TransactionProxy… 的聲明式事務(wù)管理

前面的聲明式事務(wù)雖然好,但是卻存在一個非常惱人的問題:配置文件太多。

為了緩解這個問題,Spring 為我們提供了 TransactionProxyFactoryBean,用于將TransactionInterceptor 和 ProxyFactoryBean 的配置合二為一

<beans......>
  ......
  <bean id="bankServiceTarget"
  class="footmark.spring.core.tx.declare.classic.BankServiceImpl">
    <property name="bankDao" ref="bankDao"/>
  </bean>
  <bean id="bankService"
  class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    <property name="target" ref="bankServiceTarget"/>
    <property name="transactionManager" ref="transactionManager"/>
    <property name="transactionAttributes">
      <props>
        <prop key="transfer">PROPAGATION_REQUIRED</prop>
      </props>
    </property>
  </bean>
  ......
</beans>

這樣子是減少了proxy的代碼,但是每個service還是需要一個配置。所以我們可以使用自動代理的配置,這樣子就減少了大量的配置。也應(yīng)該是最常用的。

!-- Spring事務(wù)管理 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource" />
</bean>
<!-- 配置事務(wù)的傳播特性 -->
<bean id="baseTransactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true" >
  <property name="transactionManager" ref="transactionManager" />
  <property name="transactionAttributes">
    <props>
      <prop key="add*">PROPAGATION_REQUIRED</prop>
      <prop key="edit*">PROPAGATION_REQUIRED</prop>
      <prop key="remove*">PROPAGATION_REQUIRED</prop>
      <prop key="insert*">PROPAGATION_REQUIRED</prop>
      <prop key="update*">PROPAGATION_REQUIRED</prop>
      <prop key="del*">PROPAGATION_REQUIRED</prop>
      <prop key="*">readOnly</prop>
    </props>
  </property>
</bean>

基于 命名空間的聲明式事務(wù)管理

前面兩種聲明式事務(wù)配置方式奠定了 Spring 聲明式事務(wù)管理的基石。在此基礎(chǔ)上,Spring 2.x 引入了 命名空間,結(jié)合使用 命名空間,帶給開發(fā)人員配置聲明式事務(wù)的全新體驗,配置變得更加簡單和靈活。另外,得益于 命名空間的切點表達(dá)式支持,聲明式事務(wù)也變得更加強大。

具體例子:

<beans......>
  ......
  <bean id="bankService" 
  class="footmark.spring.core.tx.declare.namespace.BankServiceImpl">
    <property name="bankDao" ref="bankDao"/>
  </bean>
  <tx:advice id="bankAdvice" transaction-manager="transactionManager">
    <tx:attributes>
      <tx:method name="transfer" propagation="REQUIRED"/>
    </tx:attributes>
  </tx:advice>
  <aop:config>
    <aop:pointcut id="bankPointcut" expression="execution(* *.transfer(..))"/>
    <aop:advisor advice-ref="bankAdvice" pointcut-ref="bankPointcut"/>
  </aop:config>
  ......
</beans>

@Transactional 的聲明式事務(wù)管理

除了基于命名空間的事務(wù)配置方式,Spring 2.x 還引入了基于 Annotation 的方式,具體主要涉及@Transactional 標(biāo)注。@Transactional 可以作用于接口、接口方法、類以及類方法上。當(dāng)作用于類上時,該類的所有 public 方法將都具有該類型的事務(wù)屬性,同時,我們也可以在方法級別使用該標(biāo)注來覆蓋類級別的定義。

具體例子:

@Transactional(propagation = Propagation.REQUIRED)
public boolean transfer(Long fromId, Long toId, double amount) {
  return bankDao.transfer(fromId, toId, amount);
}

但是使用這種我們就必須啟用tx的annotation:

<tx:annotation-driven transaction-manager="transactionManager"/>

附錄

DataSourceTransactionManager(類主要的方法,就不看原代碼了)

設(shè)置和獲取DataSource

獲取transaction

transaction是否存在

開始transaction

暫停,釋放連接connection

恢復(fù)暫停的連接

提交

回滾

僅回滾

清理


HibernateTransactionManager

轉(zhuǎn)換異常

開始事務(wù)

清理

提交

獲取事務(wù)

恢復(fù)

回滾

僅回滾

暫停

獲取數(shù)據(jù)源

獲取Entity的Interceptor

獲取SessionFactory

是否存在事務(wù)

是否預(yù)先提交

總結(jié)

本文有關(guān)Spring的編程式事務(wù)和聲明式事務(wù)詳解的介紹就到這里,希望對大家有所幫助。有什么問題可以隨時留言,小編會及時回復(fù)大家。在此也非常感謝大家對本站的支持!

相關(guān)文章

  • java socket大數(shù)據(jù)傳輸丟失問題及解決

    java socket大數(shù)據(jù)傳輸丟失問題及解決

    這篇文章主要介紹了java socket大數(shù)據(jù)傳輸丟失問題及解決,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • SpringBoot如何添加WebSocket的方法示例

    SpringBoot如何添加WebSocket的方法示例

    這篇文章主要介紹了SpringBoot如何添加WebSocket的方法示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • Java面向?qū)ο髮崿F(xiàn)汽車租賃系統(tǒng)

    Java面向?qū)ο髮崿F(xiàn)汽車租賃系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了Java面向?qū)ο髮崿F(xiàn)汽車租賃系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • SpringBoot+Vue前后端分離實現(xiàn)請求api跨域問題

    SpringBoot+Vue前后端分離實現(xiàn)請求api跨域問題

    這篇文章主要介紹了SpringBoot+Vue前后端分離實現(xiàn)請求api跨域問題,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • springboot全局日期格式化的兩種方式

    springboot全局日期格式化的兩種方式

    這篇文章主要介紹了springboot全局日期格式化的兩種方式,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • IntelliJ IDEA中如何構(gòu)建Spring Boot的項目

    IntelliJ IDEA中如何構(gòu)建Spring Boot的項目

    這篇文章主要介紹了IntelliJ IDEA中如何構(gòu)建Spring Boot的項目問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • Java面向?qū)ο笾蓡T隱藏與屬性封裝操作示例

    Java面向?qū)ο笾蓡T隱藏與屬性封裝操作示例

    這篇文章主要介紹了Java面向?qū)ο笾蓡T隱藏與屬性封裝操作,結(jié)合實例形式分析了Java面向?qū)ο蟪绦蛟O(shè)計中成員的隱藏及屬性封裝相關(guān)實現(xiàn)與使用操作技巧,需要的朋友可以參考下
    2018-06-06
  • Java實現(xiàn)自定義ArrayList類的示例代碼

    Java實現(xiàn)自定義ArrayList類的示例代碼

    這篇文章主要為大家簡單的介紹ArrayList一下里面的add方法、size方法、isEmpty方法,以及如何實現(xiàn)自定義ArrayList類,感興趣的可以了解一下
    2022-08-08
  • Java instanceof關(guān)鍵字用法詳解及注意事項

    Java instanceof關(guān)鍵字用法詳解及注意事項

    instanceof 是 Java 的保留關(guān)鍵字。它的作用是測試它左邊的對象是否是它右邊的類的實例,返回 boolean 的數(shù)據(jù)類型。本文重點給大家介紹Java instanceof關(guān)鍵字用法詳解及注意事項,需要的朋友參考下吧
    2021-09-09
  • java中設(shè)計模式(多例)的實例詳解

    java中設(shè)計模式(多例)的實例詳解

    這篇文章主要介紹了java中設(shè)計模式(多例)的實例詳解的相關(guān)資料,希望通過本文能幫助到大家,需要的朋友可以參考下
    2017-09-09

最新評論

汉川市| 塔河县| 岫岩| 华亭县| 岳阳县| 右玉县| 虞城县| 临桂县| 上杭县| 深州市| 旺苍县| 洛隆县| 阿坝县| 毕节市| 南召县| 大关县| 黔东| 曲水县| 全南县| 神木县| 合江县| 新密市| 小金县| 阜新市| 徐水县| 兴化市| 蓬莱市| 大港区| 东莞市| 常熟市| 高雄县| 长沙县| 乐安县| 麻江县| 黑水县| 宜章县| 巫溪县| 石门县| 吉隆县| 临潭县| 连江县|