MyBatis框架使用解析!數(shù)據(jù)庫相關(guān)API的使用介紹

動態(tài)SQL

if

  • 根據(jù)條件包含where子句的一部分
<select id="findActiveBlogLike" resultType="Blog">
    SELECT * FROM BLOG WHERE state = 'ACTIVE'
    <where>
        <if test="title != null">
            AND title like #{title}
        </if>
        <if test="author != null and author.name != null">
            AND author_name like #{author.name}
        </if>
    </where>
</select>
  • 緊接著 < where > 的第一個條件不要加AND

choose-when-otherwise

  • 不使用所有的條件,只是想從多個條件中選擇一個使用
<select id="findActiveBlogLike" resultType="Blog">
    SELECT * FROM BLOG WHERE state = 'ACTIVE'
    <choose>
        <when tset="title != null">
            AND title like #{title}
        </when>
        <when test="author != null and author.name != null">
            AND author_name like #{author.name}
        </when>
        <otherwise>
            AND featured = 1
        </otherwise>
    </choose>
</select>

where

  • where元素只會在子元素返回內(nèi)容的情況下才會插入WHRER的子語句
  • 若子語句的開頭為AND或者OR,where元素會將這些去除
<select id="findActiveBlogLike" resultType="Blog">
    SELECT * FROM BLOG
    <where>
        <if test="state != null">
            state = #{state}
        </if>
        <if test="title != null">
            AND title like #{title}
        </if>
        <if test="author != null and author.name != null">
            AND author_name like #{author.name}
        </if>
    </where>
</select>

trim

  • 可以通過自定義trim元素來定制where元素的功能
    • 比如和where元素等價的自定義trim元素.會移除所有prefixOverrides屬性中指定的內(nèi)容,并且插入prefix屬性中指定的內(nèi)容:
     <trim prefix="WHERE" prefixOverrides="AND |OR">
         ...
     </trim>
    
    prefixOverrides屬性會忽略通過管道符分割的文本序列 ,不同的文本序列之間必須要有空格.
    • set元素等價的自定義trim元素. 覆蓋了后綴值設(shè)置,并且自定義前綴值:
    <trim prefix="SET" suffixOverrides=",">
        ...
    </trim>
    

set

  • 用于動態(tài)更新語句的叫作set
  • set元素可以用于動態(tài)包含需要更新的列,忽略不更新的列
<update id="updateAuthorIfNecessary">
    update Author
        <set>
            <if test="username != null">
                username = #{username},
            </if>
            <if test="password != null">
                password = #{password},
            </if>
            <if test="email != null">
                email = #{email},
            </if>
            <if test="bio != null">
                bio = #{bio}
            </if>
        </set>
    where id = #{id}
</update>
  • set元素會動態(tài)地進行行首插入SET關(guān)鍵字,并會刪掉額外的逗號,這些逗號是在使用條件語句給列賦值時引入的

foreach

  • 對集合進行遍歷的時候使用foreach, 特別是在構(gòu)建IN條件語句的時候
<select id="selectPostIn" resultType="domain.blog.Post">
    SELECT * 
    FROM POST p
    WHERE ID IN
    <foreach item="item" index="index" collection="list" open="(" separator="," close=")">
        #{item}
    </foreach> 
</select>
  • foreach允許指定一個集合:
    • 聲明可以在元素體內(nèi)使用的集合項item和索引index變量
    • 指定開頭open與結(jié)尾close的字符串以及集合項迭代之間的分隔符separator
    • foreach不會錯誤地添加多余的分隔符
  • 使用foreach時:
    • 可以將任何可迭代對象,比如List,Set,Map對象或者數(shù)組對象作為集合參數(shù)傳遞給foreach
    • 當(dāng)使用可迭代對象或者數(shù)組時:
      • index是當(dāng)前迭代的序號
      • item的值是本次迭代獲取到的元素
    • 當(dāng)使用Map對象或者Map.Entry對象的集合
      • index是鍵
      • item是值

script

  • 要是想要在帶注解的接口類中使用動態(tài)SQL語句,可以使用script元素
