MyBatis中動態SQL IF、Choose、Trim、Foreach

一、MyBatis中的動態SQL

什麼是動態SQL:動態SQL就是根據不同的參數及條件生成不同的SQL語句

MyBatis中動態SQL元素

  1. if
  2. choose(when,otherwise)
  3. trim(where,set)
  4. foreach
  5. sql片段

1、創建基本環境

  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
    
  2. 創建實體類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;
    }
    
  3. 創建對應的接口BlogMapper

    package org.westos.mapper;
    
    import org.westos.pojo.Blog;
    import java.util.Map;
    
    public interface BlogMapper {
        //添加博客
        public void addBlog(Blog blog);
    }
    
  4. 創建對應的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)]

  5. 開啓下劃線轉駝峯命名

    因爲數據庫表中字段命名一般使用下劃線隔開單詞,而Java變量使用駝峯命名,所以在多單詞命名時,數據庫字段名就會和Java屬性名不一致,這個時候只需要在MyBatis核心配置文檔mybatis-config.xml中,配置一下就可以自動進行轉換了

    <settings>
        <!--開啓下劃線轉駝峯命名-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
    
  6. 開啓日誌

    開啓事務能夠在控制檯打印程序執行的詳細信息,幫助我們改錯

    在下劃線轉駝峯命名的配置下方進行配置

    <settings>
        <!--開啓下劃線轉駝峯命名-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
        <!--開啓日誌-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
    
  7. 使用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);
            }
        }
    }
    
  8. 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標籤的屬性

  1. collection

    表明存儲的參數類型,對應的值分別爲:list(List)、array(數組)、map(map集合)

  2. item

    在迭代的過程中元素的別名

  3. index

    在迭代的過程中,迭代的位置

  4. open

    前括號

  5. close

    後括號

  6. 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語句公用的部分抽取出來,實現代碼復

  1. 使用SQL標籤抽取公共的部分

    <sql id="if-title-author">
        <if test="title != null">
            title = #{title}
        </if>
        <if test="author != null">
            and author = #{author}
        </if>
    </sql>
    
  2. 將前面的if標籤引用進來,使用include標籤

    <select id="queryBlogIF" parameterType="map" resultType="blog">
        select * from mybatis.blog
        <where>
            <include refid="if-title-author"></include>
        </where>
    </select>
    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章