溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Spring事務(wù)的知識(shí)點(diǎn)有哪些

發(fā)布時(shí)間:2021-12-21 13:45:07 來源:億速云 閱讀:129 作者:iii 欄目:編程語言

這篇文章主要介紹“Spring事務(wù)的知識(shí)點(diǎn)有哪些”,在日常操作中,相信很多人在Spring事務(wù)的知識(shí)點(diǎn)有哪些問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對(duì)大家解答”Spring事務(wù)的知識(shí)點(diǎn)有哪些”的疑惑有所幫助!接下來,請(qǐng)跟著小編一起來學(xué)習(xí)吧!

數(shù)據(jù)庫事務(wù)概述

事務(wù)首先是一系列操作組成的工作單元,該工作單元內(nèi)的操作是不可分割的,即要么所有操作都做,要么所有操作都不做,這就是事務(wù)。

事務(wù)必需滿足ACID(原子性、一致性、隔離性和持久性)特性,缺一不可:

  • 原子性(Atomicity):即事務(wù)是不可分割的最小工作單元,事務(wù)內(nèi)的操作要么全做,要么全不做;

  • 一致性(Consistency):在事務(wù)執(zhí)行前數(shù)據(jù)庫的數(shù)據(jù)處于正確的狀態(tài),而事務(wù)執(zhí)行完成后數(shù)據(jù)庫的數(shù)據(jù)還是處于正確的狀態(tài),即數(shù)據(jù)完整性約束沒有被破壞;如銀行轉(zhuǎn)帳,A轉(zhuǎn)帳給B,必須保證A的錢一定轉(zhuǎn)給B,一定不會(huì)出現(xiàn)A的錢轉(zhuǎn)了但B沒收到,否則數(shù)據(jù)庫的數(shù)據(jù)就處于不一致(不正確)的狀態(tài)。

  • 隔離性(Isolation):并發(fā)事務(wù)執(zhí)行之間無影響,在一個(gè)事務(wù)內(nèi)部的操作對(duì)其他事務(wù)是不產(chǎn)生影響,這需要事務(wù)隔離級(jí)別來指定隔離性;

  • 持久性(Durability):事務(wù)一旦執(zhí)行成功,它對(duì)數(shù)據(jù)庫的數(shù)據(jù)的改變必須是永久的,不會(huì)因比如遇到系統(tǒng)故障或斷電造成數(shù)據(jù)不一致或丟失。

在實(shí)際項(xiàng)目開發(fā)中數(shù)據(jù)庫操作一般都是并發(fā)執(zhí)行的,即有多個(gè)事務(wù)并發(fā)執(zhí)行,并發(fā)執(zhí)行就可能遇到問題,目前常見的問題如下:

  • 丟失更新:兩個(gè)事務(wù)同時(shí)更新一行數(shù)據(jù),最后一個(gè)事務(wù)的更新會(huì)覆蓋掉第一個(gè)事務(wù)的更新,從而導(dǎo)致第一個(gè)事務(wù)更新的數(shù)據(jù)丟失,這是由于沒有加鎖造成的;

  • 臟讀:一個(gè)事務(wù)看到了另一個(gè)事務(wù)未提交的更新數(shù)據(jù);

  • 不可重復(fù)讀:在同一事務(wù)中,多次讀取同一數(shù)據(jù)卻返回不同的結(jié)果;也就是有其他事務(wù)更改了這些數(shù)據(jù);

  • 幻讀:一個(gè)事務(wù)在執(zhí)行過程中讀取到了另一個(gè)事務(wù)已提交的插入數(shù)據(jù);即在第一個(gè)事務(wù)開始時(shí)讀取到一批數(shù)據(jù),但此后另一個(gè)事務(wù)又插入了新數(shù)據(jù)并提交,此時(shí)第一個(gè)事務(wù)又讀取這批數(shù)據(jù)但發(fā)現(xiàn)多了一條,即好像發(fā)生幻覺一樣。

為了解決這些并發(fā)問題,需要通過數(shù)據(jù)庫隔離級(jí)別來解決,在標(biāo)準(zhǔn)SQL規(guī)范中定義了四種隔離級(jí)別:

  • 未提交讀(Read Uncommitted):最低隔離級(jí)別,一個(gè)事務(wù)能讀取到別的事務(wù)未提交的更新數(shù)據(jù),很不安全,可能出現(xiàn)丟失更新、臟讀、不可重復(fù)讀、幻讀;

  • 提交讀(Read Committed):一個(gè)事務(wù)能讀取到別的事務(wù)提交的更新數(shù)據(jù),不能看到未提交的更新數(shù)據(jù),不可能可能出現(xiàn)丟失更新、臟讀,但可能出現(xiàn)不可重復(fù)讀、幻讀;

  • 可重復(fù)讀(Repeatable Read):保證同一事務(wù)中先后執(zhí)行的多次查詢將返回同一結(jié)果,不受其他事務(wù)影響,可能可能出現(xiàn)丟失更新、臟讀、不可重復(fù)讀,但可能出現(xiàn)幻讀;

  • 序列化(Serializable):最高隔離級(jí)別,不允許事務(wù)并發(fā)執(zhí)行,而必須串行化執(zhí)行,最安全,不可能出現(xiàn)更新、臟讀、不可重復(fù)讀、幻讀。

