# Mybatis使用之動態SQL語句
### 一:簡介
?????? Mybatis動態SQL語句可幫助我們根據需要動態拼接SQL語句。主要在配置文件中使用<where> <if><choose><when><otherwise> <set> <trim><foreach>標簽來實現。
### 二:具體使用方式
### ???????2.1 where
?????????????2.1.1 功能
?????????????語句的作用主要是簡化SQL語句中where中的條件判斷,where元素的作用是會在寫入where元素的地方輸出一個where,另外一個好處是你不需要考慮where元素里面的條件輸出是什么樣子 的,MyBatis會智能的幫你處理,如果所有的條件都不滿足那么MyBatis就會查出所有的記錄,如果輸出后是and開頭的,MyBatis會把第一個and忽略,當然如果是or開頭的,MyBatis也會把它忽略;此外,在where元素中你不需要考慮空格的問 題,MyBatis會智能的幫你加上。
?????????????2.1.2 映射文件配置:
~~~
<select id="getBlogByConditionDynamic" resultMap="oneToManyNested">
select t1.id blog_id, t1.title, t2.id post_id, t2.section
from blog t1 left outer join post t2 on t1.id = t2.blog_id
<where>
<if test="title != null and title !=''">
and t1.title like '%'||#{title}||'%'
</if>
<if test="section != null and section != ''">
and t2.section like '%'||#{section}||'%'
</if>
</where>
</select>
~~~
?????????????2.1.3 映射接口方法:
~~~
List<Blog> getBlogByConditionDynamic(@Param("title") String title, @Param("section") String section);
~~~
?????????????2.1.4 測試方法:
~~~
@Test
public void testGetBlogByConditionDynamic() throws Exception {
List<Blog> blogList = blogMapper.getBlogByConditionDynamic("", "section");
Assert.assertNotNull(blogList);
}
~~~
### ???????3.1 if
?????????????3.1.1 功能
?????????????簡單的條件判斷,利用if語句我們可以實現某些簡單的條件選擇。判斷為則拼接、否則忽略。
?????????????3.1.2 映射文件配置:
~~~
<select id="getBlogDynamic" resultMap="oneToManyNested">
select t1.id blog_id, t1.title, t2.id post_id, t2.section
from blog t1 left outer join post t2 on t1.id = t2.blog_id where 1=1
<if test="title != null and title !=''">
and t1.title like '%'||#{title}||'%'
</if>
<if test="section != null and section != ''">
and t2.section like '%'||#{section}||'%'
</if>
</select>
~~~
?????????????3.1.3 映射接口方法:
~~~
List<Blog> getBlogDynamic(@Param("title") String title, @Param("section") String section);
~~~
?????????????3.1.4 測試方法:
~~~
public class BlogMapperTest {
private BlogMapper blogMapper;
public BlogMapperTest() {
blogMapper = MybatisUtil.getSqlSession().getMapper(BlogMapper.class);
}
@Test
public void testGetBlogDynamic() throws Exception {
List<Blog> blogList = blogMapper.getBlogDynamic("title", "section");
Assert.assertNotNull(blogList);
}
~~~
?????????????
????????????
### ?????? 4.1 choose
?????? 4.1.1 功能
?????????????**choose**元素的作用就相當于JAVA中的switch語句,基本上跟JSTL中的choose的作用和用法是一樣的,通常都是與when和otherwise搭配的。when元素表示當when中的條件滿足的時候就輸出其中的內容,跟JAVA中的switch效果差不多的是按照條件的順序,當when中有條件滿足的時 候,就會跳出choose,即所有的when和otherwise條件中,只有一個會輸出,當所有的我很條件都不滿足的時候就輸出otherwise中的 內容。
?????????????4.1.2 映射文件配置:
~~~
<select id="getBlogByTitleOrSection" resultMap="oneToManyNested">
select t1.id blog_id, t1.title, t2.id post_id, t2.section
from blog t1 left outer join post t2 on t1.id = t2.blog_id where 1=1
<choose>
<when test="title != null and title !=''">
and t1.title like '%'||#{title}||'%'
</when>
<when test="section != null and section != ''">
and t2.section like '%'||#{section}||'%'
</when>
<otherwise>
and t1.title is not null and t2.section is not null
</otherwise>
</choose>
</select>
~~~
?????????????4.1.3 映射接口方法:
~~~
List<Blog> getBlogByTitleOrSection(@Param("title") String title, @Param("section") String section);
~~~
?????????????4.1.4 測試方法:
~~~
@Test
public void testGetBlogByTitleOrSection() throws Exception {
List<Blog> blogList = blogMapper.getBlogByTitleOrSection("", "");
Assert.assertNotNull(blogList);
}
~~~
### ??????????????5.1 set
????????????????????5.1.1 功能
????????????????????set元素主要是用在更新操作的時候,它的主要功能和where元素其實是差不多的,主要是在包含的語句前輸出一個set,然后如果包含的語句是以逗號結束的話將會把該逗號忽略,如果set包含的內容為空的話則會出錯。有了set元素我們就可以動態的更新那些修改了的字段。
????????????????????5.1.2 映射文件配置:
~~~
<update id="updateBlogTitleSet" parameterType="blog">
update blog
<set>
<if test="title != null and title != ''">
title = #{title}
</if>
<if test="id != null and id != ''">
, id = #{id}
</if>
</set>
where id = #{id}
</update>
~~~
????????????????????5.1.3 映射接口方法:
~~~
int updateBlogTitleSet(Blog blog);
~~~
????????????????????5.1.4 測試方法:
~~~
@Test
public void testUpdateBlogTitleSet() throws Exception {
Blog blog = new Blog(1, "");
int flag = this.blogMapper.updateBlogTitleSet(blog);
Assert.assertEquals(true, flag > 0);
}
~~~
### ???????6.1 trim
????????????????????6.1.1 功能
????????????????????trim元素的主要功能是可以在自己包含的內容前加上某些前綴,也可以在其后加上某些后綴,與之對應的屬性是 prefix和suffix;可以把包含內容的首部某些內容覆蓋,即忽略,也可以把尾部的某些內容覆蓋,對應的屬性是prefixOverrides和 suffixOverrides;正因為trim有這樣的功能,所以我們也可以非常簡單的利用trim來代替where元素的功能
????????????????????6.1.2 映射文件配置:
~~~
<select id="getBlogByConditionDynamicTrim" resultMap="oneToManyNested">
select t1.id blog_id, t1.title, t2.id post_id, t2.section
from blog t1 left outer join post t2 on t1.id = t2.blog_id
<trim prefix="where" prefixOverrides="and | or">
<if test="title != null and title !=''">
and t1.title like '%'||#{title}||'%'
</if>
<if test="section != null and section != ''">
and t2.section like '%'||#{section}||'%'
</if>
</trim>
</select>
~~~
????????????????????6.1.3 映射接口方法:
~~~
List<Blog> getBlogByConditionDynamicTrim(@Param("title") String title, @Param("section") String section);
~~~
????????????????????6.1.4 測試方法:
~~~
@Test
public void testGetBlogByConditionDynamicTrim() throws Exception {
List<Blog> blogList = blogMapper.getBlogByConditionDynamicTrim("title", "section");
Assert.assertNotNull(blogList);
}
~~~
### ???????7.1 foreach
?????????????7.1.1 功能
**foreach**的主要用在構建in條件中,它可以在SQL語句中進行迭代一個集合。foreach元素的屬性主要有item,index,collection,open,separator,close。item表示集合中每一個元素進行迭代時的別名,index指 定一個名字,用于表示在迭代過程中,每次迭代到的位置,open表示該語句以什么開始,separator表示在每次進行迭代之間以什么符號作為分隔 符,close表示以什么結束,在使用foreach的時候最關鍵的也是最容易出錯的就是collection屬性,該屬性是必須指定的,但是在不同情況 下,該屬性的值是不一樣的,主要有一下3種情況:
如果傳入的是單參數且參數類型是一個List的時候,collection屬性值為list
如果傳入的是單參數且參數類型是一個array數組的時候,collection的屬性值為array
如果傳入的參數是多個的時候,我們就需要把它們封裝成一個Map了,**當然單參數也可以封裝成map**,實際上如果你在傳入參數的時候,在MyBatis里面也是會把它封裝成一個Map的,map的key就是參數名,所以這個時候collection屬性值就是傳入的List或array對象在自己封裝的map里面的key
以Array為例:
?????????????7.1.2 映射文件配置:
~~~
<select id="dynamicForeach2Test" resultType="Blog">
select * from t_blog where id in
<foreach collection="array" index="index" item="item" open="(" separator="," close=")">
#{item}
</foreach>
</select>
~~~
?????????????7.1.3 映射接口方法:
~~~
public List<Blog> dynamicForeach2Test(int[] ids);
~~~
?????????????7.1.4 測試方法:
~~~
@Test
public void dynamicForeach2Test() {
SqlSession session = MybatisUtil.getSqlSessionFactory().openSession();
BlogMapper blogMapper = session.getMapper(BlogMapper.class);
int[] ids = new int[] {1,3,6,9};
List<Blog> blogs = blogMapper.dynamicForeach2Test(ids);
}
~~~
### 三:補充
? ? ? 更多內容:[Mybatis 目錄](http://blog.csdn.net/crave_shy/article/details/45825599)
?????? github地址:https://github.com/andyChenHuaYing/scattered-items/tree/master/items-mybatis
?????? 源碼下載地址:http://download.csdn.net/detail/chenghuaying/8713311