大數據

Spring 5 中文解析數據存儲篇-理解Spring事物抽象

Spring核心篇章:

Spring 5 中文解析之核心篇-IoC容器

Spring 5 中文解析核心篇-IoC容器之依賴關係

Spring 5 中文解析核心篇-IoC容器之Bean作用域

Spring 5 中文解析核心篇-IoC容器之自定義Bean性質

Spring 5 中文解析核心篇-IoC容器之BeanDefinition繼承與容器拓展點

Spring 5 中文解析核心篇-IoC容器之基於註解的容器配置

Spring 5 中文解析核心篇-IoC容器之類路徑掃描和組件管理

Spring 5 中文解析核心篇-IoC容器之JSR330標準註解

Spring 5 中文解析核心篇-IoC容器之基於Java容器配置

Spring 5 中文解析核心篇-IoC容器之Environment抽象

Spring 5 中文解析核心篇-IoC容器之ApplicationContext與BeanFactory

Spring 5 中文解析核心篇-IoC容器之Resources

Spring 5 中文解析核心篇-IoC容器之數據校驗、數據綁定和類型轉換

Spring 5 中文解析核心篇-IoC容器之SpEL表達式

Spring 5 中文解析核心篇-IoC容器之AOP編程(上)")

Spring 5 中文解析核心篇-IoC容器之AOP編程(下)")

Spring 5 中文解析核心篇-IoC容器之Spring AOP API

Spring測試篇章:

Spring 5 中文解析測試篇-Spring測試

Spring 5 中文解析核心篇-集成測試之概要和集成測試註解

Spring 5 中文解析核心篇-集成測試之TestContext(上)")

Spring 5 中文解析核心篇-集成測試之TestContext(中)")

Spring 5 中文解析測試篇-集成測試之TestContext(下)")

Spring 5 中文解析測試篇-Spring MVC測試框架

Spring 5 中文解析測試篇-WebTestClient

Spring存儲篇章:

Spring 5 中文解析數據存儲篇-Spring框架的事物支持模型的優勢

完整電子書地址

1.2 理解Spring框架事物抽象

Spring事務抽象的關鍵是事務策略的概念。事務策略由TransactionManager定義,特別是用於命令式事務管理的org.springframework.transaction.PlatformTransactionManager接口和用於響應式事務管理的org.springframework.transaction.ReactiveTransactionManager接口。以下清單顯示了PlatformTransactionManager API的定義:

public interface PlatformTransactionManager extends TransactionManager {

    TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;

    void commit(TransactionStatus status) throws TransactionException;

    void rollback(TransactionStatus status) throws TransactionException;
}

儘管你可以從應用程序代碼中以編程方式使用它,但它主要是一個服務提供接口(SPI)。由於PlatformTransactionManager是接口,因此可以根據需要輕鬆對其進行模擬或存根。它與JNDI之類的查找策略無關。與Spring框架IoC容器中的任何其他對象(或bean)一樣,定義了PlatformTransactionManager實現。這一優點使Spring框架事務成為值得抽象的,即使在使用JTA時也是如此。與直接使用JTA相比,你可以更輕鬆地測試事務代碼。

同樣,為了與Spring的理念保持一致,可以由任何PlatformTransactionManager接口方法拋出的TransactionException未檢查異常(也就是說,它擴展了java.lang.RuntimeException類)。事物基礎架構故障幾乎總是致命的。在極少數情況下,應用程序代碼實際上可以從事務失敗中恢復,應用程序開發人員仍然可以選擇捕獲和處理TransactionException。實際一點是,開發人員沒有被迫這樣做。

getTransaction(..)方法根據TransactionDefinition參數返回TransactionStatus對象。如果當前調用堆棧中存在匹配的事務,則返回的TransactionStatus可能表示一個新事務或一個現有事務。後一種情況的含義是,與Java EE事務上下文一樣,TransactionStatus與執行線程相關聯。

從Spring框架5.2開始,Spring還為使用響應式類型或Kotlin協程的響應式應用程序提供了事務管理抽象。以下清單顯示了由org.springframework.transaction.ReactiveTransactionManager定義的事務策略:

public interface ReactiveTransactionManager extends TransactionManager {

    Mono<ReactiveTransaction> getReactiveTransaction(TransactionDefinition definition) throws TransactionException;

    Mono<Void> commit(ReactiveTransaction status) throws TransactionException;

    Mono<Void> rollback(ReactiveTransaction status) throws TransactionException;
}

響應式事務管理器主要是服務提供接口(SPI),儘管你可以從應用程序代碼中以編程方式使用它。由於ReactiveTransactionManager是接口,因此可以根據需要輕鬆對其進行模擬或存根。