隔離級(jí)別越高,數(shù)據(jù)庫事務(wù)并發(fā)執(zhí)行性能越差,能處理的操作越少。因此在實(shí)際項(xiàng)目開發(fā)中為了考慮并發(fā)性能一般使用提交讀隔離級(jí)別,它能避免丟失更新和臟讀,盡管不可重復(fù)讀和幻讀不能避免,但可以在可能出現(xiàn)的場合使用悲觀鎖或樂觀鎖來解決這些問題。

事務(wù)類型

數(shù)據(jù)庫事務(wù)類型有本地事務(wù)和分布式事務(wù):

  • 本地事務(wù):就是普通事務(wù),能保證單臺(tái)數(shù)據(jù)庫上的操作的ACID,被限定在一臺(tái)數(shù)據(jù)庫上;

  • 分布式事務(wù):涉及兩個(gè)或多個(gè)數(shù)據(jù)庫源的事務(wù),即跨越多臺(tái)同類或異類數(shù)據(jù)庫的事務(wù)(由每臺(tái)數(shù)據(jù)庫的本地事務(wù)組成的),分布式事務(wù)旨在保證這些本地事務(wù)的所有操作的ACID,使事務(wù)可以跨越多臺(tái)數(shù)據(jù)庫;

Java事務(wù)類型有JDBC事務(wù)和JTA事務(wù):

  • JDBC事務(wù):就是數(shù)據(jù)庫事務(wù)類型中的本地事務(wù),通過Connection對(duì)象的控制來管理事務(wù);

  • JTA事務(wù):JTA指Java事務(wù)API(Java Transaction API),是Java EE數(shù)據(jù)庫事務(wù)規(guī)范, JTA只提供了事務(wù)管理接口,由應(yīng)用程序服務(wù)器廠商(如WebSphere Application Server)提供實(shí)現(xiàn),JTA事務(wù)比JDBC更強(qiáng)大,支持分布式事務(wù)。

Java EE事務(wù)類型有本地事務(wù)和全局事務(wù):

  • 本地事務(wù):使用JDBC編程實(shí)現(xiàn)事務(wù);

  • 全局事務(wù):由應(yīng)用程序服務(wù)器提供,使用JTA事務(wù);

按是否通過編程實(shí)現(xiàn)事務(wù)有聲明式事務(wù)和編程式事務(wù);

  • 聲明式事務(wù): 通過注解或XML配置文件指定事務(wù)信息;

  • 編程式事務(wù):通過編寫代碼實(shí)現(xiàn)事務(wù)。

Spring提供的事務(wù)管理

Spring框架最核心功能之一就是事務(wù)管理,而且提供一致的事務(wù)管理抽象,這能幫助我們:

  • 提供一致的編程式事務(wù)管理API,不管使用Spring JDBC框架還是集成第三方框架使用該API進(jìn)行事務(wù)編程;

  • 無侵入式的聲明式事務(wù)支持。

Spring支持聲明式事務(wù)和編程式事務(wù)事務(wù)類型。

spring事務(wù)特性

spring所有的事務(wù)管理策略類都繼承自org.springframework.transaction.PlatformTransactionManager接口

其中TransactionDefinition接口定義以下特性:

事務(wù)隔離級(jí)別

隔離級(jí)別是指若干個(gè)并發(fā)的事務(wù)之間的隔離程度。TransactionDefinition 接口中定義了五個(gè)表示隔離級(jí)別的常量:

  • TransactionDefinition.ISOLATION_DEFAULT:這是默認(rèn)值,表示使用底層數(shù)據(jù)庫的默認(rèn)隔離級(jí)別。對(duì)大部分?jǐn)?shù)據(jù)庫而言,通常這值就是TransactionDefinition.ISOLATION_READ_COMMITTED。

  • TransactionDefinition.ISOLATION_READ_UNCOMMITTED:該隔離級(jí)別表示一個(gè)事務(wù)可以讀取另一個(gè)事務(wù)修改但還沒有提交的數(shù)據(jù)。該級(jí)別不能防止臟讀,不可重復(fù)讀和幻讀,因此很少使用該隔離級(jí)別。比如PostgreSQL實(shí)際上并沒有此級(jí)別。

  • TransactionDefinition.ISOLATION_READ_COMMITTED:該隔離級(jí)別表示一個(gè)事務(wù)只能讀取另一個(gè)事務(wù)已經(jīng)提交的數(shù)據(jù)。該級(jí)別可以防止臟讀,這也是大多數(shù)情況下的推薦值。

  • TransactionDefinition.ISOLATION_REPEATABLE_READ:該隔離級(jí)別表示一個(gè)事務(wù)在整個(gè)過程中可以多次重復(fù)執(zhí)行某個(gè)查詢,并且每次返回的記錄都相同。該級(jí)別可以防止臟讀和不可重復(fù)讀。

  • TransactionDefinition.ISOLATION_SERIALIZABLE:所有的事務(wù)依次逐個(gè)執(zhí)行,這樣事務(wù)之間就完全不可能產(chǎn)生干擾,也就是說,該級(jí)別可以防止臟讀、不可重復(fù)讀以及幻讀。但是這將嚴(yán)重影響程序的性能。通常情況下也不會(huì)用到該級(jí)別。