@update({"<script>",
            "update Author",
                "<set>",
                    "<if test='username != null'>username=#{username},</if>",
                    "<if test='password != null'>password=#{password},</if>",
                    "<if test='email != null'>email=#{email},</if>",    
                "</set>",
                "where id=#{id}",
                "</script>"})   
})
void updateAuthorValues(Author author);

bind

  • 可以使用bind元素在OGNL表達式以外創(chuàng)建一個變量,并綁定到上下文中
<select id="selectBlogsLike" resultType="Blog">
    <bind name="pattern" value="'%' + _parameter.getTitle() + '%'" />
    SELECT * FROM BLOG
    WHERE title LIKE #{pattern}
</select>

多數(shù)據(jù)庫支持

  • 如果配置了databaseIdProvider, 就可以在動態(tài)代碼中使用名為 "_databaseId" 的變量來為不同的數(shù)據(jù)庫構(gòu)建特定的語句
<insert id="insert">
    <selectKey keyProperty="id" resultType="int" order="BEFORE">
        <if test="_databaseId == 'oracle'">
            select seq_users.nextval from dual
        </if>
        <if test="_databaseId == 'db2'">
            select nextval for seq_users from sysibm.sysdummy1
        </if>
    </selectKey>
    insert into users values (#{id}, #{name})
</insert>

動態(tài)SQL中插入腳本語言

  • MyBatis 3.2版本開始支持插入腳本語言
  • 允許插入一種語言驅(qū)動,并基于這種語言來編寫動態(tài)SQL查詢語句
  • 通過實現(xiàn)LanguageDriver接口插入語言:
public interface LanguageDriver {
    ParameterHandler createParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql);
    
    SqlSource createSqlSource(Configuration configuration, XNode script, Class<?> parameterType);
    SqlSource crateSqlSource(Configuration configuration, String script, Class<?> parameterType);
}
  • 實現(xiàn)自定義語言驅(qū)動后,可以在mybatis-config.xml文件中設(shè)置為默認(rèn)語言:
<typeAliases>
    <typeAliase type="com.oxford.MyLanguageDriver" alias="myLanguage" />
</typeAliases>
<settings>
    <setting name="defaultScriptingLanguage" value="myLanguage" />
</settings>
  • 也可以使用lang屬性為特定的語句指定語言:
<select id="selectBlog" lang="myLanguage">
    SELECT * FROM BLOG
</select>
  • 或者在mapper接口上使用 @Lang注解:
public interface Mapper {
    @Lang(MyLanguageDriver.class)
    @Select("SELECT * FROM BLOG")
    List<Blog> selectBlog();
}
  • MyBatis中的xml文件中的所有xml標(biāo)簽都由默認(rèn)MyBatis語言提供,是由語言驅(qū)動org.apache.ibatis.scripting.xmltags.XmlLanguageDriver, 別名為xml. 提供的.

Java API

  • MyBatis的執(zhí)行方法在SqlSession類中

語句執(zhí)行方法

  • 這些方法被用來執(zhí)行定義在SQL映射XML文件中的SELECT,INSERT,UPDATE和DELETE語句
    • 每一個方法都接收語句的ID以及參數(shù)對象
    • 參數(shù)可以是原始類型(支持自動裝箱),包裝類,JavaBean,POJO或者Map
selectOne
<T> T selectOne(String statement, Object parameter);
selectList
<E> List<E> selectList(String statement, Object parameter);
  • selectOne和selectList的不同點是:
    • selectOne必須返回一個對象或者null值, 如果返回值多于一個就會拋出異常
    • 如果不清楚返回對象會有多少個,就使用selectList
selectCursor
<T> Cursor<T> selectCursor(String statement, Object parameter);
  • 游標(biāo)Cursor與列表List返回的結(jié)果相同,不同的是: 游標(biāo)借助迭代器實現(xiàn)了數(shù)據(jù)的惰性加載
try (Cursor<Entity> entities = session.selectCursor(statement, param)) {
    for (Entity entity : entities) {
        // 處理單個實體
    }
}
     
selectMap
<K,V> Map<K,V> selectMap(String statement, Object parameter, String mapKey); 
  • selectMap會將返回對象的其中一個屬性作為key值,將對象作為value值,從而將多個結(jié)果集轉(zhuǎn)為Map類型值
insert
int insert(String statement, Object parameter);
update
int update(String statement, Object parameter);
delete
int delete(String statement, Obejct parameter);
  • 如果需要查看某個對象是否存在, 最好的辦法就是查詢一個count值,使用0或者1
  • 由于不是所有語句都需要參數(shù),所以這些方法都具有一個不需要參數(shù)的重載形式
  • insert, updatedelete方法返回值表示受該語句影響的行數(shù)

select高級版本

  • 允許限制返回行數(shù)的范圍
  • 提供自定義結(jié)果處理邏輯
  • 通常是在數(shù)據(jù)集非常龐大的情形下使用
selectList
<E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds);
selectCursor
<T> List<T> selectCursor(String statement, Object parameter, RowBounds rowBounds);
selectMap
<K, V> Map<K,V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds);
select
void select(String statement, Object parameter, ResultHandler<T> handler);
select
void select(String statement Object parameter, RowBounds rowBounds, ResultHandler<T> handler);
  • RowBounds參數(shù):
    • 指定MyBatis略過指定數(shù)量的記錄,并限制返回結(jié)果的數(shù)量
    • RowBounds類的offset和limit值只有在構(gòu)造函數(shù)時才能傳入,其他時候是不能修改的
    int offset = 100;
    int limit = 25;
    RowBounds rowBounds = new RowBounds(offset, limit);
    
  • ResultHandler參數(shù):
    • 允許自定義每行結(jié)果的處理過程
    • 可以添加到List中,創(chuàng)建Map和Set. 甚至丟棄每個返回值,只保留計算后的統(tǒng)計結(jié)果
  • ResultHandler接口:
package org.apache.ibatis.session;
public interface ResultHandler<T> {
    void handlerResult(ResultContext<? extends T> context);
}
  • ResultContext參數(shù):
    • 允許訪問結(jié)果對象和當(dāng)前已被創(chuàng)建的對象數(shù)目
    • 提供一個返回值為Booleanstop方法,可以使用這個stop方法來停止MyBatis加載更多的結(jié)果
  • 使用ResultHandler要注意兩條限制:
    • 使用帶ResultHandler參數(shù)的方法時,收到的數(shù)據(jù)不會被緩存
    • 當(dāng)使用高級的結(jié)果映射集resultMap,MyBatis很可能需要數(shù)行結(jié)果來構(gòu)造一個對象.如果這時使用了ResultHandler, 可能會接收到關(guān)聯(lián)association或者集合collection中尚未被完整填充的對象

清除批量更新方法

  • 當(dāng)ExecutorType設(shè)置為ExecutorType.BATCH時,可以使用flushStatements清除緩存在JDBC驅(qū)動類中的批量更新語句
flushStatements
List<BatchResult> flushStatements();

事務(wù)控制方法

  • 控制事務(wù)作用域的方法有四個,如果已經(jīng)設(shè)置了自動提交或者使用了外部事務(wù)管理器, 就不需要使用這些方法
  • 如果正在使用Connection實例控制的JDBC事務(wù)管理器,就可以使用以下的四個方法:
void commit();

void commit(boolean force);

void rollback();

void rollback(boolean force);
  • 默認(rèn)情況下 ,MyBatis不會自動提交事務(wù),除非發(fā)現(xiàn)到調(diào)用了插入,更新或刪除方法改變了數(shù)據(jù)庫
  • 如果沒有使用這些方法提交修改,那么就可以在commitrollback方法參數(shù)傳入true值來保證事務(wù)被正常提交
    • 注意: 在自動提交模式或者使用了外部事務(wù)管理器的情況下,設(shè)置force值對session無效
  • 大部分情況下,無需調(diào)用rollback(), 因為MyBatis會在沒有調(diào)用commit() 時完成回滾操作
  • 但是,當(dāng)要在一個可能多次提交或回滾的session中詳細(xì)控制事務(wù),就要使用到回滾rollback操作
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

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