MyBatis快速入門

1、概述

MyBatis是Apache的一個開源項目,是一個基於Java的持久層框架。它支持普通SQL查詢、存儲過程以及高級映射。消除了幾乎全部的JDBC代碼,而且基本不須要手動去設置參數和獲取檢索結果。使用XML或者註解進行配置,可以映射基本數據元素、Map接口和POJO到數據庫。java

2、框架

MyBatis的功能架構分三層:基礎支撐層、數據處理層、API接口層。mysql

  1. 基礎支撐層sql

    負責最基本的功能支撐,包括鏈接管理、事務管理、配置加載和緩存處理。基礎支撐層爲上層的數據處理層提供了最基礎的支撐。數據庫

  2. 數據處理層緩存

    負責具體的SQL查詢、SQL解析、SQL執行和執行結果的映射處理等。數據處理層的主要目的是根據調用的請求完成一次數據庫操做。mybatis

  3. API接口層架構

    提供給外部使用的接口API,經過這些API來操做數據庫。接口層接收到調用請求會馬上調用數據處理層來完成具體的操做。oracle

3、工做流程

一、加載配置並初始化

經過配置文件或註解,將SQL的配置信息加載成MappedStatement對象,存儲在內存中。app

二、接收調用請求

調用MyBatis提供的API,並將請求傳遞給下層的數據處理層進行處理。框架

三、處理操做請求

  • 根據傳入的SQL的ID查找對應的MappedStatement對象
  • 根據傳入的參數解析MappedStatement對象,獲得要執行的SQL
  • 獲取數據庫鏈接,執行SQL,並獲得執行結果
  • 根據MappedStatement對象中的結果映射配置,對執行結果進行轉換處理,獲得最終結果
  • 釋放鏈接資源

四、返回處理結果

4、實現

一、建立與表對應的實體類

二、建立映射文件xxxMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper .//EN" "http://mybatis.org/dtd/mybatis--mapper.dtd">

<mapper namespace="com.demo.ssm.mapping.userMapper">
    <select id="getUser" parameterType="int" resultType="User">
        select * from user where id = #{id}
    </select>
</mapper>

其中,namespace屬性用來定義mapper的命名空間。<select>標籤中的id屬性用來標識sql語句,值必須惟一。parameterType屬性用來定義查詢時使用的參數類型。resultType屬性用來定義查詢返回的結果集類型。若是返回的結果集是個列表,應該定義resultMap類型。

<resultMap id="resultListUser" type="User">
    <id column="id" property="id" />
    <result column="userName" property="userName" />
    <id column="userAge" property="userAge" />
</resultMap>

<mapper namespace="com.demo.ssm.mapping.userMapper">
    <select id="getUsers" parameterType="string" resultMap="resultListUser">
        select * from user where username like #{userName}
    </select>
</mapper>

三、配置MyBatis的配置文件

<?xml version="." encoding="UTF-"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config .//EN" "http://mybatis.org/dtd/mybatis--config.dtd">

<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC" />
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver" />
                <property name="url" value="jdbc:mysql://localhost:/mybatis" />
                <property name="username" value="root" />
                <property name="password" value="root" />
            </dataSource>
        <environment>
    <environments>

    <mappers>
        <mapper resource="com.demo.ssm.mapping.userMapper.xml">
    </mappers>
</configuration>

5、關聯查詢

在實際應用中,常常須要進行關聯查詢,如一對多、多對一等。這時,就須要在配置文件中使用<association>標籤進行關聯。關聯查詢的配置有兩種方式:內部關聯和外部關聯。

一、在內部關聯

<resultMap id="resultUserArticleList" type="Article">
    <id property="id" column="aid" />
    <result property="title" column="title" />
    <result property="content" column="content" />
    <association property="user" javaType="User">
        <id property="id" column="id" />
        <result property="userName" column="userName" />
        <result property="userAge" column="userAge" />
    </association>
</resultMap>

<select id="getUserArticles" parameterType="int" resultMap="resultUserArticleList">
    select user.id,user.userName,user.userAge,article.id aid,article.title,article.content from user,article
    where user.id=article.userid and user.id=#{id}