事務(wù)傳播行為

  所謂事務(wù)的傳播行為是指,如果在開始當(dāng)前事務(wù)之前,一個(gè)事務(wù)上下文已經(jīng)存在,此時(shí)有若干選項(xiàng)可以指定一個(gè)事務(wù)性方法的執(zhí)行行為。在TransactionDefinition定義中包括了如下幾個(gè)表示傳播行為的常量:
  • TransactionDefinition.PROPAGATION_REQUIRED:如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒有事務(wù),則創(chuàng)建一個(gè)新的事務(wù)。這是默認(rèn)值。

  • TransactionDefinition.PROPAGATION_REQUIRES_NEW:創(chuàng)建一個(gè)新的事務(wù),如果當(dāng)前存在事務(wù),則把當(dāng)前事務(wù)掛起。

  • TransactionDefinition.PROPAGATION_SUPPORTS:如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒有事務(wù),則以非事務(wù)的方式繼續(xù)運(yùn)行。

  • TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事務(wù)方式運(yùn)行,如果當(dāng)前存在事務(wù),則把當(dāng)前事務(wù)掛起。

  • TransactionDefinition.PROPAGATION_NEVER:以非事務(wù)方式運(yùn)行,如果當(dāng)前存在事務(wù),則拋出異常。

  • TransactionDefinition.PROPAGATION_MANDATORY:如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒有事務(wù),則拋出異常。

  • TransactionDefinition.PROPAGATION_NESTED:如果當(dāng)前存在事務(wù),則創(chuàng)建一個(gè)事務(wù)作為當(dāng)前事務(wù)的嵌套事務(wù)來運(yùn)行;如果當(dāng)前沒有事務(wù),則該取值等價(jià)于TransactionDefinition.PROPAGATION_REQUIRED。

事務(wù)超時(shí)

  所謂事務(wù)超時(shí),就是指一個(gè)事務(wù)所允許執(zhí)行的最長時(shí)間,如果超過該時(shí)間限制但事務(wù)還沒有完成,則自動(dòng)回滾事務(wù)。在 TransactionDefinition 中以 int 的值來表示超時(shí)時(shí)間,其單位是秒。

默認(rèn)設(shè)置為底層事務(wù)系統(tǒng)的超時(shí)值,如果底層數(shù)據(jù)庫事務(wù)系統(tǒng)沒有設(shè)置超時(shí)值,那么就是none,沒有超時(shí)限制。

事務(wù)只讀屬性

  只讀事務(wù)用于客戶代碼只讀但不修改數(shù)據(jù)的情形,只讀事務(wù)用于特定情景下的優(yōu)化,比如使用Hibernate的時(shí)候。

默認(rèn)為讀寫事務(wù)。

概述

Spring框架支持事務(wù)管理的核心是事務(wù)管理器抽象,對(duì)于不同的數(shù)據(jù)訪問框架(如Hibernate)通過實(shí)現(xiàn)策略接口PlatformTransactionManager,從而能支持各種數(shù)據(jù)訪問框架的事務(wù)管理,PlatformTransactionManager接口定義如下:

java代碼:

public interface PlatformTransactionManager {
       TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;
       void commit(TransactionStatus status) throws TransactionException;
       void rollback(TransactionStatus status) throws TransactionException;
}
  • getTransaction():返回一個(gè)已經(jīng)激活的事務(wù)或創(chuàng)建一個(gè)新的事務(wù)(根據(jù)給定的TransactionDefinition類型參數(shù)定義的事務(wù)屬性),返回的是TransactionStatus對(duì)象代表了當(dāng)前事務(wù)的狀態(tài),其中該方法拋出TransactionException(未檢查異常)表示事務(wù)由于某種原因失敗。

  • commit():用于提交TransactionStatus參數(shù)代表的事務(wù),具體語義請(qǐng)參考Spring Javadoc;

  • rollback():用于回滾TransactionStatus參數(shù)代表的事務(wù),具體語義請(qǐng)參考Spring Javadoc。

TransactionDefinition接口定義如下:

