天天看點

Spring架構 -- 聲明式事務

一、事務

1. 事務定義

  是一組執行單元,這個執行單元的各個組成部分要麼同時執行成功,要麼同時執行失敗。

2. 事務特性(ACID)

具有4個基本特性:原子性、一緻性、隔離性、持久性

  • 原子性(Automicity):一個事務是一個不可再分割的工作機關,事務中的全部操作要麼都做,要麼都不做;
  • 一緻性(Consistency):事務必須是使得資料庫狀态從一個一緻性狀态,轉變到另外一個一緻性狀态。也就是說在事務前和事務後,被操作的目标資源狀态一緻。比如銀行轉賬案例中,轉賬前和轉賬後總賬不變;
  • 隔離性(Isolation):一個事務的執行不能被其他事務所影響,即一個事務内部的操作及使用的資料對并發的其他事務是隔離的,多個并發事務之間不能互相幹擾;
  • 持久性(Durability):一個事務一旦送出,它對資料庫中資料的改變會永久存儲起來,其他操作不會對它産生影響。

二、Spring中的事務管理

Spring在不同的事務管理API之上定義了一個抽象層,使得開發人員不必了解底層的事務管理API就可以使用Spring的事務管理機制。Spring支援程式設計式事務管理和聲明式的事務管理。

1. 程式設計式事務管理

  将事務管理代碼嵌到業務方法中來控制事務的送出和復原

  缺點:必須在每個事務操作業務邏輯中包含額外的事務管理代碼

2. 聲明式事務管理

  一般情況下比程式設計式事務好用,将事務管理代碼從業務方法中分離出來,以聲明的方式來實作事務管理。将事務管理作為橫切關注點,通過AOP方法子產品化,Spring中通過Spring AOP架構支援聲明式事務管理。

三、Spring聲明式事務管理

1. 前言

  • JavaEE 體系進行分層開發,事務處理位于業務層, Spring 提供了分層設計業務層的事務處了解決方案;
  • Spring 架構為我們提供了一組事務控制的接口;
  • Spring 的事務控制都是基于 AOP 的,它既可以使用程式設計的方式實作,也可以使用配置的方式實作。

2. 事務管理器

  Spring的核心事務管理抽象,管理封裝了一組獨立于技術的方法,無論使用Spring的哪種事務管理政策(程式設計式或者聲明式)事務管理器都是必須的。

org.springframework.transaction.PlatformTransactionManager

,此接口是 Spring 的事務管理器,它提供了常用的操作事務的方法

Spring架構 -- 聲明式事務

PlaformTransactionManager

接口,包含三個方法:

  • 擷取事務狀态資訊:

    TransactionStatus getTransaction(TransactionDefinition definition)

  • 送出事務:

    void commit(TransactionStatus status)

  • 復原事務:

    void rollback(TransactionStatis status)

在開發中通常使用其實作類,如:

  • SpringJDBC 或 iBatis 進行持久化資料時使用

    org.springframework.jdbc.datasource.DataSourceTransactionManager

  • Hibernate 版本進行持久化資料時使用

    org.springframework.orm.hibernate5.HibernateTransactionManager

3. 事務

JDBC事務

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

Hibernate事務

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

JPA事務

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>
           

Java原生API事務

通常用于跨越多個事務管理源(多資料源),則需要使用下面的内容

<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
    <property name="transactionManagerName" value="java:/TransactionManager" />
</bean>
           

四、事務屬性

Spring架構 -- 聲明式事務

1. 事務隔離級别

并發事務會導緻發生以下三種類型的問題:

問題 例如
髒讀 一個事務讀取了另一個事務改寫尚未送出的資料時,改寫的資料被復原了,那麼第一個事務擷取的資料無效
不可重複讀 當同一個事務執行兩次及以上相同的查詢時,每次都得到不同的資料。一般因為另一并發事務在兩次查詢期間進行了更新
幻讀 第一個事務讀取一些資料,此時第二個事務在該表中插入了一些新資料,這時第一個事務再讀取相同的資料就會多幾行

不可重複讀和幻讀的差別:不可重複讀側重點在相同資料被修改,而幻讀是删除或新增

Spring中事務的隔離級别可以通過隔離屬性指定

Spring架構 -- 聲明式事務

從理論上講,事務應該完全隔離,避免并發事務導緻的問題,但是這樣可能對性能産生極大影響,因為事務必須按順序進行了。是以在實際的開發中,為了提升性能,事務會以比較低的隔離級别運作。

2. 事務傳播行為

  事務方法被另一個事務方法調用時,必須指定事務應該如何傳播。例如方法可能繼續在現有事務中運作,也可能開啟一個新的事務,并在自己的事務運作,Spring中的事務傳播行為可以由傳播屬性指定。

Spring架構 -- 聲明式事務
  • REQUIRED

    :目前方法必須有事務環境,如果目前方法已經有事務環境就加入,如果目前方法沒有事務環境就建立一個新的事務;适合增删改操作;
  • SUPPORTS

    :表示目前方法支援事務,有事務可以運作沒有事務也可以;适合查詢操作;
  • REQUERS_NEW

    :目前方法必須有事務環境;不管目前方法有沒有事務,都建立一個新的事務。

