動態 SQL 一般要作的事情是有條件地包含 where 子句的一部分。好比:數據庫
<select id="findActiveBlogWithTitleLike" resultType="Blog"> SELECT * FROM BLOG WHERE state = ‘ACTIVE’ <if test="title != null"> AND title like #{title} </if> </select>
<select id="findActiveBlogLike" resultType="Blog"> SELECT * FROM BLOG WHERE state = ‘ACTIVE’ <choose> <when test="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>
爲處理if動態拼接多餘的WHERE、AND關鍵詞:數組
<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>
where 元素知道只有在一個以上的if條件有值的狀況下才去插入「WHERE」子句。並且,若最後的內容是「AND」或「OR」開頭的,where 元素也知道如何將他們去除。oracle
若是 where 元素沒有按正常套路出牌,咱們仍是能夠經過自定義 trim 元素來定製咱們想要的功能。好比,和 where 元素等價的自定義 trim 元素爲:app
<trim prefix="WHERE" prefixOverrides="AND |OR "> ... </trim>
prefixOverrides 屬性會忽略經過管道分隔的文本序列(注意此例中的空格也是必要的)。它帶來的結果就是全部在 prefixOverrides 屬性中指定的內容將被移除,而且插入 prefix 屬性中指定的內容。dom
相似的用於動態更新語句的解決方案叫作 set。set 元素能夠被用於動態包含須要更新的列,而捨去其餘的。好比:ide
<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 關鍵字,同時也會消除無關的逗號,由於用了條件語句以後極可能就會在生成的賦值語句的後面留下這些逗號。spa
若你對等價的自定義 trim 元素的樣子感興趣,那這就應該是它的真面目:code
<trim prefix="SET" suffixOverrides=","> ... </trim>
注意這裏咱們忽略的是後綴中的值,而又一次附加了前綴中的值。對象
動態 SQL 的另一個經常使用的必要操做是須要對一個集合進行遍歷,一般是在構建 IN 條件語句的時候。好比:blog
<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 元素的功能是很是強大的,它容許你指定一個集合,聲明能夠用在元素體內的集合項和索引變量。它也容許你指定開閉匹配的字符串以及在迭代中間放置分隔符。這個元素是很智能的,所以它不會偶然地附加多餘的分隔符。
注意 你能夠將任何可迭代對象(如列表、集合等)和任何的字典或者數組對象傳遞給foreach做爲集合參數。當使用可迭代對象或者數組時,index是當前迭代的次數,item的值是本次迭代獲取的元素。當使用字典(或者Map.Entry對象的集合)時,index是鍵,item是值。
bind 元素能夠從 OGNL 表達式中建立一個變量並將其綁定到上下文。好比:
<select id="selectBlogsLike" resultType="Blog"> <bind name="pattern" value="'%' + _parameter.getTitle() + '%'" /> SELECT * FROM BLOG WHERE title LIKE #{pattern} </select>
一個配置了「_databaseId」變量的 databaseIdProvider 對於動態代碼來講是可用的,這樣就能夠根據不一樣的數據庫廠商構建特定的語句。好比下面的例子:
<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>
MyBatis 從 3.2 開始支持可插拔的腳本語言,所以你能夠在插入一種語言的驅動(language driver)以後來寫基於這種語言的動態 SQL 查詢。
能夠經過實現下面接口的方式來插入一種語言:
public interface LanguageDriver { ParameterHandler createParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql); SqlSource createSqlSource(Configuration configuration, XNode script, Class<?> parameterType); SqlSource createSqlSource(Configuration configuration, String script, Class<?> parameterType); }