java代碼:

public interface TransactionDefinition {
       int getPropagationBehavior();
       int getIsolationLevel();
       int getTimeout();
       boolean isReadOnly();
       String getName();
}
  • getPropagationBehavior():返回定義的事務(wù)傳播行為;

  • getIsolationLevel():返回定義的事務(wù)隔離級(jí)別;

  • getTimeout():返回定義的事務(wù)超時(shí)時(shí)間;

  • isReadOnly():返回定義的事務(wù)是否是只讀的;

  • getName():返回定義的事務(wù)名字。

TransactionStatus接口定義如下:

java代碼:

public interface TransactionStatus extends SavepointManager {
       boolean isNewTransaction();
       boolean hasSavepoint();
       void setRollbackOnly();
       boolean isRollbackOnly();
       void flush();
       boolean isCompleted();
}
  • isNewTransaction():返回當(dāng)前事務(wù)狀態(tài)是否是新事務(wù);

  • hasSavepoint():返回當(dāng)前事務(wù)是否有保存點(diǎn);

  • setRollbackOnly():設(shè)置當(dāng)前事務(wù)應(yīng)該回滾;

  • isRollbackOnly(():返回當(dāng)前事務(wù)是否應(yīng)該回滾;

  • flush():用于刷新底層會(huì)話中的修改到數(shù)據(jù)庫,一般用于刷新如Hibernate/JPA的會(huì)話,可能對(duì)如JDBC類型的事務(wù)無任何影響;

  • isCompleted():當(dāng)前事務(wù)否已經(jīng)完成。

內(nèi)置事務(wù)管理器實(shí)現(xiàn)

Spring提供了許多內(nèi)置事務(wù)管理器實(shí)現(xiàn):

  • DataSourceTransactionManager:位于org.springframework.jdbc.datasource包中,數(shù)據(jù)源事務(wù)管理器,提供對(duì)單個(gè)javax.sql.DataSource事務(wù)管理,用于Spring JDBC抽象框架、iBATIS或MyBatis框架的事務(wù)管理;

  • JdoTransactionManager:位于org.springframework.orm.jdo包中,提供對(duì)單個(gè)javax.jdo.PersistenceManagerFactory事務(wù)管理,用于集成JDO框架時(shí)的事務(wù)管理;

  • JpaTransactionManager:位于org.springframework.orm.jpa包中,提供對(duì)單個(gè)javax.persistence.EntityManagerFactory事務(wù)支持,用于集成JPA實(shí)現(xiàn)框架時(shí)的事務(wù)管理;

  • HibernateTransactionManager:位于org.springframework.orm.hibernate3包中,提供對(duì)單個(gè)org.hibernate.SessionFactory事務(wù)支持,用于集成Hibernate框架時(shí)的事務(wù)管理;該事務(wù)管理器只支持Hibernate3+版本,且Spring3.0+版本只支持Hibernate 3.2+版本;

  • JtaTransactionManager:位于org.springframework.transaction.jta包中,提供對(duì)分布式事務(wù)管理的支持,并將事務(wù)管理委托給Java EE應(yīng)用服務(wù)器事務(wù)管理器;

  • OC4JjtaTransactionManager:位于org.springframework.transaction.jta包中,Spring提供的對(duì)OC4J10.1.3+應(yīng)用服務(wù)器事務(wù)管理器的適配器,此適配器用于對(duì)應(yīng)用服務(wù)器提供的高級(jí)事務(wù)的支持;

  • WebSphereUowTransactionManager:位于org.springframework.transaction.jta包中,Spring提供的對(duì)WebSphere 6.0+應(yīng)用服務(wù)器事務(wù)管理器的適配器,此適配器用于對(duì)應(yīng)用服務(wù)器提供的高級(jí)事務(wù)的支持;

  • WebLogicJtaTransactionManager:位于org.springframework.transaction.jta包中,Spring提供的對(duì)WebLogic 8.1+應(yīng)用服務(wù)器事務(wù)管理器的適配器,此適配器用于對(duì)應(yīng)用服務(wù)器提供的高級(jí)事務(wù)的支持。

Spring不僅提供這些事務(wù)管理器,還提供對(duì)如JMS事務(wù)管理的管理器等,Spring提供一致的事務(wù)抽象如圖9-1所示。
Spring事務(wù)的知識(shí)點(diǎn)有哪些

圖9-1 Spring事務(wù)管理器

接下來讓我們學(xué)習(xí)一下如何在Spring配置文件中定義事務(wù)管理器:

一、聲明對(duì)本地事務(wù)的支持:

a)JDBC及iBATIS、MyBatis框架事務(wù)管理器

java代碼:

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

通過dataSource屬性指定需要事務(wù)管理的單個(gè)javax.sql.DataSource對(duì)象。

b)Jdo事務(wù)管理器

java代碼:

