MyBatis進階(一)連接池 & 事務提交 & 動態 SQL 語句 & 延遲加載 & 緩存

MyBatis

Mybatis 的連接池技術

1.1MyBatis連接池分類

在 Mybatis 中我們將它的數據源 dataSource 分爲以下幾類,
在這裏插入圖片描述

可以看出 Mybatis 將它自己的數據源分爲三類:

JNDI 使用 JNDI 實現的數據源

POOLED 使用連接池的數據源

UNPOOLED 不使用連接池的數據源

在這裏插入圖片描述
相應地,MyBatis 內部分別定義了實現了 java.sql.DataSource 接口的 UnpooledDataSource, PooledDataSource 類來表示 UNPOOLED、POOLED 類型的數據源,並且PooledDataSource 還持有一個UnpooledDataSource 的引用。當PooledDataSource 需要創建java.sql.Connection實例對象時,還是通過調用UnpooledDataSource來創建。PooledDataSource只是一種緩存連接池機制。

在這三種數據源中,我們一般採用的是 POOLED 數據源(很多時候我們所說的數據源就是爲了更好的管理數據庫連接,也就是我們所說的連接池技術)。

1.2Mybatis 中數據源的配置

主配置文件如下

<!-- 配置數據源(連接池)信息 --> 
<dataSource type="POOLED">  
    <property name="driver" value="${jdbc.driver}"/>  
    <property name="url" value="${jdbc.url}"/>  
    <property name="username" value="${jdbc.username}"/>  
    <property name="password" value="${jdbc.password}"/> 
</dataSource> 
<!-- type=POOLED時,MyBatis 會創建 PooledDataSource 實例  --> 

MyBatis 在初始化時,根據的 type 屬性來創建相應類型的的數據源 DataSource,type=POOLED時,MyBatis 會創建 PooledDataSource 實例。

1.3Mybatis 中 DataSource 的存取

MyBatis 是通過工廠模式來創建數據源 DataSource 對象的, MyBatis 定義了抽象的工廠接 口:org.apache.ibatis.datasource.DataSourceFactory,通過其 getDataSource()方法返回數據源 DataSource。

1.4MyBatis中連接獲取的過程

當我們需要創建 SqlSession 對象並需要執行 SQL 語句時,這時候 MyBatis 纔會去調用 dataSource 對象來創建java.sql.Connection對象。也就是說,java.sql.Connection對象的創建一直延遲到執行SQL語句的時候。數據庫連接是我們最爲寶貴的資源,只有在要用到的時候,纔去獲取並打開連接,當我們用完了就再立即將數據庫連接歸還到連接池中。

Mybatis 的事務提交

在 JDBC 中我們可以通過手動方式將事務的提交改爲手動方式,通過 setAutoCommit() 方法就可以調整。 Mybatis框架因爲是對 JDBC 的封裝,所以 Mybatis 框架的事務控制方式,本身也是用 JDBC的 setAutoCommit()方法來設置事務提交方式的。
觀察Connection 的整個變化過程,通過分析我們能夠發現之前的 CRUD 操作過程中,我們都要手動進行事務的提交,原因是 setAutoCommit()方法,在執行時它的值被設置爲 false 了,所以我們在 CRUD 操作中, 必須通過 sqlSession.commit() 方法來執行提交操作,相當於使用了 JDBC 中的 connection.commit()方法實現事務提交。

可以在創建sqlSession對象時指定自動提交 session = factory.openSession(true);

但就編程而言,設置爲自動提交方式爲 false再根據情況決定是否進行提交,這種方式更常用。因爲我們可以根據業務情況來決定提交是否進行提交。

Mybatis 的動態 SQL 語句

<!-- 查詢所有用戶在 id 的集合之中 -->  
<select id="findInIds" resultType="user" parameterType="queryvo">  
    <!--  select * from user where id in (1,2,3,4,5); --> 
  	<include refid="defaultSql"></include>   
  	<where> 
  		<if test="ids != null and ids.size() > 0">     
       		<foreach collection="ids" open="id in ( " close=")" item="uid"  separator=",">      
           		#{uid}     
       		</foreach>   
    	</if>   
    </where>  
</select> 

SQL片段

<sql id="defaultSql">   
	select * from user  
</sql> 
<select id="findAll" resultType="user">  
    <include refid="defaultSql"></include> 
</select> 

MyBatis延遲加載

延遲加載:就是在需要用到數據時才進行加載,不需要用到數據時就不加載數據。延遲加載也稱懶加載.

好處:先從單表查詢,需要時再從關聯表去關聯查詢,大大提高數據庫性能,因爲查詢單表要比關聯查詢多張錶速度要快。

壞處:因爲只有當需要用到數據時,纔會進行數據庫查詢,這樣在大批量數據查詢時,因爲查詢工作也要消耗時間,所以可能造成用戶等待時間變長,造成用戶體驗下降

使用了resultMap來實現一對一,一對多,多對多關係的操作。主要 是通過 association、collection 實現一對一及一對多映射。association、collection 具備延遲加載功能。

Mybatis 緩存

Mybatis 中緩存分爲一級緩存,二級緩存。
在這裏插入圖片描述

一級緩存

一級緩存是 SqlSession 級別的緩存,只有當調用 SqlSession 的修改,添加,刪除,commit(),close()等方法時,就會清空一級緩存。

例如:

第一次發起查詢用戶 id 爲 1 的用戶信息,先去找緩存中是否有 id 爲 1 的用戶信息,如果沒有,從數據庫查詢用戶信息。 得到用戶信息,將用戶信息存儲到一級緩存中。

如果 sqlSession 去執行 commit 操作(執行插入、更新、刪除),清空 SqlSession 中的一級緩存,這樣做的目的爲了讓緩存中存儲的是最新的信息,避免髒讀。

第二次發起查詢用戶 id 爲 1 的用戶信息,先去找緩存中是否有 id 爲 1 的用戶信息,緩存中有,直接從緩存中獲取用戶信息

二級緩存

二級緩存是 mapper 映射級別的緩存,多個 SqlSession 去操作同一個 Mapper 映射的 sql 語句,多個 SqlSession 可以共用二級緩存,二級緩存是跨 SqlSession 的。

例如

sqlSession1 去查詢用戶信息,查詢到用戶信息會將查詢數據存儲到二級緩存中。

如果 SqlSession3 去執行相同 mapper 映射下 sql,執行 commit 提交,將會清空該 mapper 映射下的二 級緩存區域的數據。

sqlSession2 去查詢與 sqlSession1 相同的用戶信息,首先會去緩存中找是否存在數據,如果存在直接從 緩存中取出數據

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