TransactionDefinition接口指定:

  • 傳播:通常,事務範圍內的所有代碼都在該事務中運行。但是,如果在已存在事務上下文的情況下運行事務方法,則可以指定行為。例如,代碼可以在現有事務中繼續運行(常見情況),或者可以暫停現有事務並創建新事務。Spring提供了EJB CMT熟悉的所有事務傳播選項。要了解有關Spring中事務傳播的語義的信息,請參閱事務傳播
  • 隔離:此事務與其他事務的工作隔離的程度。例如,此事務能否看到其他事務未提交的寫入?
  • 超時:該事務在超時之前將運行多長時間,並由基礎事務基礎結構自動回滾。
  • 只讀狀態:當代碼讀取但不修改數據時,可以使用只讀事務。在某些情況下,例如使用Hibernate時,只讀事務可能是有用的優化。

這些設置反映了標準的事物概念。如有必要,請參考討論事務隔離級別和其他核心事務概念的資源。瞭解這些概念對於使用Spring框架或任何事務管理解決方案至關重要。

TransactionStatus接口為事務代碼提供了一種控制事務執行和查詢事務狀態的簡單方法。這些概念應該很熟悉,因為它們對於所有事務API都是通用的。以下清單顯示了TransactionStatus接口:

public interface TransactionStatus extends TransactionExecution, SavepointManager, Flushable {

    @Override
    boolean isNewTransaction();

    boolean hasSavepoint();

    @Override
    void setRollbackOnly();

    @Override
    boolean isRollbackOnly();

    void flush();

    @Override
    boolean isCompleted();
}

無論你在Spring中選擇聲明式還是編程式事務管理,定義正確的TransactionManager實現都是絕對必要的。通常,你可以通過依賴注入來定義此實現。TransactionManager實現通常需要了解其工作環境:JDBCJTAHibernate等。

TransactionManager實現通常需要了解其工作環境:JDBCJTAHibernate等。以下示例顯示瞭如何定義本地PlatformTransactionManager實現(在這種情況下,使用純JDBC)。

你可以通過創建類似於以下內容的bean來定義JDBC數據源:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="${jdbc.driverClassName}" />
    <property name="url" value="${jdbc.url}" />
    <property name="username" value="${jdbc.username}" />
    <property name="password" value="${jdbc.password}" />
</bean>

然後,相關的PlatformTransactionManager Bean定義將引用DataSource定義。它應類似於以下示例:

<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
</bean>

如果你在Java EE容器中使用JTA,則可以使用通過JNDI獲得的容器DataSource以及Spring的JtaTransactionManager。以下示例顯示了JTAJNDI查找:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/jee
        https://www.springframework.org/schema/jee/spring-jee.xsd">

    <jee:jndi-lookup id="dataSource" jndi-name="jdbc/jpetstore"/>

    <bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager" />

    <!-- other <bean/> definitions here -->

</beans>

JtaTransactionManager不需要了解數據源(或任何其他特定資源),因為它使用了容器的全局事務管理基礎結構。

dataSource bean的先前定義使用jee名稱空間中的標記。有關更多信息,參考JEE Schema

你還可以輕鬆使用Hibernate本地事務,如以下示例所示。在這種情況下,你需要定義一個Hibernate LocalSessionFactoryBean,你的應用程序代碼可使用該Hibernate LocalSessionFactoryBean獲取Hibernate Session實例。

DataSource bean定義與先前顯示的本地JDBC示例相似,因此在以下示例中未顯示。

如果通過JNDI查找數據源(由任何非JTA事務管理器使用)並由Java EE容器管理,則該數據源應該是非事務性的,因為Spring框架(而不是Java EE容器)管理事務。

在這種情況下,txManager bean是HibernateTransactionManager類型。就像DataSourceTransactionManager需要引用數據源一樣,HibernateTransactionManager需要引用SessionFactory。以下示例聲明瞭sessionFactorytxManager bean:

<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="mappingResources">
        <list>
            <value>org/springframework/samples/petclinic/hibernate/petclinic.hbm.xml</value>
        </list>
    </property>
    <property name="hibernateProperties">
        <value>
            hibernate.dialect=${hibernate.dialect}
        </value>
    </property>
</bean>

<bean id="txManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory"/>
</bean>

如果使用Hibernate和Java EE容器管理的JTA事務,則應使用與前面的JDBC JTA示例相同的JtaTransactionManager,如以下示例所示:

<bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>

如果使用JTA,則無論使用哪種數據訪問技術(無論是JDBCHibernate JPA或任何其他受支持的技術),事務管理器定義都應該相同。這是由於JTA事務是全局事務,它可以徵用任何事務資源。

在所有這些情況下,無需更改應用程序代碼。你可以僅通過更改配置來更改事務的管理方式,即使更改意味著從本地事務轉移到全局事務,反之亦然。

作者

個人從事金融行業,就職過易極付、思建科技、某網約車平臺等重慶一流技術團隊,目前就職於某銀行負責統一支付系統建設。自身對金融行業有強烈的愛好。同時也實踐大數據、數據存儲、自動化集成和部署、分佈式微服務、響應式編程、人工智能等領域。同時也熱衷於技術分享創立公眾號和博客站點對知識體系進行分享。關注公眾號:青年IT男 獲取最新技術文章推送!

博客地址: http://youngitman.tech

CSDN: https://blog.csdn.net/liyong1028826685

微信公眾號:

技術交流群:

Leave a Reply

Your email address will not be published. Required fields are marked *