MyBatis快速入門

一、概述

MyBatis是Apache的一個開源項目,是一個基于Java的持久層框架。它支持普通SQL查詢、存儲過程以及高級映射。消除了幾乎所有的JDBC代碼,并且基本不需要手動去設置參數(shù)和獲取檢索結果。使用XML或者注解進行配置,能夠映射基本數(shù)據(jù)元素、Map接口和POJO到數(shù)據(jù)庫。

二、框架

MyBatis的功能架構分三層:基礎支撐層、數(shù)據(jù)處理層、API接口層。

  1. 基礎支撐層

    負責最基本的功能支撐,包括連接管理、事務管理、配置加載和緩存處理?;A支撐層為上層的數(shù)據(jù)處理層提供了最基礎的支撐。

  2. 數(shù)據(jù)處理層

    負責具體的SQL查詢、SQL解析、SQL執(zhí)行和執(zhí)行結果的映射處理等。數(shù)據(jù)處理層的主要目的是根據(jù)調(diào)用的請求完成一次數(shù)據(jù)庫操作。

  3. API接口層

    提供給外部使用的接口API,通過這些API來操作數(shù)據(jù)庫。接口層接收到調(diào)用請求會立刻調(diào)用數(shù)據(jù)處理層來完成具體的操作。

三、工作流程

1、加載配置并初始化

通過配置文件或注解,將SQL的配置信息加載成MappedStatement對象,存儲在內(nèi)存中。

2、接收調(diào)用請求

調(diào)用MyBatis提供的API,并將請求傳遞給下層的數(shù)據(jù)處理層進行處理。

3、處理操作請求

  • 根據(jù)傳入的SQL的ID查找對應的MappedStatement對象
  • 根據(jù)傳入的參數(shù)解析MappedStatement對象,得到要執(zhí)行的SQL
  • 獲取數(shù)據(jù)庫連接,執(zhí)行SQL,并得到執(zhí)行結果
  • 根據(jù)MappedStatement對象中的結果映射配置,對執(zhí)行結果進行轉換處理,得到最終結果
  • 釋放連接資源

4、返回處理結果

四、實現(xiàn)

1、創(chuàng)建與表對應的實體類

2、創(chuàng)建映射文件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屬性用來定義查詢時使用的參數(shù)類型。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>

3、配置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>

五、關聯(lián)查詢

在實際應用中,經(jīng)常需要進行關聯(lián)查詢,如一對多、多對一等。這時,就需要在配置文件中使用<association>標簽進行關聯(lián)。關聯(lián)查詢的配置有兩種方式:內(nèi)部關聯(lián)和外部關聯(lián)。

1、在內(nèi)部關聯(lián)

<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>

2、從外部關聯(lián)

<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>

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

六、分頁

在實際應用中,如果查詢返回的結果記錄很多,就需要做物理分頁。不同的數(shù)據(jù)庫,對應不同的實現(xiàn)方法。mysql利用limit offset和pagesize來實現(xiàn),而oracle利用rownum來實現(xiàn)。實現(xiàn)MyBatis的物理分頁。

1、在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是傳入的參數(shù)類或者Map,包含offset和pagesize,以及其他需要的參數(shù)。相對來說,這是比較簡單的一種方式。

2、使用MyBatis插件

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

七、動態(tài)SQL

MyBatis的動態(tài)sql語句是基于OGNL表達式的,可以很方便地在sql語句中實現(xiàn)某些邏輯。

1、if

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

如果提供的userName參數(shù)不為空,就為sql語句動態(tài)添加userName=#{userName}的語句。

2、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語句動態(tài)添加userName=#{userName}。否則,為sql語句動態(tài)添加userName="sean"語句。當條件滿足時,不再繼續(xù)判斷,直接跳出choose。當所有條件都不滿足時,輸出otherwise中的內(nèi)容。

3、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條件判斷。

4、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>

用來給包含的內(nèi)容加上前綴或后綴,也可以把包含內(nèi)容的首部或尾部的某些內(nèi)容覆蓋。通??梢岳胻rim來代替where元素的功能。

5、set

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

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

6、foreach

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

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

不同情況下,collection屬性的值是不同的。如果傳入的是單參數(shù)且參數(shù)類型是一個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>

如果傳入的是單參數(shù)且參數(shù)類型是一個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>

如果傳入的是多個參數(shù)時,將參數(shù)封裝成一個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>

八、代碼生成工具

由于MyBatis應用程序需要大量的配置文件,如果完全手工配置,工作量巨大。MyBatis官方推出一個代碼生成工具mybatis-generator-core的jar包,以便提高效率。

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

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

首先需要創(chuàng)建一個配置文件,進行生成工具的各種設置。

<generatorConfiguration>
    <!-- 配置mysql驅(qū)動jar包路徑 -->
    <classPathEntry location=""
    <context id="mysql_tables" targetRuntime="MyBatis3">
    <!-- 控制生成代碼中的注釋 -->
    <commentGenerator>
        <property name="suppressAllComments" value="true" />
        <property name="suppressDate" value="true" />
    </commentGenerator>
    <!-- 數(shù)據(jù)庫連接 -->
    <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>
    <!-- 指定要生成代碼的數(shù)據(jù)庫表 -->
    <table schema="mybatis" tableName="user" domainObjectName="User"
        enableCountByExample="false" enableUpdateByExample="false"
        enableDeleteByExample="false" enableSelectByExample="false"
        selectByExampleQueryId="false">
    </table>
    </context>
</generatorConfiguration>

然后創(chuàng)建一個代碼生成類,用于生成代碼。

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();
        }
    }
}
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容