目前事務挂起:意思是先執行剛建立的事務,剛建立事務執行完後,再執行剛挂起的事務。

3. 事務的逾時時間

  事務可以在行和表上獲得鎖,是以長事務會占用資源,并對整體性能産生影響。可以配置逾時事務屬性,事務在強制復原之前可以保持多久,這樣可以避免長期運作的事務占用資源。

  預設值是-1,沒有逾時限制;如果要設定,以秒為機關。

4. 是否是隻讀事務

  如果事務隻讀資料但不修改可以通過配置隻讀事務屬性,幫助資料庫引擎優化事務。隻讀事務屬性:表示這個事務隻讀讀取資料,但是不更新資料建議查詢時設定為隻讀。

五、XML方式實作事務

1. pom.xml添加依賴

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.0.2.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.0.2.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
    <version>5.0.2.RELEASE</version>
</dependency>
<!--aop支援-->
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.8.7</version>
</dependency>
           

2. ApplicationContext.xml配置事務

<!--1.開啟注解掃描-->
<context:component-scan base-package="com.zz"/>

<!--5.Spring聲明式事務配置-->
<!--5.1 配置事務管理器(事務切面)-->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
</bean>
<!--5.2 配置事務通知規則(攔截到方法後如何管理事務)-->
<tx:advice id="txAdvice" transaction-manager="txManager">
    <tx:attributes>
        <!--find/select/get開頭的方法,有事務可以無事務也可以,隻讀的事務-->
        <tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
        <tx:method name="select*" propagation="SUPPORTS" read-only="true"/>
        <tx:method name="get*" propagation="SUPPORTS" read-only="true"/>
        <!--* 表示其他所有的方法就是指增删改操作,必須有事務環境,讀寫事務-->
        <tx:method name="*" propagation="REQUIRED" read-only="false"/>
    </tx:attributes>
</tx:advice>
<!--5.3 Aop配置:切入點表達式 + 通知規則-->
<aop:config>
    <!--5.3.1 配置切入點表達式-->
    <aop:pointcut id="pt" expression="execution(* com.itheima.service.impl.*ServiceImpl.*(..))" />
    <!--5.3.2 建立切入點表達式與通知規則的關系-->
    <aop:advisor advice-ref="txAdvice" pointcut-ref="pt"/>
</aop:config>
           

六、注解方式實作事務

1. 修改ApplicationContext.xml

Spring架構 -- 聲明式事務

2. service層使用注解

/**
 * @Transactional 事務注解支援
 * 1. 可以修飾在實作類上,表示目前實作類的所有方法都應用事務。
 * 2. 也可以修飾在方法上,表示目前方法應用事務。
 * 3. 還可以修飾在接口上,表示目前的接口的所有實作類都應用事務。
 * 4. 也可以修飾在接口方法上,表示所有實作該方法的地方都自動應用事務。
 * 5. 事務屬性
 *    propagation = Propagation.REQUIRED 表示目前運作方法必須有事務環境
 *    readOnly = false 表示讀寫事務
 *    noRollbackFor = ArithmeticException.class 遇到指定的異常不復原
 */
@Service
@Transactional
public class AccountServiceImpl implements IAccountService {
    // 注入dao
    @Autowired
    private IAccountDao accountDao;

    @Override
    public void save(Account account) {
        accountDao.save(account);
        //int i=1/0;//如果沒有用事務,資料庫會多一條資料。有用事務,資料庫不會變化。
        String str = null;str.length();
        accountDao.save(account);
    }
}
           

七、總結

1. Spring聲明式事務原理:Aop

  • 1)切面類:

    DataSourceTransactionManagerSpring

    已經提供,且針對不同的持久層實作技術,提供了不同的事務實作;
  • 2)AOP 關鍵

      切入點表達式,隻要目标對象符合切入點表達式規則,就可以聲明代理對象;

      自動代理:根據目标對象有實作接口,使用JDK代理;目标對象沒有實作接口,使用CGLib代理。

2. Spring聲明式事務特點

優點:

  • 解耦,事務控制代碼與業務代碼完全解耦;
  • 友善維護,假如項目不想用事務,直接移除配置;如果更換了持久層,事務控制隻需要修改事務管理器即可。

缺點:

  Spring聲明式事務原理是AOP,AOP原理是代理,代理隻能對方法進行攔截,是以Spring的聲明式事務隻能對方法進行事務控制,不能對方法的某幾行進行事務控制。

3. 事務粒度

  • 粗粒度事務控制:Spring聲明式事務控制就是粗粒度事務控制,是方法級别的事務控制
  • 細粒度事務控制:一般都是指程式設計式事務控制,通過代碼手動控制事務。(耦合,重複代碼多)

參考:【Spring】-- 聲明式事務配置詳解