一、MyBatis中的動態SQL
什麼是動態SQL:動態SQL就是根據不同的參數及條件生成不同的SQL語句
MyBatis中動態SQL元素
- if
- choose(when,otherwise)
- trim(where,set)
- foreach
- sql片段
1、創建基本環境
-
創建數據庫表blog
CREATE TABLE `blog` ( `id` varchar(50) NOT NULL COMMENT '博客id', `title` varchar(100) NOT NULL COMMENT '博客標題', `author` varchar(30) NOT NULL COMMENT '博客作者', `create_time` datetime NOT NULL COMMENT '創建時間', `views` int(30) NOT NULL COMMENT '瀏覽量' ) ENGINE=InnoDB DEFAULT CHARSET=utf8
-
創建實體類Blog
對應表blog的字段,創建Blog類
package org.westos.pojo; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.util.Date; @Data @AllArgsConstructor @NoArgsConstructor public class Blog { private String id; private String title; private String author; private Date createTime; private int views; }
-
創建對應的接口BlogMapper
package org.westos.mapper; import org.westos.pojo.Blog; import java.util.Map; public interface BlogMapper { //添加博客 public void addBlog(Blog blog); }
-
創建對應的xml配置文件BlogMapper.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="org.westos.mapper.BlogMapper"> <insert id="addBlog" parameterType="org.westos.pojo.Blog"> INSERT INTO `blog`(`id`,`title`,`author`,`create_time`,`views`) VALUES (#{id},#{title},#{author},#{createTime},#{views}) </insert> </mapper>
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-zWr0PEkL-1582304351170)(assets/1582271343949.png)]
-
開啓下劃線轉駝峯命名
因爲數據庫表中字段命名一般使用下劃線隔開單詞,而Java變量使用駝峯命名,所以在多單詞命名時,數據庫字段名就會和Java屬性名不一致,這個時候只需要在MyBatis核心配置文檔mybatis-config.xml中,配置一下就可以自動進行轉換了
<settings> <!--開啓下劃線轉駝峯命名--> <setting name="mapUnderscoreToCamelCase" value="true"/> </settings>
-
開啓日誌
開啓事務能夠在控制檯打印程序執行的詳細信息,幫助我們改錯
在下劃線轉駝峯命名的配置下方進行配置
<settings> <!--開啓下劃線轉駝峯命名--> <setting name="mapUnderscoreToCamelCase" value="true"/> <!--開啓日誌--> <setting name="logImpl" value="STDOUT_LOGGING"/> </settings>
-
使用unit測試工具進行測試
往表中添加博客記錄,以便後面進行觀察
package org.westos.mapper; import org.junit.Test; import org.westos.pojo.Blog; import org.westos.utils.IDUtils; import org.westos.utils.MyBatisUtil; import java.util.Date; public class BlogMapperTest { @Test public void testAddBlog() { //傳遞參數,默認開啓事務提交 BlogMapper mapper = MyBatisUtil.getSession(true).getMapper(BlogMapper.class); Blog blog; //循環給表中添加數據 for (int i = 0; i < 10; i++) { blog = new Blog(); blog.setId(IDUtils.getId()); blog.setTitle("文章" + i); blog.setAuthor("北風"); blog.setCreateTime(new Date()); blog.setViews(i * 1000); mapper.addBlog(blog); } } }
-
IDUtils工具類
工具類,創建隨機數,作爲文章的id
package org.westos.utils; import java.util.UUID; public class IDUtils { public static String getId() { return UUID.randomUUID().toString().replaceAll("-", ""); } }
2、if標籤
常用於where語句、update語句、insert語句中,通過判斷if後表達式的取值決定是否使用if標籤中的子句。
當判斷條件爲真的時候,添加if標籤中的子句,當判斷條件爲假的時候,什麼都不加
if是與的關係(and)
java代碼
//BlogMapper接口新增方法
//查詢博客
List<Blog> getBlogByIf(Map map);
//BlogMapperTest中新增測試方法
@Test
public void testGetBlogByIf() {
BlogMapper mapper = MyBatisUtil.getSession(true).getMapper(BlogMapper.class);
//創建Map集合,用的參數從Map集合中拿
Map<String, String> map = new HashMap<String, String>();
map.put("title","wenzhang1");
map.put("author","beifeng");
List<Blog> blogByIf = mapper.getBlogByIf(map);
for (Blog blog : blogByIf) {
System.out.println(blog);
}
}
xml配置
<!--根據if標籤後的表達式的值來決定SQL語句-->
<select id="getBlogByIf" parameterType="Map" resultType="Blog">
select * from mybatis.blog where
<!--通過判斷if後表達式的值,決定是否要添加if標籤中的子句-->
<if test="title!=null">
title=#{title}
</if>
<if test="author!=null">
and author =#{author}
</if>
</select>
3、choose標籤(when,otherwise)
類似於Java中的switch語句,當匹配到成立的when標籤後的條件時,就執行這個when標籤後的SQL子句,choose標籤結束。當所有的when標籤都不成立時,執行otherwise標籤中的SQL子句
choose是或的關係(or)
java代碼
//BlogMapper新增接口
List<Blog> queryBlogByChoose(Map map);
//測試類新增測試方法
@Test
public void testQueryBlogByChoose() {
BlogMapper mapper = MyBatisUtil.getSession().getMapper(BlogMapper.class);
Map<String, String> map = new HashMap<String, String>();
map.put("title", "wenzhang1");
map.put("author", "beifeng");
List<Blog> blogByIf = mapper.getBlogByIf(map);
for (Blog blog : blogByIf) {
System.out.println(blog);
}
}
xml配置
<!--使用choose標籤-->
<select id="queryBlogByChoose" parameterType="map" resultType="blog">
select * from mybatis.blog
<where>
<choose>
<when test="title != null">
and title = #{title}
</when>
<when test="author != null">
and author = #{author}
</when>
<otherwise>
and views = #{views}
</otherwise>
</choose>
</where>
</select>
4、trim標籤(where,set)
where:當where標籤中有返回值的話,它就插入一個where子句,如果沒有,如果標籤返回的內容是以 AND 或 OR 或 “,” 開頭結尾的,則它會刪除掉
java代碼
//接口
List<Blog> selectBlogByWhere(Map map);
//測試方法
@Test
public void testSelectBlogByWhere() {
BlogMapper mapper = MyBatisUtil.getSession().getMapper(BlogMapper.class);
Map<String, String> map = new HashMap<String, String>();
map.put("title", "wenzhang1");
map.put("author", "beifeng");
List<Blog> blogByIf = mapper.selectBlogByWhere(map);
for (Blog blog : blogByIf) {
System.out.println(blog);
}
}
xml配置
<select id="selectBlogByWhere" parameterType="map" resultType="blog">
select * from mybatis.blog
<where>
<if test="title != null">
title = #{title}
</if>
<if test="author != null">
and author = #{author}
</if>
</where>
</select>
set:當在 update 語句中使用 if 標籤時,如果最後的 if 沒有執行,則或導致逗號多餘錯誤。使用 set 標籤可以將動態的配置 set關鍵字,並刪除追加到條件末尾的任何不相關的逗號
java代碼
//接口
int updateBlogBySete(Map map);
//測試方法
@Test
public void testUpdateBlogBySete() {
//開啓事務提交
BlogMapper mapper = MyBatisUtil.getSession(true).getMapper(BlogMapper.class);
Map<String, String> map = new HashMap<String, String>();
//給Map中填充數據
map.put("title", "123123123");
map.put("author", "11111111");
map.put("id", "8bc79ab97f6f4887a2e61ae7d6512453");
//打印受影響行數
int i = mapper.updateBlogBySete(map);
System.out.println(i);
}
xml配置
<update id="updateBlogBySete" parameterType="map">
update mybatis.blog
<set>
<if test="title != null">
title = #{title},
</if>
<if test="author != null">
author = #{author}
</if>
</set>
where id = #{id}
</update>
5、foreach標籤
foreach主要用於構建in條件,也可在SQl中對集合進行迭代。批量增刪等操作
foreach標籤的屬性
-
collection
表明存儲的參數類型,對應的值分別爲:list(List)、array(數組)、map(map集合)
-
item
在迭代的過程中元素的別名
-
index
在迭代的過程中,迭代的位置
-
open
前括號
-
close
後括號
-
separator
分隔符,表示迭代的時候以什麼符號分隔元素
java代碼
//接口
List<Blog> getBlogByForeach(Map map);
//測試方法
@Test
public void testGetBlogByForeach() {
BlogMapper mapper = MyBatisUtil.getSession().getMapper(BlogMapper.class);
Map<String, List> map = new HashMap<String, List>();
List<String> ids = new ArrayList<String>();
ids.add("8bc79ab97f6f4887a2e61ae7d6512453");
ids.add("d38e8e24768249eb8c0a671e64e5991f");
ids.add("35e3643a0ab14b18b018b72146d1f0d4");
map.put("ids", ids);
List<Blog> blogByIf = mapper.getBlogByIf(map);
for (Blog blog : blogByIf) {
System.out.println(blog);
}
}
xml配置
<select id="getBlogByForeach" parameterType="map" resultType="blog">
select * from user where
<!--得到map集合裏的鍵值對,值爲List集合,然後遍歷得到值,使用or鏈接起來-->
<foreach item="id" collection="ids"
open="(" separator="or" close=")">
#{id}
</foreach>
</select>
6、SQL片段
將一些SQL語句公用的部分抽取出來,實現代碼復
-
使用SQL標籤抽取公共的部分
<sql id="if-title-author"> <if test="title != null"> title = #{title} </if> <if test="author != null"> and author = #{author} </if> </sql>
-
將前面的if標籤引用進來,使用include標籤
<select id="queryBlogIF" parameterType="map" resultType="blog"> select * from mybatis.blog <where> <include refid="if-title-author"></include> </where> </select>