</select>

二、從外部關聯

<resultMap type="User" id="resultListUser">
    <id column="id" property="id" />
    <result column="userName" property="userName" />
    <result column="userAge" property="userAge" />
</resultMap>

<resultMap id="resultUserArticleList" type="Article">
    <id property="id" column="aid" />
    <result property="title" column="title" />
    <result property="content" column="content" />
    <association property="user" javaType="User" resultMap="resultListUser" />
</resultMap>

<select id="getUserArticles" parameterType="int" resultMap="resultUserArticleList">
    select user.id,user.userName,user.userAge,article.id aid,article.title,article.content from user,article
    where user.id=article.userid and user.id=#{id}
</select>

很顯然,第二種方式更容易達到複用的效果。

6、分頁

在實際應用中,若是查詢返回的結果記錄不少,就須要作物理分頁。不一樣的數據庫,對應不一樣的實現方法。mysql利用limit offset和pagesize來實現,而oracle利用rownum來實現。實現MyBatis的物理分頁。

一、在mapper的sql語句中直接使用分頁條件

<select id="getUserArticles" parameterType="params" resultMap="resultUserArticleList">
    select user.id,user.userName,user.userAge,article.id aid,article.title,article.content from user,article
    where user.id=article.userid and user.id=#{id} limit #{offset},#{pagesize}
</select>

這裏的parameterType是傳入的參數類或者Map,包含offset和pagesize,以及其餘須要的參數。相對來講,這是比較簡單的一種方式。

二、使用MyBatis插件

更通用的一種方式是使用插件進行分頁。使用插件的話,須要在MyBatis的配置文件中進行設置。

7、動態SQL

MyBatis的動態sql語句是基於OGNL表達式的,能夠很方便地在sql語句中實現某些邏輯。

一、if

<select id="dynamicIf" parameterType="User" resultType="User">
    select * from user where 1 = 1
    <if test="userName != null">
        and userName = #{userName}
    </if>
</select>

若是提供的userName參數不爲空,就爲sql語句動態添加userName=#{userName}的語句。

二、choose

<select id="dynamicChoose" parameterType="User" resultType="User">
    select * from user where 1 = 1
    <choose>
        <when test="userName != null">
            and userName = #{userName}
        </when>
        <otherwise>
            and userName = "sean"
        </otherwise>
    </choose>
</select>

當userName不爲空時,爲sql語句動態添加userName=#{userName}。不然,爲sql語句動態添加userName="sean"語句。當條件知足時,再也不繼續判斷,直接跳出choose。當全部條件都不知足時,輸出otherwise中的內容。

三、where

<select id="dynamicWhere" parameterType="User" resultType="User">
    select * from user
    <where>
        <if test="userName != null">
            userName = #{userName}
        </if>
    </where>
</select>

在where元素的地方輸出一個where,而且可以智能地處理and和or條件。主要用來簡化sql語句中where條件判斷。

四、trim

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

用來給包含的內容加上前綴或後綴,也能夠把包含內容的首部或尾部的某些內容覆蓋。一般能夠利用trim來代替where元素的功能。

五、set

<update id="dynamicSet" parameterType="User">
    update user
    <set>
        <if test="userName != null">
            userName = #{userName}
        </if>
    </set>
    where userId = #{userId}
</update>

主要用於更新操做,在包含的語句前輸出一個set,功能和where元素基本相同。

六、foreach

主要用於構建in條件,能夠在sql語句中迭代一個集合。foreach元素主要有幾個屬性:

  • item:表示每一個元素在進行迭代時的別名
  • index:表示在迭代時,每次迭代到的位置
  • open:表示語句以什麼開始
  • separator:表示迭代之間以什麼做爲分隔符
  • close:表示語句以什麼結束
  • collection:表示集合

不一樣狀況下,collection屬性的值是不一樣的。若是傳入的是單參數且參數類型是一個List的時候,屬性值爲list。

