MyBatis框架使用解析!數據庫相關API的基本介紹

動態SQL

if

  • 根據條件包含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元素只會在子元素返回內容的狀況下才會插入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屬性中指定的內容,而且插入prefix屬性中指定的內容:
    <trim prefix="WHERE" prefixOverrides="AND |OR">
     	...
     </trim>
    複製代碼
    prefixOverrides屬性會忽略經過管道符分割的文本序列 ,不一樣的文本序列之間必需要有空格.
    • set元素等價的自定義trim元素. 覆蓋了後綴值設置,而且自定義前綴值:
    <trim prefix="SET" suffixOverrides=",">
    	...
    </trim>
    複製代碼

set

  • 用於動態更新語句的叫做set
  • set元素能夠用於動態包含須要更新的列,忽略不更新的列
<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元素會動態地進行行首插入SET關鍵字,並會刪掉額外的逗號,這些逗號是在使用條件語句給列賦值時引入的

foreach

  • 對集合進行遍歷的時候使用foreach, 特別是在構建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容許指定一個集合:
    • 聲明能夠在元素體內使用的集合項item和索引index變量
    • 指定開頭open與結尾close的字符串以及集合項迭代之間的分隔符separator
    • foreach不會錯誤地添加多餘的分隔符
  • 使用foreach時:
    • 能夠將任何可迭代對象,好比List,Set,Map對象或者數組對象做爲集合參數傳遞給foreach
    • 當使用可迭代對象或者數組時:
      • index是當前迭代的序號
      • item的值是本次迭代獲取到的元素
    • 當使用Map對象或者Map.Entry對象的集合
      • index是鍵
      • item是值

script

  • 要是想要在帶註解的接口類中使用動態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表達式之外建立一個變量,並綁定到上下文中
<select id="selectBlogsLike" resultType="Blog">
	<bind name="pattern" value="'%' + _parameter.getTitle() + '%'" />
	SELECT * FROM BLOG
	WHERE title LIKE #{pattern}
</select>
複製代碼

多數據庫支持

  • 若是配置了databaseIdProvider, 就能夠在動態代碼中使用名爲 "_databaseId" 的變量來爲不一樣的數據庫構建特定的語句
<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>
複製代碼

動態SQL中插入腳本語言

  • MyBatis 3.2版本開始支持插入腳本語言
  • 容許插入一種語言驅動,並基於這種語言來編寫動態SQL查詢語句
  • 經過實現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);
}
複製代碼
  • 實現自定義語言驅動後,能夠在mybatis-config.xml文件中設置爲默認語言:
<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標籤都由默認MyBatis語言提供,是由語言驅動org.apache.ibatis.scripting.xmltags.XmlLanguageDriver, 別名爲xml. 提供的.

Java API

  • MyBatis的執行方法在SqlSession類中

語句執行方法

  • 這些方法被用來執行定義在SQL映射XML文件中的SELECT,INSERT,UPDATE和DELETE語句
    • 每個方法都接收語句的ID以及參數對象
    • 參數能夠是原始類型(支持自動裝箱),包裝類,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);
複製代碼
  • 遊標Cursor與列表List返回的結果相同,不一樣的是: 遊標藉助迭代器實現了數據的惰性加載
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值,從而將多個結果集轉爲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
  • 因爲不是全部語句都須要參數,因此這些方法都具備一個不須要參數的重載形式
  • insert, updatedelete方法返回值表示受該語句影響的行數

select高級版本

  • 容許限制返回行數的範圍
  • 提供自定義結果處理邏輯
  • 一般是在數據集很是龐大的情形下使用
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參數:
    • 指定MyBatis略過指定數量的記錄,並限制返回結果的數量
    • RowBounds類的offset和limit值只有在構造函數時才能傳入,其餘時候是不能修改的
    int offset = 100;
    int limit = 25;
    RowBounds rowBounds = new RowBounds(offset, limit);
    複製代碼
  • ResultHandler參數:
    • 容許自定義每行結果的處理過程
    • 能夠添加到List中,建立Map和Set. 甚至丟棄每一個返回值,只保留計算後的統計結果
  • ResultHandler接口:
package org.apache.ibatis.session;
public interface ResultHandler<T> {
	void handlerResult(ResultContext<? extends T> context);
}
複製代碼
  • ResultContext參數:
    • 容許訪問結果對象和當前已被建立的對象數目
    • 提供一個返回值爲Booleanstop方法,能夠使用這個stop方法來中止MyBatis加載更多的結果
  • 使用ResultHandler要注意兩條限制:
    • 使用帶ResultHandler參數的方法時,收到的數據不會被緩存
    • 當使用高級的結果映射集resultMap,MyBatis極可能須要數行結果來構造一個對象.若是這時使用了ResultHandler, 可能會接收到關聯association或者集合collection中還沒有被完整填充的對象

清除批量更新方法

  • ExecutorType設置爲ExecutorType.BATCH時,能夠使用flushStatements清除緩存在JDBC驅動類中的批量更新語句
flushStatements
List<BatchResult> flushStatements();
複製代碼

事務控制方法

  • 控制事務做用域的方法有四個,若是已經設置了自動提交或者使用了外部事務管理器, 就不須要使用這些方法
  • 若是正在使用Connection實例控制的JDBC事務管理器,就能夠使用如下的四個方法:
void commit();

void commit(boolean force);

void rollback();

void rollback(boolean force);
複製代碼
  • 默認狀況下 ,MyBatis不會自動提交事務,除非發現到調用了插入,更新或刪除方法改變了數據庫
  • 若是沒有使用這些方法提交修改,那麼就能夠在commitrollback方法參數傳入true值來保證事務被正常提交
    • 注意: 在自動提交模式或者使用了外部事務管理器的狀況下,設置force值對session無效
  • 大部分狀況下,無需調用rollback(), 由於MyBatis會在沒有調用commit() 時完成回滾操做
  • 可是,當要在一個可能屢次提交或回滾的session中詳細控制事務,就要使用到回滾rollback操做
相關文章
相關標籤/搜索