MyBatis 原理介紹

ORM(Object/Relational Mapping),即對象關係映射,它完成面向對象的編程語言到關係數據庫的映射。ORM工具的惟一做用是:把持久化對象的保存、修改、刪除等操做,轉換成對數據庫的操做。java

ORM 基本映射關係:

數據表映射類。
數據表的行映射對象(實例)。
數據表的列(字段)映射對象的屬性。

MyBatis 簡介:

MyBatis 是支持定製化 SQL、存儲過程以及高級映射的優秀的持久層框架。
MyBatis 避免了幾乎全部的 JDBC 代碼和手動設置參數以及對結果集的檢索封裝。
MyBatis 能夠對配置和原生 Map 使用簡單的 XML 或註解,將接口和Java的POJOs(Plain Old Java Objects(普通的 Java 對象))映射成數據庫中的記錄。

MyBatis 主要思想是將程序中的大量SQL語句抽取出來,配置在配置文件中,以實現SQL的靈活配置。
MyBatis 並不徹底是一種ORM框架,它的設計思想和ORM類似,只是它容許直接編寫SQL語句,使得數據庫訪問更加靈活。
MyBatis 提供了一種「半自動化」的ORM實現,是一種「SQL Mapping」框架。

MyBatis功能結構

1. API接口層:
提供給外部使用的接口API,開發人員經過這些本地API來操縱數據庫。接口層接收到調用請求就會調用數據處理層來完成具體的數據處理。
2. 數據處理層:
負責具體的SQL查找、SQL解析、SQL執行和執行結果映射處理等。它主要的目的是根據調用的請求完成一次數據庫操做。
3. 基礎支撐層:
負責最基礎的功能支撐,包括鏈接管理、事務管理、配置加載和緩存處理,這些都是共用的東西,將他們抽取出來做爲最基礎的組件,爲上層的數據處理層提供最基礎的支撐。

MyBatis 框架結構

1. 加載配置:
MyBatis 應用程序根據XML配置文件加載運行環境,建立SqlSessionFactory, SqlSession,將SQL的配置信息加載成爲一個個MappedStatement對象(包括了傳入參數映射配置、執行的SQL語句、結果映射配置),存儲在內存中。(配置來源於兩個地方,一處是配置文件,一處是 Java 代碼的註解)
2. SQL解析:
當API接口層接收到調用請求時,會接收到傳入SQL的ID和傳入對象(能夠是Map、JavaBean或者基本數據類型),MyBatis 會根據SQL的ID找到對應的MappedStatement,而後根據傳入參數對象對MappedStatment進行解析,解析後能夠獲得最終要執行的SQL語句和參數。
3. SQL的執行:
SqlSession將最終獲得的SQL和參數拿到數據庫進行執行,獲得操做數據庫的結果。
4. 結果映射:
將操做數據庫的結果按照映射的配置進行轉換,能夠轉換成HashMap、JavaBean或者基本數據類型,並將最終結果返回,用完以後關閉SqlSession。

SqlSessionFactory:

每一個基於MyBatis的應用都是以一個SqlSessionFactory的實例爲核心的。
SqlSessionFactory是單個數據庫映射關係通過編譯後的內存映像。
SqlSessionFactory的實例能夠經過SqlSessionFactoryBuilder得到。
而SqlSessionFactoryBuilder則能夠從XML配置文件或一個預先定製的Configuration的實例構建出SqlSessionFactory的實例。
SqlSessioFactory是建立SqlSession的工廠。

SqlSession:

SqlSession是執行持久化操做的對象,它徹底包含了面向數據庫執行SQL命令所需的全部方法。
能夠經過SqlSession實例來直接執行已映射的SQL語句,在使用完SqlSession後咱們應該使用finally塊來確保關閉它。

Mybatis.xml 配置文件:

配置文件包括:
1. configuration 配置
2. properties 配置
可外部配置且動態替換。
例如:在resource資源目錄下配置config.properties配置文件,在Mybatis.xml中配置以下。

<properties resource="config.properties"/>

也能夠經過properties的子元素傳遞值:
<properties resource="config.properties">  
<property name="username" value="root"/>  
<property name="password" value="123"/>
</properties>
3. settings 設置
settings 是 Mybatis.xml 文件中極其重要的設置,它們會改變MyBatis的運行時行爲,如開啓二級緩存、開啓延遲加載等。
4. typeAliases 類型別名
typeAliases只和XML配置有關,用來減小類徹底限定名的冗餘。
第一種配置方法:
<typeAliases>  
<typeAlias alias="User" type="com.shiyanlou.mybatis.model.User"/>  
</typeAliases>
這裏將全路徑的com.shiyanlou.mybatis.model.User(User是包com.shiyanlou.mybatis.mode下的方法)起一個別名User,在映射文件中parameterType和resultType就能夠直接使用別名User,無需使用全路徑。