<bean id="txManager" class="org.springframework.orm.jdo.JdoTransactionManager">
    <property name="persistenceManagerFactory" ref="persistenceManagerFactory"/>
</bean>

通過persistenceManagerFactory屬性指定需要事務(wù)管理的javax.jdo.PersistenceManagerFactory對(duì)象。

c)Jpa事務(wù)管理器

java代碼:

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

通過entityManagerFactory屬性指定需要事務(wù)管理的javax.persistence.EntityManagerFactory對(duì)象。

還需要為entityManagerFactory對(duì)象指定jpaDialect屬性,該屬性所對(duì)應(yīng)的對(duì)象指定了如何獲取連接對(duì)象、開啟事務(wù)、關(guān)閉事務(wù)等事務(wù)管理相關(guān)的行為。

java代碼:

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        ……
        <property name="jpaDialect" ref="jpaDialect"/>
</bean>
<bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>

d)Hibernate事務(wù)管理器

java代碼:

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

通過entityManagerFactory屬性指定需要事務(wù)管理的org.hibernate.SessionFactory對(duì)象。

聲明式事務(wù)

聲明式事務(wù)概述

從上節(jié)編程式實(shí)現(xiàn)事務(wù)管理可以深刻體會(huì)到編程式事務(wù)的痛苦,即使通過代理配置方式也是不小的工作量。

本節(jié)將介紹聲明式事務(wù)支持,使用該方式后最大的獲益是簡單,事務(wù)管理不再是令人痛苦的,而且此方式屬于無侵入式,對(duì)業(yè)務(wù)邏輯實(shí)現(xiàn)無影響。

接下來先來看看聲明式事務(wù)如何實(shí)現(xiàn)吧。

聲明式實(shí)現(xiàn)事務(wù)管理

1、定義業(yè)務(wù)邏輯實(shí)現(xiàn),此處使用ConfigUserServiceImpl和ConfigAddressServiceImpl:

2、定義配置文件(chapter9/service/ applicationContext-service-declare.xml):

2.1、XML命名空間定義,定義用于事務(wù)支持的tx命名空間和AOP支持的aop命名空間:

java代碼:
<beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:tx="http://www.springframework.org/schema/tx"
      xmlns:aop="http://www.springframework.org/schema/aop"
      xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

2.2、業(yè)務(wù)實(shí)現(xiàn)配置,非常簡單,使用以前定義的非侵入式業(yè)務(wù)實(shí)現(xiàn):

java代碼:
<bean id="userService" class="cn.javass.spring.chapter9.service.impl.ConfigUserServiceImpl">
    <property name="userDao" ref="userDao"/>
    <property name="addressService" ref="addressService"/>
</bean>
<bean id="addressService" class="cn.javass.spring.chapter9.service.impl.ConfigAddressServiceImpl">
    <property name="addressDao" ref="addressDao"/>
</bean>

2.3、事務(wù)相關(guān)配置:

java代碼:
<tx:advice id="txAdvice" transaction-manager="txManager">
    <tx:attributes>
        <tx:method name="save*" propagation="REQUIRED" isolation="READ_COMMITTED"/>
        <tx:method name="*" propagation="REQUIRED" isolation="READ_COMMITTED" read-only="true"/>
    </tx:attributes>
</tx:advice>

java代碼:

<tx:advice>:事務(wù)通知定義,用于指定事務(wù)屬性,其中“transaction-manager”屬性指定事務(wù)管理器,并通過< tx:attributes >指定具體需要攔截的方法;
 <tx:method name=”save*”>:表示將攔截以save開頭的方法,被攔截的方法將應(yīng)用配置的事務(wù)屬性:propagation=”REQUIRED”表示傳播行為是Required,isolation=”READ_COMMITTED”表示隔離級(jí)別是提交讀;
<tx:method name=”*”>:表示將攔截其他所有方法,被攔截的方法將應(yīng)用配置的事務(wù)屬性:propagation=”REQUIRED”表示傳播行為是Required,isolation=”READ_COMMITTED”表示隔離級(jí)別是提交讀,read-only=”true”表示事務(wù)只讀;
:AOP相關(guān)配置:
:切入點(diǎn)定義,定義名為”serviceMethod”的aspectj切入點(diǎn),切入點(diǎn)表達(dá)式為”execution(* cn..chapter9.service..*.*(..))”表示攔截cn包及子包下的chapter9\. service包及子包下的任何類的任何方法;
:Advisor定義,其中切入點(diǎn)為serviceMethod,通知為txAdvice。
從配置中可以看出,將對(duì)cn包及子包下的chapter9\. service包及子包下的任何類的任何方法應(yīng)用“txAdvice”通知指定的事務(wù)屬性。

3、修改測試方法并測試該配置方式是否好用:

將TransactionTest 類的testServiceTransaction測試方法拷貝一份命名為testDeclareTransaction:

并在testDeclareTransaction測試方法內(nèi)將:

