亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Spring數(shù)據(jù)庫(kù)事務(wù)的實(shí)現(xiàn)機(jī)制講解

 更新時(shí)間:2021年10月08日 15:00:36   作者:不去天涯  
這篇文章主要介紹了Spring數(shù)據(jù)庫(kù)事務(wù)的實(shí)現(xiàn)機(jī)制講解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

事務(wù)控制的核心——Connection

在開始之前,先讓我們回憶一下數(shù)據(jù)庫(kù)較原始的JDBC是怎么管理事務(wù)的:

    //僅做演示,代碼不完整,不完全規(guī)范
    try {
        con.setAutoCommit(false);
        statement1 = con.prepareStatement(sql);
        statement1.executeUpdate();
        statement2 = con.prepareStatement(sql1);
        statement2.executeUpdate();
        con.commit();
    } catch (SQLException e) {
        try {
            con.rollback();
        } catch (SQLException e1) {
        }
    }

可以很明顯的看到,JDBC框架下的事務(wù)控制是由connection完成的。因?yàn)椴徽撌荕yBatis還是MyBatis-Spring都是在JDBC框架基礎(chǔ)上的高層框架,所以他們的原理仍然應(yīng)該是一致的,也就是說(shuō)想控制事務(wù),必須要控制Connection。

我們常說(shuō)事務(wù)要切在Service層,所以連接需要在整個(gè)Service請(qǐng)求中都是同一個(gè),不能變。

用AOP技術(shù)保持當(dāng)前的Connection

Spring的事務(wù)管理就是使用AOP技術(shù),通過(guò)對(duì)Service層設(shè)置切面,注入事務(wù)管理的邏輯。

Spring的事務(wù)管理切面配置采用了聲明式事務(wù),最常用的兩種方法是 tx:Advice 和 tx:annotation-driven 兩種方式。

兩種方式的配置文件解析器分別是:

org.springframework.transaction.config.TxAdviceBeanDefinitionParser

org.springframework.transaction.config.AnnotationDrivenBeanDefinitionParser

細(xì)看其中的代碼和配置內(nèi)容,就會(huì)發(fā)現(xiàn),不論哪種方式都會(huì)創(chuàng)建包含事務(wù)處理功能的動(dòng)態(tài)代理。代理關(guān)聯(lián)的切面(Advice)類是 TransactionInterceptor 。

一起看下關(guān)鍵代碼:

   protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation)
            throws Throwable {
        //......
        if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
            TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);//-----1.開啟事務(wù)
            Object retVal = null;
            try {
                retVal = invocation.proceedWithInvocation();//...2.執(zhí)行被代理的請(qǐng)求
            }
            catch (Throwable ex) {
completeTransactionAfterThrowing(txInfo, ex);//...3.異?;貪L
                throw ex;
            }
            finally {
                cleanupTransactionInfo(txInfo);
            }
            commitTransactionAfterReturning(txInfo);//...4.提交事務(wù)
            return retVal;
        }
        //......

上邊的代碼里是不是沒(méi)有看到TransactionManger和Connection?那么這兩個(gè)東西的作用在哪里呢?

TransactionManger是上述TransactionInterceptor的一個(gè)屬性(不嚴(yán)的說(shuō)),主要作用是用來(lái)創(chuàng)建connection,創(chuàng)建之后的Connection會(huì)被保存在TransactionInfo里面。

TransactionInfo在上述代碼片段中被后續(xù)傳遞給事務(wù)提交和事務(wù)回滾的代碼。

Service層和Dao層共享Connection

我們都知道事務(wù)要切在Service層,也就是說(shuō)上一節(jié)的切面只是在Service層有效,那么Dao層怎么獲取到Connection連接呢?

如果Service層和Dao層的連接不是一個(gè)連接那么回滾和提交操作就等同于無(wú)效了!

這里只用MyBatis來(lái)說(shuō)明,其他的ORM框架實(shí)現(xiàn)原理基本也是一樣的。

要明白這一點(diǎn)需要先弄明白MyBatis本身的事務(wù)管理機(jī)制,可以參考MyBatis源碼解析之Transaction事務(wù)模塊。MyBatis提供了兩種事務(wù)管理機(jī)制一種是自己內(nèi)部用的JDBC模式,一種是支持代理給外部控制的MANAGED模式。

第二種模式下會(huì)把事務(wù)的交給外部控制,外部只需要提供一個(gè)實(shí)現(xiàn)了 org.apache.ibatis.transaction.Transaction 接口的控制類即可。

一起來(lái)看一下Transaction需要提供哪些方法:

public interface Transaction {
  Connection getConnection() throws SQLException;
  void commit() throws SQLException;
  void rollback() throws SQLException;
  void close() throws SQLException;
}

注意里邊的getConnection方法,也就是說(shuō)MyBatis的連接也是交給外部來(lái)獲取的?。∧敲粗恍枰朕k法把Service層的Connection存起來(lái),然后讓自己實(shí)現(xiàn)Transaction獲取到即可。

Spring采用的是ThreadLocal本地線程變量的技術(shù)來(lái)做到的,我們可以看下mybatis-spring的 org.mybatis.spring.transaction.SpringManagedTransaction 中g(shù)etConnection的實(shí)現(xiàn)就明白了:

  public Connection getConnection() throws SQLException {
    if (this.connection == null) {
      openConnection();
    }
    return this.connection;
  }

  private void openConnection() throws SQLException {
    this.connection = DataSourceUtils.getConnection(this.dataSource);//...1.關(guān)鍵點(diǎn)在這里?。?
    this.autoCommit = this.connection.getAutoCommit();
    this.isConnectionTransactional = DataSourceUtils.isConnectionTransactional(this.connection, this.dataSource);
    if (LOGGER.isDebugEnabled()) {
      LOGGER.debug(
          "JDBC Connection ["
              + this.connection
              + "] will"
              + (this.isConnectionTransactional ? " " : " not ")
              + "be managed by Spring");
    }
  }

其中

this.connection = DataSourceUtils.getConnection(this.dataSource); 

一行就會(huì)從ThreadLocal中拿到Connection對(duì)象。

事務(wù)為什么要切在Service層的理由

對(duì)于這個(gè)常識(shí),有一點(diǎn)個(gè)人的理解:

事務(wù)的ACID要求事務(wù)要有原子性,也就是一個(gè)事務(wù)里邊的多項(xiàng)DB操作要同時(shí)成功,同時(shí)失敗,成功一半的情況是不允許的。

也就是說(shuō),一般需要事務(wù)的時(shí)候,都是包含多個(gè)功能單元的。那么我們都放在一個(gè)Dao里面就顯得不那么職能分明,也就是不那么符合設(shè)計(jì)原則的單一職責(zé)原則。

spring事務(wù)與數(shù)據(jù)庫(kù)事務(wù)的區(qū)別

先說(shuō)一下什么是事務(wù),事務(wù)(Transaction):

一般是指要做的或所做的事情。在計(jì)算機(jī)術(shù)語(yǔ)中是指訪問(wèn)并可能更新數(shù)據(jù)庫(kù)中各種數(shù)據(jù)項(xiàng)的一個(gè)程序執(zhí)行單元(unit)。事務(wù)通常由高級(jí)數(shù)據(jù)庫(kù)操縱語(yǔ)言或編程語(yǔ)言(如SQL,C++或Java)書寫的用戶程序的執(zhí)行所引起,并用形如begin transaction和end transaction語(yǔ)句(或函數(shù)調(diào)用)來(lái)界定。事務(wù)由事務(wù)開始(begin transaction)和事務(wù)結(jié)束(end transaction)之間執(zhí)行的全體操作組成。。

之前一直覺得事務(wù)只針對(duì)于數(shù)據(jù)庫(kù)當(dāng)中,5種隔離級(jí)別,7種傳播行為,后來(lái)才發(fā)現(xiàn)這是針對(duì)Spring的,對(duì)數(shù)據(jù)庫(kù)來(lái)說(shuō)隔離級(jí)別只有4種,Spring多了一個(gè)DEFAULT 這是一個(gè)PlatfromTransactionManager默認(rèn)的隔離級(jí)別,使用數(shù)據(jù)庫(kù)默認(rèn)的事務(wù)隔離級(jí)別.

總的來(lái)說(shuō),本質(zhì)上其實(shí)是同一個(gè)概念

spring的事務(wù)是對(duì)數(shù)據(jù)庫(kù)的事務(wù)的封裝,最后本質(zhì)的實(shí)現(xiàn)還是在數(shù)據(jù)庫(kù),假如數(shù)據(jù)庫(kù)不支持事務(wù)的話,spring的事務(wù)是沒(méi)有作用的