第二種配置方法:
<typeAliases>  
<package name="com.shiyanlou.mybatis.model" />  
</typeAliases>
指定一個包名起別名,MyBatis 會在包名下搜索須要的JavaBean,將Java類的類名做爲類的類別名。
5. typeHandlers 類型處理器
typeHandlers的做用是實現JDBC類型和Java類型之間的轉換,MyBatis中默認的類型處理器基本能知足平常需求。
6. objectFactory 對象工廠
7. plugins 插件
8. environments 環境
MyBatis 的環境配置實際是數據源的配置,MyBatis能夠配置多個環境,幫助你將SQL映射對應到多種數據庫。

注意:
儘管能夠配置多個環境,每一個SqlSessionFactory實例只能對應一個數據庫,有幾個數據庫就須要建立幾個SqlSessionFactory實例。

接收環境配置的兩個方法:
SqlSessionFactory sqlSessionFactory = new     SqlSessionFactoryBuilder().build(reader, environment);  
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader, environment,properties);

若是忽略了環境參數,默認環境將會被加載:
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);  
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader,properties);
9. transactionManager:事務管理器
MyBatis中有兩種事務管理器,即 type=」\[JDBC | MANAGED\]」;

JDBC:直接使用JDBC的提交和回滾設置。

MANAGED:讓容器來管理事務的整個生命週期。
10. dataSource :數據源
dataSource元素使用標準的JDBC數據源接口來配置JDBC鏈接對象的資源。

MyBatis 三種內建的數據源類型,即type=」\[UNPOOLED | POOLED | JNDI\]」;
1.  UNPOOLED :不支持JDBC數據源鏈接池,實現的只是每次被請求時打開和關閉鏈接。屬性有:
    1)driver :JDBC驅動的Java類的徹底限定名,如 MySQL 的com.mysql.jdbc.Driver
    2)url :數據庫的JDBC URL地址。
    3)username :數據庫的用戶名。
    4)password :數據庫的密碼。
    5)defaultTransactionIsolationLevel :默認的鏈接事務隔離級別。

2.  POOLED :支持JDBC數據源鏈接池,利用「池」的概念將JDBC鏈接對象組織起來,避免了建立新的鏈接實例時所必須的初始化和認證時間。

3.  JNDI :支持外部數據源鏈接池,它的實現是爲了能在如EJB或應用服務器這類容器中使用。
11. databaseIdProvider 數據庫廠商標識
12. mappers 映射器
mappers 映射器用於引用已經定義好的映射文件,告訴MyBatis 去哪尋找映射SQL的語句。

常見的方法有:
1)經過resource加載單個映射文件
<mappers>
<mapper resource="com/shiyanlou/mybatis/mapper/UserMapper.xml"/> 
</mappers>

2)經過徹底限定資源定位符(絕對路徑前加上 「file:///」 )加載單個映射文件。
<mappers>  
<mapper url="file:///home/project/MyBatisTest/src/com/shiyanlou/mybatis/mapper/UserMapper.xml"/>  
</mappers>

3) 經過mapper接口對象加載單個映射文件。
<mappers>  
<mapper class="com.shiyanlou.mybatis.mapper.UserMapper"/>  
</mappers>

4)  經過mapper接口包加載整個包的映射文件。
<mappers>  
<package name="com.shiyanlou.mybatis.mapper" />  
</mappers>

如下是一個簡單的 MyBatis.xml 的配置文件:

<?xml version="1.0" encoding="UTF-8"?>  
<!DOCTYPE configuration PUBLIC "-[//mybatis.org//DTD](//mybatis.org//DTD) Config 3.0//EN" "[http://mybatis.org/dtd/mybatis-3-config.dtd](http://mybatis.org/dtd/mybatis-3-config.dtd)">
<configuration>
    <!-- 爲 JavaBean 起類別名 -->
    <typeAliases>
    <!-- 指定一個包名起別名,將包內的 Java 類的類名做爲類的類別名 -->
    <package name="com.springMybatis.demo" />
    </typeAliases>

    <!-- 配置 mybatis 運行環境 -->
    <environments default="development">
    <environment id="development">
    <!-- type="JDBC" 表明直接使用 JDBC 的提交和回滾設置 -->
    <transactionManager type="JDBC" />
    <!-- POOLED 表示支持 JDBC 數據源鏈接池 -->
    <!\-\- 數據庫鏈接池,由 Mybatis 管理,數據庫名是 mybatis,MySQL 用戶名 root,密碼爲空 -->
    <dataSource type="POOLED">
        <property name="driver" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost:3306/mybatis" /
        <property name="username" value="root" />
        <property name="password" value="數據庫密碼" />
    </dataSource>
</environment>
</environments>

<mappers>
<!-- 經過 mapper 接口包加載整個包的映射文件 -->
<package name="cn.dbOperation.demo" />
</mappers>

</configuration>

MyBatis 映射文件:

映射文件是全部SQL語句放置的地方,寫好SQL語句映射文件後,須要在mybatis.xml配置文件的mappers標籤中引用。

映射文件包含的頂級元素:

1.  cache :給定命名空間的緩存配置。
2.  cache-ref :其餘命名空間緩存配置的引用。
3.  resultMap :描述如何從數據庫結果集中來加載對象。
4.  sql :可被其它語句引用的可重用語句塊。
5.  insert :映射插入語句。
6.  updata :映射更新語句。
7.  delete :映射刪除語句。
8.  select :映射查詢語句。

resultMap:

在映射文件中也是最複雜最強大的,resultMap的設計就是簡單語句不須要明確的結果映射,而不少複雜語句確實須要描述它們的關係。
resultMap的子元素包括:
1.  constructor :用來將結果注入到一個實例化好的類的構造方法中。
2.  idArg :ID參數,標記結果做爲ID。
3.  arg :注入到構造方法的一個普通結果。
4.  id :一個ID結果,標記結果做爲ID。
5.  result :注入到字段或JavaBean屬性的普通結果。
6.  association :複雜的類型關聯,多個結果合成的類型。
7.  collection :複雜類型的集,也能夠引用一個外部結果映射。
8.  discriminator :使用結果值來決定使用哪一個結果集。
9.  case :基本一些值的結果映射。
resultMap的屬性包括:
1.  id :當前命名空間中的一個惟一標識,用於標識一個resultMap
2.  type :類的全限定名,或者一個類型別名。
3.  automapping :爲這個ResultMap開啓或關閉自動映射,改屬性會覆蓋全局的屬性autoMappingBehavior,默認值爲:unset

動態SQL語句:

MyBatis 經常使用的動態 SQL 元素包括:
1.  if
2.  choose(when, otherwise)
3.  trim(where, set)
4.  foreach
5.  bind
if
if 在 where 子句中作簡單的條件判斷;
若是addres爲空,則where id = #{id}。
若是 addres 不爲空, 則where id = #{id} and addres = #{addres};

<select id="selectUserTest" parameterType="int" resultType="User"> 
select * from User where id = #{id} <if test="addres != null"> and addres = #{addres} </if>
</select>
choose(when, otherwise):
choose 的用法和 java 的switch相似。
按照順序執行,當when中有條件知足時,則跳出choose,當全部when的條件都不知足時就輸出otherwise的內容。

<!\-\- select id="selectUserTest" parameterType="int" resultType="User">
select * from User where id = #{id}
    <choose>
        <when test="username != null">
            and username = #{username}
        </when>
        <when test="phone != null">
            and phone = #{phone}
        </when>
        <otherwise>
            and addres = #{addres}
        </otherwise>
    </choose>
</select -->
trim(where, set):
trim 元素能夠給本身包含的內容加上前綴(prefix)或加上後綴(suffix)。
也能夠把包含內容的首部(prefixOverrides)或尾部(suffixOverrides)某些內容移除;

<select id="selectUserTest" parameterType="int" resultType="User">
    select * from User
    <trim prefix="where" prefixOverrides="and | or">
        <if test="id != null">
        id = #{id}
        </if>
        <if test="addres != null">
        and addres = #{addres}
        </if>
    </trim>
</select>

where 元素知道只有在一個以上的 if 條件知足的狀況下才去插入 where 子句,並且可以智能地處理and和or條件;
<select id="dynamicWhereTest" resultType="User">
    select * from user
    <where>
        <if test="address != null">
        address = #{address}
        </if>
        <if test="phone != null">
        and phone like #{phone}
        </if>
    </where>
</select>

set 元素能夠被用於動態包含須要更新的列,而捨去其餘的
<update id="dynamicSetTest">
    update User
    <set>
        <if test="phone != null">phone=#{phone},</if>
        <if test="address != null">address=#{address}</if>
    </set> where id=#{id}
</update>
foreach:
foreach 元素經常使用到須要對一個集合進行遍歷時,在in語句查詢時特別有用:
foreach元素的主要屬性:
1.  item :本次迭代獲取的元素;
2.  index : 當前迭代的次數;
3.  open :開始標誌;
4.  separator :每次迭代之間的分隔符;
5.  close :結束標誌;
6.  collection :該屬性必須指定(一、單參數且爲List時,值爲list。 二、單參數且爲array時,值爲array。 三、多參數需封裝成一個Map,map的key就是參數名)

<select id="selectUser" parameterType="int" resultType="User">
    select * from User where id in
    <foreach collection="list" item="item" index="index"
        open = "(" separator="," close=")">
        #{item}
        </foreach>
</select>
bind:
bind 元素能夠從OGNL表達式中建立一個變量並將其綁定到上下文。

<select id="selectUser" parameterType="int" resultType="User">
    <bind name="pattern" value="'%' + _parameter.getPhone() + '%'"/>
    select * from User where phone like #{pattern}
</select>

MyBatis、JDBC、Hibernate的區別:

MyBatis也是基於JDBC的,Java與數據庫操做僅能經過JDBC完成。MyBatis也要經過JDBC完成數據查詢、更新這些動做。
MyBatis僅僅是在JDBC基礎上作了 OO化、封裝事務管理接口這些東西。
MyBatis和Hibernate都屏蔽JDBC API的底層訪問細節,使咱們不用跟JDBC API打交道就能夠訪問數據庫。
可是,Hibernate是全自動的ORM映射工具,能夠自動生成SQL語句。
MyBatis須要在xml配置文件中寫SQL語句。
由於Hibernate是自動生成SQL語句的,在寫複雜查詢時,Hibernate實現比MyBatis複雜的多。
相關文章
相關標籤/搜索