4、執(zhí)行測試,測試正常通過,說明該方式能正常工作,當(dāng)調(diào)用save方法時(shí)將匹配到事務(wù)通知中定義的“”中指定的事務(wù)屬性,而調(diào)用countAll方法時(shí)將匹配到事務(wù)通知中定義的“”中指定的事務(wù)屬性。

聲明式事務(wù)是如何實(shí)現(xiàn)事務(wù)管理的呢?還記不記得TransactionProxyFactoryBean實(shí)現(xiàn)配置式事務(wù)管理,配置式事務(wù)管理是通過代理方式實(shí)現(xiàn),而聲明式事務(wù)管理同樣是通過AOP代理方式實(shí)現(xiàn)。

聲明式事務(wù)通過AOP代理方式實(shí)現(xiàn)事務(wù)管理,利用環(huán)繞通知TransactionInterceptor實(shí)現(xiàn)事務(wù)的開啟及關(guān)閉,而TransactionProxyFactoryBean內(nèi)部也是通過該環(huán)繞通知實(shí)現(xiàn)的,因此可以認(rèn)為是幫你定義了TransactionProxyFactoryBean,從而簡化事務(wù)管理。

了解了實(shí)現(xiàn)方式后,接下來詳細(xì)學(xué)習(xí)一下配置吧:

9.4.4配置詳解
聲明式事務(wù)管理通過配置來定義事務(wù)屬性,配置方式如下所示:

java代碼:
<tx:advice id="……" transaction-manager="……">
<tx:attributes>
        <tx:method name="……"
                           propagation=" REQUIRED"
                           isolation="READ_COMMITTED"
                           timeout="-1"
                           read-only="false"
                           no-rollback-for=""
                           rollback-for=""/>
        ……
    </tx:attributes>
</tx:advice>
<tx:advice>:id用于指定此通知的名字, transaction-manager用于指定事務(wù)管理器,默認(rèn)的事務(wù)管理器名字為“transactionManager”;
<tx:method>:用于定義事務(wù)屬性即相關(guān)聯(lián)的方法名;

name:定義與事務(wù)屬性相關(guān)聯(lián)的方法名,將對(duì)匹配的方法應(yīng)用定義的事務(wù)屬性,可以使用“”通配符來匹配一組或所有方法,如“save”將匹配以save開頭的方法,而“*”將匹配所有方法;

propagation:事務(wù)傳播行為定義,默認(rèn)為“REQUIRED”,表示Required,其值可以通過TransactionDefinition的靜態(tài)傳播行為變量的“PROPAGATION_”后邊部分指定,如“TransactionDefinition.PROPAGATION_REQUIRED”可以使用“REQUIRED”指定;

isolation:事務(wù)隔離級(jí)別定義;默認(rèn)為“DEFAULT”,其值可以通過TransactionDefinition的靜態(tài)隔離級(jí)別變量的“ISOLATION_”后邊部分指定,如“TransactionDefinition. ISOLATION_DEFAULT”可以使用“DEFAULT”指定:

timeout:事務(wù)超時(shí)時(shí)間設(shè)置,單位為秒,默認(rèn)-1,表示事務(wù)超時(shí)將依賴于底層事務(wù)系統(tǒng);

read-only:事務(wù)只讀設(shè)置,默認(rèn)為false,表示不是只讀;

rollback-for:需要觸發(fā)回滾的異常定義,以“,”分割,默認(rèn)任何RuntimeException 將導(dǎo)致事務(wù)回滾,而任何Checked Exception 將不導(dǎo)致事務(wù)回滾;異常名字定義和TransactionProxyFactoryBean中含義一樣

no-rollback-for:不被觸發(fā)進(jìn)行回滾的 Exception(s);以“,”分割;異常名字定義和TransactionProxyFactoryBean中含義一樣;

記不記得在配置方式中為了解決“自我調(diào)用”而導(dǎo)致的不能設(shè)置正確的事務(wù)屬性問題,使用“((IUserService)AopContext.currentProxy()).otherTransactionMethod()”方式解決,在聲明式事務(wù)要得到支持需要使用來開啟。