數(shù)據(jù)庫(kù)的事務(wù)說(shuō)簡(jiǎn)單就只有開啟,回滾和關(guān)閉,spring對(duì)數(shù)據(jù)庫(kù)事務(wù)的包裝,原理就是拿一個(gè)數(shù)據(jù)連接,根據(jù)spring的事務(wù)配置,操作這個(gè)數(shù)據(jù)連接對(duì)數(shù)據(jù)庫(kù)進(jìn)行事務(wù)開啟,回滾或關(guān)閉操作.但是spring除了實(shí)現(xiàn)這些,還配合spring的傳播行為對(duì)事務(wù)進(jìn)行了更廣泛的管理.其實(shí)這里還有個(gè)重要的點(diǎn),那就是事務(wù)中涉及的隔離級(jí)別,以及spring如何對(duì)數(shù)據(jù)庫(kù)的隔離級(jí)別進(jìn)行封裝.事務(wù)與隔離級(jí)別放在一起理解會(huì)更好些。

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • java開發(fā)接口吞吐量提升10多倍技巧

    java開發(fā)接口吞吐量提升10多倍技巧

    這篇文章主要為大家介紹了java開發(fā)技巧之接口吞吐量提升10多倍的方法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01
  • Lucene詞向量索引文件構(gòu)建源碼解析

    Lucene詞向量索引文件構(gòu)建源碼解析

    這篇文章主要為大家介紹了Lucene詞向量索引文件構(gòu)建源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • java實(shí)現(xiàn)FTP文件上傳與文件下載

    java實(shí)現(xiàn)FTP文件上傳與文件下載

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)FTP文件上傳與文件下載的相關(guān)資料,通過(guò)以下兩種方式實(shí)現(xiàn),通過(guò)JDK自帶的API實(shí)現(xiàn),二是通過(guò)Apache提供的API是實(shí)現(xiàn),感興趣的小伙伴們可以參考一下
    2016-04-04
  • java中快速創(chuàng)建帶初始值的List和Map實(shí)例

    java中快速創(chuàng)建帶初始值的List和Map實(shí)例

    下面小編就為大家?guī)?lái)一篇java中快速創(chuàng)建帶初始值的List和Map實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-10-10
  • Java關(guān)于JDK1.8新特性的Stream流

    Java關(guān)于JDK1.8新特性的Stream流

    這篇文章主要介紹了版本薇JDK1.8 的Java中的Stream流,Stream流是一個(gè)來(lái)自數(shù)據(jù)源的元素隊(duì)列并支持聚合操作,感興趣的朋友可以參考下面文章內(nèi)容
    2021-09-09
  • Java如何在List或Map遍歷過(guò)程中刪除元素

    Java如何在List或Map遍歷過(guò)程中刪除元素

    相信大家在日常的開發(fā)過(guò)程中,經(jīng)常需要對(duì)List或Map里面的符合某種業(yè)務(wù)的數(shù)據(jù)進(jìn)行刪除,但是如果不了解里面的機(jī)制就容易掉入“陷阱”導(dǎo)致遺漏或者程序異常。下面這篇文章將會(huì)給大家詳細(xì)介紹Java如何在List和Map遍歷過(guò)程中刪除元素,有需要的朋友們可以參考借鑒。
    2016-12-12
  • SpringBoot實(shí)現(xiàn)OneDrive文件上傳的詳細(xì)步驟

    SpringBoot實(shí)現(xiàn)OneDrive文件上傳的詳細(xì)步驟

    這篇文章主要介紹了SpringBoot實(shí)現(xiàn)OneDrive文件上傳的詳細(xì)步驟,文中通過(guò)代碼示例和圖文講解的非常詳細(xì),對(duì)大家實(shí)現(xiàn)OneDrive文件上傳有一定的幫助,需要的朋友可以參考下
    2024-02-02
  • java環(huán)境中的JDK、JVM、JRE詳細(xì)介紹

    java環(huán)境中的JDK、JVM、JRE詳細(xì)介紹

    這篇文章主要介紹了java環(huán)境中的JDK、JVM、JRE詳細(xì)介紹的相關(guān)資料,對(duì)于初學(xué)者還是有必要了解下,細(xì)致說(shuō)明他們是什么,需要的朋友可以參考下
    2016-11-11
  • SpringBoot-JWT生成Token和攔截器的使用(訪問(wèn)受限資源)

    SpringBoot-JWT生成Token和攔截器的使用(訪問(wèn)受限資源)

    本文主要介紹了SpringBoot-JWT生成Token和攔截器的使用(訪問(wèn)受限資源),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-05-05
  • 解決執(zhí)行Junit單元測(cè)試報(bào)錯(cuò)java.lang.ClassNotFoundException問(wèn)題

    解決執(zhí)行Junit單元測(cè)試報(bào)錯(cuò)java.lang.ClassNotFoundException問(wèn)題

    這篇文章主要介紹了解決執(zhí)行Junit單元測(cè)試報(bào)錯(cuò)java.lang.ClassNotFoundException問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-11-11

最新評(píng)論