<select id="dynamicForeachList" resultType="User">
    select * from user where userId in
    <foreach collection="list" index="index" item="item" open="(" separator="," close=")">
        #{item}
    </foreach>
</select>

若是傳入的是單參數且參數類型是一個Array的時候,屬性值爲array。

<select id="dynamicForeachArray" resultType="User">
    select * from user where userId in
    <foreach collection="array" index="index" item="item" open="(" separator="," close=")">
        #{item}
    </foreach>
</select>

若是傳入的是多個參數時,將參數封裝成一個Map,屬性值爲map裏的key。

<select id="dynamicForeachMap" resultType="User">
    select * from user where userName like "%"#{userName}"%" and userId in
    <foreach collection="ids" index="index" item="item" open="(" separator="," close=")">
        #{item}
    </foreach>
</select>

8、代碼生成工具

因爲MyBatis應用程序須要大量的配置文件,若是徹底手工配置,工做量巨大。MyBatis官方推出一個代碼生成工具mybatis-generator-core的jar包,以便提升效率。

代碼生成工具主要有幾個功能:

  • 生成pojo與數據庫結構相對應
  • 若是有主鍵,可以匹配主鍵;若是沒有主鍵,能夠用其餘字段匹配
  • 動態select、update、delete方法
  • 自動生成接口
  • 自動生成mapper,以及對單表的增刪改查語句配置
  • 提供例子以供參考

首先須要建立一個配置文件,進行生成工具的各類設置。

<generatorConfiguration>
    <!-- 配置mysql驅動jar包路徑 -->
    <classPathEntry location=""
    <context id="mysql_tables" targetRuntime="MyBatis3">
    <!-- 控制生成代碼中的註釋 -->
    <commentGenerator>
        <property name="suppressAllComments" value="true" />
        <property name="suppressDate" value="true" />
    </commentGenerator>
    <!-- 數據庫鏈接 -->
    <jdbcConnection driverClass="com.mysql.jdbc.Driver"
        connectionURL="jdbc:mysql://127.0.0.1:3306/mybatis?characterEncoding=utf8"
        userId="root"
        password="root">
    </jdbcConnection>
    <javaTypeResolver>
        <property name="forceBigDecimals" value="false" />
    </javaTypeResolver>
    <!-- model層 -->
    <javaModelGenerator targetPackage="com.demo.ssm.model" targetProject="src">
        <property name="enableSubPackages" value="true" />
        <property name="trimStrings" value="true" />
    </javaModelGenerator>
    <!-- mapper映射文件 -->
    <sqlMapGenerator targetPackage="com.demo.ssm.mapper" targetProject="src">
        <property name="enableSubPackages" value="true" />
    </sqlMapGenerator>
    <!-- mapper接口 -->
    <javaClientGenerator type="XMLMAPPER" targetPackage="com.demo.ssm.inter" targetProject="src">
        <property name="enableSubPackages" value="true" />
    </javaClientGenerator>
    <!-- 指定要生成代碼的數據庫表 -->
    <table schema="mybatis" tableName="user" domainObjectName="User"
        enableCountByExample="false" enableUpdateByExample="false"
        enableDeleteByExample="false" enableSelectByExample="false"
        selectByExampleQueryId="false">
    </table>
    </context>
</generatorConfiguration>

而後建立一個代碼生成類,用於生成代碼。

public class GenMain {
    public static void main(String[] args) {
        List<String> warnings = new ArrayList<String>();
        boolean overwrite = true;
        String genCfg = "/mbgConfiguration.xml";
        File configFile = new File(GenMain.class.getResource(genCfg).getFile());
        ConfigurationParser cp = new ConfigurationParser(warnings);
        Configuration config = null;
        try {
            config = cp.parseConfiguration(configFile);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (XMLParserException e) {
            e.printStackTrace();
        }
        DefaultShellCallback callback = new DefaultShellCallback(overwrite);
        MyBatisGenerator myBatisGenerator = null;
        try {
            myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
        } catch (InvalidConfigurationException e) {
            e.printStackTrace();
        }
        try {
            myBatisGenerator.generate(null);
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
相關文章
相關標籤/搜索