9.4.5 多事務(wù)語義配置及最佳實(shí)踐
什么是多事務(wù)語義?說白了就是為不同的Bean配置不同的事務(wù)屬性,因?yàn)槲覀冺?xiàng)目中不可能就幾個(gè)Bean,而可能很多,這可能需要為Bean分組,為不同組的Bean配置不同的事務(wù)語義。在Spring中,可以通過配置多切入點(diǎn)和多事務(wù)通知并通過不同方式組合使用即可。

   1、首先看下聲明式事務(wù)配置的最佳實(shí)踐吧:
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
           <tx:method name="save*" propagation="REQUIRED" />
           <tx:method name="add*" propagation="REQUIRED" />
           <tx:method name="create*" propagation="REQUIRED" />
           <tx:method name="insert*" propagation="REQUIRED" />
           <tx:method name="update*" propagation="REQUIRED" />
           <tx:method name="merge*" propagation="REQUIRED" />
           <tx:method name="del*" propagation="REQUIRED" />
           <tx:method name="remove*" propagation="REQUIRED" />
           <tx:method name="put*" propagation="REQUIRED" />
           <tx:method name="get*" propagation="SUPPORTS" read-only="true" />
           <tx:method name="count*" propagation="SUPPORTS" read-only="true" />
          <tx:method name="find*" propagation="SUPPORTS" read-only="true" />
          <tx:method name="list*" propagation="SUPPORTS" read-only="true" />
          <tx:method name="*" propagation="SUPPORTS" read-only="true" />
       </tx:attributes>
</tx:advice>

該聲明式事務(wù)配置可以應(yīng)付常見的CRUD接口定義,并實(shí)現(xiàn)事務(wù)管理,我們只需修改切入點(diǎn)表達(dá)式來攔截我們的業(yè)務(wù)實(shí)現(xiàn)從而對(duì)其應(yīng)用事務(wù)屬性就可以了,如果還有更復(fù)雜的事務(wù)屬性直接添加即可,即

如果我們有一個(gè)batchSaveOrUpdate方法需要“REQUIRES_NEW”事務(wù)傳播行為,則直接添加如下配置即可:

java代碼:
1


2、接下來看一下多事務(wù)語義配置吧,聲明式事務(wù)最佳實(shí)踐中已經(jīng)配置了通用事務(wù)屬性,因此可以針對(duì)需要其他事務(wù)屬性的業(yè)務(wù)方法進(jìn)行特例化配置:

java代碼:
<tx:advice id="noTxAdvice" transaction-manager="txManager">
    <tx:attributes>
           <tx:method name="*" propagation="NEVER" />
    </tx:attributes>
</tx:advice>

該聲明將對(duì)切入點(diǎn)匹配的方法所在事務(wù)應(yīng)用“Never”傳播行為。

多事務(wù)語義配置時(shí),切入點(diǎn)一定不要疊加,否則將應(yīng)用兩次事務(wù)屬性,造成不必要的錯(cuò)誤及麻煩。

@Transactional實(shí)現(xiàn)事務(wù)管理

對(duì)聲明式事務(wù)管理,Spring提供基于 @Transactional注解方式來實(shí)現(xiàn),但需要Java 5+。

注解方式是最簡單的事務(wù)配置方式,可以直接在Java源代碼中聲明事務(wù)屬性,且對(duì)于每一個(gè)業(yè)務(wù)類或方法如果需要事務(wù)都必須使用此注解。

接下來學(xué)習(xí)一下注解事務(wù)的使用吧:

1、定義業(yè)務(wù)邏輯實(shí)現(xiàn):

package cn.javass.spring.chapter9.service.impl;
//省略import
public class AnnotationUserServiceImpl implements IUserService {
    private IUserDao userDao;
    private IAddressService addressService;
    public void setUserDao(IUserDao userDao) {
        this.userDao = userDao;
    }
    public void setAddressService(IAddressService addressService) {
        this.addressService = addressService;
    }
    @Transactional(propagation=Propagation.REQUIRED, isolation=Isolation.READ_COMMITTED)
    @Override
    public void save(final UserModel user) {
        userDao.save(user);
        user.getAddress().setUserId(user.getId());
        addressService.save(user.getAddress());
    }
    @Transactional(propagation=Propagation.REQUIRED, isolation=Isolation.READ_COMMITTED, readOnly=true)
    @Override
    public int countAll() {
        return userDao.countAll();
    }
}

2、定義配置文件(chapter9/service/ applicationContext-service-annotation.xml):

2.1、XML命名空間定義,定義用于事務(wù)支持的tx命名空間和AOP支持的aop命名空間:

java代碼:

    <beans xmlns="http://www.springframework.org/schema/beans"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:tx="http://www.springframework.org/schema/tx"
          xmlns:aop="http://www.springframework.org/schema/aop"
          xsi:schemaLocation="
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

2.2、業(yè)務(wù)實(shí)現(xiàn)配置,非常簡單,使用以前定義的非侵入式業(yè)務(wù)實(shí)現(xiàn):

java代碼:
<bean id="userService" class="cn.javass.spring.chapter9.service.impl.ConfigUserServiceImpl">
    <property name="userDao" ref="userDao"/>
    <property name="addressService" ref="addressService"/>
</bean>
<bean id="addressService" class="cn.javass.spring.chapter9.service.impl.ConfigAddressServiceImpl">
    <property name="addressDao" ref="addressDao"/>
</bean>

2.3、事務(wù)相關(guān)配置:

java代碼:
1
<tx:annotation-driven transaction-manager="txManager"/>
使用如上配置已支持聲明式事務(wù)。
3、修改測試方法并測試該配置方式是否好用:
將TransactionTest 類的testServiceTransaction測試方法拷貝一份命名為testAnntationTransactionTest:
classpath:chapter9/service/applicationContext-service-annotation.xml"
userService.save(user);
try {
    userService.save(user);
    Assert.fail();
} catch (RuntimeException e) {
}
Assert.assertEquals(0, userService.countAll());
Assert.assertEquals(0, addressService.countAll());

4、執(zhí)行測試,測試正常通過,說明該方式能正常工作,因?yàn)樵贏nnotationAddressServiceImpl類的save方法中拋出異常,因此事務(wù)需要回滾,所以兩個(gè)countAll操作都返回0。

9.4.7 @Transactional配置詳解
Spring提供的用于開啟對(duì)注解事務(wù)管理的支持,從而能識(shí)別Bean類上的 @Transactional注解元數(shù)據(jù),其具有以下屬性:

transaction-manager:指定事務(wù)管理器名字,默認(rèn)為transactionManager,當(dāng)使用其他名字時(shí)需要明確指定;
proxy-target-class:表示將使用的代碼機(jī)制,默認(rèn)false表示使用JDK代理,如果為true將使用CGLIB代理
order:定義事務(wù)通知順序,默認(rèn)Ordered.LOWEST_PRECEDENCE,表示將順序決定權(quán)交給AOP來處理。
Spring使用 @Transactional 來指定事務(wù)屬性,可以在接口、類或方法上指定,如果類和方法上都指定了 @Transactional ,則方法上的事務(wù)屬性被優(yōu)先使用,具體屬性如下:

value:指定事務(wù)管理器名字,默認(rèn)使用指定的事務(wù)管理器,用于支持多事務(wù)管理器環(huán)境;
propagation:指定事務(wù)傳播行為,默認(rèn)為Required,使用Propagation.REQUIRED指定;
isolation:指定事務(wù)隔離級(jí)別,默認(rèn)為“DEFAULT”,使用Isolation.DEFAULT指定;
readOnly:指定事務(wù)是否只讀,默認(rèn)false表示事務(wù)非只讀;
timeout:指定事務(wù)超時(shí)時(shí)間,以秒為單位,默認(rèn)-1表示事務(wù)超時(shí)將依賴于底層事務(wù)系統(tǒng);
rollbackFor:指定一組異常類,遇到該類異常將回滾事務(wù);
rollbackForClassname:指定一組異常類名字,其含義與中的rollback-for屬性語義完全一樣;
noRollbackFor:指定一組異常類,即使遇到該類異常也將提交事務(wù),即不回滾事務(wù);
noRollbackForClassname:指定一組異常類名字,其含義與中的no-rollback-for屬性語義完全一樣;
Spring提供的 @Transactional 注解事務(wù)管理內(nèi)部同樣利用環(huán)繞通知TransactionInterceptor實(shí)現(xiàn)事務(wù)的開啟及關(guān)閉。

使用 @Transactional注解事務(wù)管理需要特別注意以下幾點(diǎn):

如果在接口、實(shí)現(xiàn)類或方法上都指定了 @Transactional 注解,則優(yōu)先級(jí)順序?yàn)榉椒?gt;實(shí)現(xiàn)類>接口;
建議只在實(shí)現(xiàn)類或?qū)崿F(xiàn)類的方法上使用 @Transactional,而不要在接口上使用,這是因?yàn)槿绻褂肑DK代理機(jī)制是沒問題,因?yàn)槠涫褂没诮涌诘拇恚欢褂檬褂肅GLIB代理機(jī)制時(shí)就會(huì)遇到問題,因?yàn)槠涫褂没陬惖拇矶皇墙涌?,這是因?yàn)榻涌谏系? @Transactional注解是“不能繼承的”;

具體請(qǐng)參考基于JDK動(dòng)態(tài)代理和CGLIB動(dòng)態(tài)代理的實(shí)現(xiàn)Spring注解管理事務(wù)(@Trasactional)到底有什么區(qū)別。

在Spring代理機(jī)制下(不管是JDK動(dòng)態(tài)代理還是CGLIB代理),“自我調(diào)用”同樣不會(huì)應(yīng)用相應(yīng)的事務(wù)屬性,其語義和中一樣;

默認(rèn)只對(duì)RuntimeException異?;貪L;

在使用Spring代理時(shí),默認(rèn)只有在public可見度的方法的 @Transactional 注解才是有效的,其它可見度(protected、private、包可見)的方法上即使有 @Transactional
注解也不會(huì)應(yīng)用這些事務(wù)屬性的,Spring也不會(huì)報(bào)錯(cuò),如果你非要使用非公共方法注解事務(wù)管理的話,可考慮使用AspectJ。

到此,關(guān)于“Spring事務(wù)的知識(shí)點(diǎn)有哪些”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI