Spring事務管理學習

一、spring事務管理架構

image

1. PlatformTranscationManager

  • 通過這個接口,spring為各個平臺如JDBC、Hibernate、JtA、JPA等提供了統(tǒng)一的事務管理API,所以spring本身并不直接管理事務,而是將事務的管理托管給各個持久化平臺的實現(xiàn)。

2. TranscationStatus

  • 描述事務狀態(tài)
    • isNewTransaction
    • hasSavePoint
    • isRollBackOnly
    • isConpleted

3. TranscationManager

  • 事務管理器
    • 在這里順便提一下,問什么要使用spring的事務管理,如果不使用的話,即手動進行事務管理,那么如果底層用的是JDBC事務,就需要在services層(處理事務的層)加入很多JDBC依賴的事務處理代碼(Connection、Datasource),如果是Hibernate,就需要加入很多Session相關的代碼,所以如果需要在這幾種平臺之間互換的話,需要改很多業(yè)務層的代碼,而Spring的事務管理就相當于為這些不同平臺的事務管理接口提供了一個統(tǒng)一的API,這樣即使平臺不同,但是在業(yè)務層使用的代碼都是相同的(都是使用PlatFormTransactionManager這個接口提供的API),這樣一來,如果需要更改平臺,就不需要更改業(yè)務層的代碼。
    • spring事務管理就是一個典型的策略模式,通過為其注入不同的事務管理器的實現(xiàn),進而支持不同持久化方案的事務管理**
    • JDBC:JDBC是通過java.sql.connection來管理事務,后者是由datasource獲得的。
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>
    
    • HIbernate:Hibernate的事務是通過org.hibernate.Transcation來實現(xiàn)的,后者是從Hibernate Session 獲得的。
    <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>
    

4. TranscationDefinition

  • 定義事務屬性
image

5. 事務傳播行為

  • 當在一個事務方法中調用另一個事務方法時,要指定事務應該如何傳播,比如是新建一個事務還是在當前事務繼續(xù)執(zhí)行。
behavior throw exception new transaction suspend curent transaction
not_suport no no yes
supports no no no
required no null -> yes no
require_new no yes yes
nested no yes yes
never yes no no
mandatory yes no no
  • 嵌套事務的特點是:外層事務失敗的時候回回滾內層事務,而內層事務的異常不會引起外層事務的回滾,嵌套事務是外部事務的一部分,啟動嵌套事務的時候回保存一個savepoint,如果失敗回回滾到這個保存點,嵌套事務只有在外層事務執(zhí)行成功的時候才會commit。

  • 而require_new不會回滾內層事務,它是啟動一個新的,不依賴于當前事務的環(huán)境,

  • 隔離規(guī)則

    • 定義一個事務可能受其他并發(fā)事務的影響程度
    • 并發(fā)事務引起的問題
** Definition
臟讀 A事務讀取了B事務修改了但還沒有提交的數(shù)據(jù),但是B事務因為失敗而回滾了,這個時候A事務讀取的數(shù)據(jù)是無效的
不可重復讀 A事務進行了同樣的兩次查詢,但是獲得的數(shù)據(jù)不一樣,一般是因為兩次查詢中間有B事務對數(shù)據(jù)進行了更新
幻讀 類似于不可重復讀,但是重點是B事務對原數(shù)據(jù)進行了增刪而不是修改,不可重復讀側重于修改
隔離級別 含義 作用(阻止了以上那個問題的發(fā)生)
default 使用數(shù)據(jù)庫默認的隔離級別 --
read_uncommitted 允許讀取未提交的數(shù)據(jù) --
read_committed 只允許讀取已提交的數(shù)據(jù) 臟讀
repetable_read 多次讀取同一字段得到同樣的數(shù)據(jù),除非是本身修改 臟讀、不可重復讀
serializable 串行化執(zhí)行事務操作 臟讀、不可重復讀、幻讀

6. 回滾規(guī)則

  • 定義了事務在遇到哪些異常才會回滾,

7. 是否只讀

  • 事務設置為只讀之后有利于數(shù)據(jù)庫對該操作進行相關的優(yōu)化

8. 事務超時

  • 事務一旦超時就會自動回

二 、 Spring編程式事務

1. 使用TransactionTemplate

image

TranscationTemplate 類圖

  • 由上可知,TransactionDefinition是用來定義事務的屬性的,所以TransactionTemplate也就具備了配置事務的能力,另外還需要為其指定TransactionManager,用來實現(xiàn)底層事務的管理。
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">  
    <property name="driverClassName">  
        <value>com.mysql.jdbc.Driver</value>  
    </property>  
    <property name="url">  
        <value>${jdbc.mgr.url}</value>  
    </property>  
    <property name="username">  
        <value>${jdbc.mgr.user}</value>  
    </property>  
    <property name="password">  
        <value>${jdbc.mgr.password}</value>  
    </property>  
