MyBatis-03 | 學習mybatis中連接池的使用及mybatis的事務管理機制

上一篇 瞭解MyBatis框架實現CRUD操作及MyBatis配置文件參數:https://blog.csdn.net/weixin_44187963/article/details/104975306

目錄

連接池概述

MyBatis連接池提供三種方式的配置

MyBatis數據源DataSource分類

使用了連接池的PooledDataSource

不使用連接池的UnpooledDataSource

MyBatis的事務管理機制

1. 事務的配置

2. 事務工廠的創建

3. 事務的提交

 

前面在學習JDBC的時候也已經提到過幾種連接池,比如常見的c3p0、Druid的使用,在此基礎上今天來看看MyBatis中關於連接池的使用~

連接池概述

連接池就是用於存儲連接的容器,而之所以在實際開發中都會用到連接池呢,是因爲連接池大大減少了我們在不斷獲取鏈連接釋放連接過程中所消耗的時間。

而作爲容器:

  • 通常是一個線程安全的集合對象
  • 而且集合必須實現隊列的特性:先進先出

MyBatis連接池提供三種方式的配置

配置的位置就在主配置文件SqlMapConfig.xml中的datasource標籤,其中的type屬性就是採用何種連接池。

<dataSource type="POOLED">
  • POOLED:採用傳統的javax.sql.datasource規範中的連接池,mybatis中有針對規範的實現

  • UNPOOLED:採用傳統的獲取連接的方式,雖然也實現了javax.sql.datasource接口,但是沒有使用池的思想

  • JDNI:採用服務器提供的JNDI技術實現,來獲取Datasource對象。如果不是web或maven的war工程是不能使用的

注:tomcat服務器採用的是dbcp連接池

 

MyBatis數據源DataSource分類

MyBatis內部定義了實現了java.sql.DataSource接口的UnpooledDataSource類來表示UNPOOLED、java.sql.DataSource接口的PooledDataSource類來表示POOLED類型的數據源。

使用了連接池的PooledDataSource

使用PooledDataSource的getConnection()方法來返回Connection對象的基本原理:

PooledDataSource將java.sql.Connection對象包裹成PooledConnection對象放到了PoolState類型的容器中維護。 MyBatis將連接池中的PooledConnection分爲兩種狀態: 空閒狀態(idle)和活動狀態(active),這兩種狀態的PooledConnection對象分別被存儲到PoolState容器內的idleConnectionsactiveConnections兩個List集合中:

idleConnections:空閒狀態PooledConnection對象被放置到此集合中,表示當前閒置的沒有被使用的PooledConnection集合,調用PooledDataSource的getConnection()方法時,會優先從此集合中取PooledConnection對象。當用完一個java.sql.Connection對象時,MyBatis會將其包裹成PooledConnection對象放到此集合中。

activeConnections:活動狀態的PooledConnection對象被放置到名爲activeConnections的ArrayList中,表示當前正在被使用的PooledConnection集合,調用PooledDataSource的getConnection()方法時,會優先從idleConnections集合中取PooledConnection對象,如果沒有,則看此集合是否已滿,如果未滿,PooledDataSource會創建出一個PooledConnection,添加到此集合中,並返回。

PooledDataSource 的getConnection()方法獲取Connection對象的處理流程圖:

不使用連接池的UnpooledDataSource

當 <dataSource>的type屬性被配置成了”UNPOOLED”

<dataSource type="UNPOOLED">

MyBatis首先會實例化一個UnpooledDataSourceFactory工廠實例,然後通過.getDataSource()方法返回一個UnpooledDataSource實例對象引用。使用UnpooledDataSource的getConnection(),每調用一次就會產生一個新的Connection實例對象。

UnpooledDataSource會做以下事情:

1.  初始化驅動:判斷driver驅動是否已經加載到內存中,如果還沒有加載,則會動態地加載driver類,並實例化一個Driver對象,使用DriverManager.registerDriver()方法將其註冊到內存中,以供後續使用。

2.  創建Connection對象:使用DriverManager.getConnection()方法創建連接。

3.  配置Connection對象:設置是否自動提交autoCommit和隔離級別isolationLevel。

4.  返回Connection對象。

 

MyBatis的事務管理機制

MyBatis的事務管理分爲兩種形式

  1. 使用JDBC的事務管理機制:即利用java.sql.Connection對象完成對事務的提交(commit())、回滾(rollback())、關閉(close())等

  2. 使用MANAGED的事務管理機制:這種機制MyBatis自身不會去實現事務管理,而是讓程序的容器如(JBOSS,Weblogic)來實現對事務的管理

兩者的類圖如下:

1. 事務的配置

我們在使用MyBatis時,一般會在MyBatisXML配置文件中定義類似如下的信息:

<!--環境配置-->
    <environments default="mysql">
        <environment id="mysql">
            <transactionManager type="jdbc"></transactionManager>
            <!--數據庫連接池-->
            <dataSource type="UNPOOLED">
                <!--數據庫連接配置-->
                <property name="driver" value="${driver}"></property>
                <property name="url" value="${url}"></property>
                <property name="username" value="${user}"></property>
                <property name="password" value="${password}"></property>
            </dataSource>
        </environment>
    </environments>

其中transactionManager type屬性表示使用JDBC事務管理機制:

<transactionManager type="jdbc"></transactionManager>

2. 事務工廠的創建

    MyBatis事務的創建是交給TransactionFactory 事務工廠來創建的,如果我們將<transactionManager>的type 配置爲"JDBC",那麼,在MyBatis初始化解析<environment>節點時,會根據type="JDBC"創建一個JdbcTransactionFactory工廠。

如果type = "JDBC",  則MyBatis會創建一個JdbcTransactionFactory.class 實例;如果type="MANAGED",則MyBatis會創建一個MangedTransactionFactory.class實例。

3. 事務的提交

在之前博客中有寫到關於事務的提交我們都是通過手動提交:

@After//在測試方法執行之後進行
    public void destroy() throws IOException {
        //提交事務
        session.commit();

        session.close();
        in.close();
    }

那麼如何實現事務的自動提交呢,看源碼中有這樣寫:

所以在使用中factory.openSession(true)傳參爲true就表示事務的自動提交:

 public void init() throws IOException {
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
        session = factory.openSession(true);
        userDao = session.getMapper(UserDao.class);
    }

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章