</bean>
<bean id="sessionFactory"  
      class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">  
    <property name="dataSource" ref="dataSource"/>  
    <property name="packagesToScan">  
        <list>  
            <!-- 可以加多個包 -->  
            <value>com.cuilei01.mgr.utils</value>  
        </list>  
    </property>  
    <property name="hibernateProperties">  
        <props>  
  
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>  
            <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>  
        </props>  
    </property>  
</bean>  
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">  
    <property name="sessionFactory" ref="sessionFactory"></property>  
</bean>  
<!-- 配置transactionTemplate -->  
<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">  
    <property name="transactionManager" ref="transactionManager"></property>  
    <!--定義事務隔離級別,-1表示使用數(shù)據(jù)庫默認級別-->  
    <property name="readOnly" value="false"></property>  
    <property name="isolationLevelName" value="ISOLATION_DEFAULT"></property>  
    <property name="propagationBehaviorName" value="PROPAGATION_REQUIRED"></property>  
</bean>  
  • 然后就可以在代碼中注入bean并使用
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})  
@RunWith(SpringJUnit4ClassRunner.class)  
public class TransactionTest {  
  
    private final Logger logger = LoggerFactory.getLogger(TransactionTest.class);  
  
    @Resource  
    private TransactionTemplate transactionTemplate;  
  
    @Test  
    public void testProgrammaticTransaction() {  
        logger.info("Begin test programmatic transaction!########################");  
        // 第一個事務  
        Integer result = transactionTemplate.execute(new TransactionCallback<Integer>() {  
            @Override  
            public Integer doInTransaction(TransactionStatus status) {  
                logger.info("Do in transaction with a return value!#####################################");  
                // 在事務中執(zhí)行, 有返回值  
                return 1;  
            }  
        });  
  
        logger.info("result:{}", result);  
  
        // 第二個事務  
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {  
            @Override  
            protected void doInTransactionWithoutResult(TransactionStatus status) {  
                logger.info("Do in transaction without a return value!#####################################");  
                // 在事務中執(zhí)行,沒有返回值  
            }  
        });  
    }  
    1. 使用PlatformTranscationManager
    • 其實現(xiàn)步驟基本和TransactionTemplate相同,spring推薦使用后者

三、Spring聲明式事務管理

  • 聲明式事務管理式建立在AOP基礎上的,其本質是在方法執(zhí)行的前后進行攔截,然后再目標方法開始之前開啟一個事務,或者加入一個已經(jīng)存在的事務, 在執(zhí)行完方法之后根據(jù)情況是否提交或者回滾,。聲明式事務管理的優(yōu)點就是不需要使用代碼管理事務,所以也就不需要再業(yè)務層加入事務管理相關的代碼,將所有事務管理相關的代碼都放到配置文件中。此外,聲明式事務管理還符合spring的“非侵入式”的編程原則,使得業(yè)務代碼不受污染,一個普通的POJO只需要簡單的加上注解就可以獲得事務管理的支持,相比于編程式事務的缺點是粒度比后者大,只到方法級別,編程式事務可以管理到代碼塊級別。
  • 以mybatis為例,基于上面一步已經(jīng)配置好數(shù)據(jù)源和對應平臺的事務管理器.
    • 開啟注解支持
    <!-- 開啟事務控制的注解支持 -->  
    <tx:annotation-driven transaction-manager="transactionManager"/></span></span>  
    
    • 添加tx名字空間
    xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd  
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"  
    
    • 在需要使用事務的方法或者類上加上注解,并設置相關事務屬性
    @Autowired  
    private MyBatisDao dao;  
      
    @Transactional  
    @Override  
    public void insert(Test test) {  
        dao.insert(test);  
        throw new RuntimeException("test");//拋出unchecked異常,觸發(fā)事物,回滾  
    } 
    
  • 相關事務屬性如下:
屬性 類型 描述
value String 可選的限定描述符,指定使用的事務管理器
propagation enum: Propagation 可選的事務傳播行為設置
isolation enum: Isolation 可選的事務隔離級別設置
readOnly boolean 讀寫或只讀事務,默認讀寫
timeout int (in seconds granularity) 事務超時時間設置
rollbackFor Class對象數(shù)組,必須繼承自Throwable 導致事務回滾的異常類數(shù)組
rollbackForClassName 類名數(shù)組,必須繼承自Throwable 導致事務回滾的異常類名字數(shù)組
noRollbackFor Class對象數(shù)組,必須繼承自Throwable 不會導致事務回滾的異常類數(shù)組

noRollbackForClassName 類名數(shù)組,必須繼承自Throwable 不會導致事務回滾的異常類名字數(shù)組

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容