1. 程式人生 > 其它 >Mybatis學習筆記--Mybatis動態SQL

Mybatis學習筆記--Mybatis動態SQL

技術標籤:Mybatis資料庫mybatissqlmysql

文章目錄

本文章涉及環境版本:

  • mysql 5.7
  • Mybatis 3.5.x
  • Maven 3.6.x
  • JDK 1.8

專案程式碼倉庫:
https://github.com/Gang-bb/Study-Record/tree/main/bzhan-mybatis-study
需要clone整個bzhan-mybatis-study專案
(整體是一個maven多module工程)

該文章對應:《bzhan-mybatis-study07 》module專案

1. 動態SQL

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

利用動態 SQL 這一特性可以徹底擺脫這種痛苦。

動態 SQL 元素和 JSTL 或基於類似 XML 的文字處理器相似。在 MyBatis 之前的版本中,有很多元素需要花時間瞭解。MyBatis 3 大大精簡了元素種類,現在只需學習原來一半的元素便可。MyBatis 採用功能強大的基於 OGNL 的表示式來淘汰其它大部分元素。

2. 搭建環境

  1. 建表
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

準備一些測試資料:

image-20210209133355820

  1. POJO類編寫
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Blog { private Integer id; private String title; private String author; private Date createTime; private Integer views; }
  1. 編寫dao層mapper介面和mapper.xml檔案

3. IF語句使用

  1. BlogMapper
List<Blog> getBlogsIf(Map map);
  1. BlogMapper.xml
<select id="getBlogsIf" resultType="com.gangbb.model.pojo.Blog">
    select * from blog where 1=1
    <if test="title != null">
        and title = #{title}
    </if>
    <if test="author != null">
        and author = #{author}
    </if>
</select>

或者:(涉及where標籤知識內容)
<select id="getBlogsIf" resultType="com.gangbb.model.pojo.Blog">
    select * from blog
    <where>
    	<if test="title != null">
        	title = #{title}
        </if>
        <if test="author != null">
            and author = #{author}
        </if>
    </where>
</select>
  1. 測試類
@Test
public void getBlogs(){
    SqlSession sqlSession = null;
    try {
        sqlSession = MybatisUtil.openSession();
        BlogMapper blogMapper = sqlSession.getMapper(BlogMapper.class);
        Map map = new HashMap();
        map.put("author", "Gangbb");
        List<Blog> blogList = blogMapper.getBlogsIf(map);
        for (int i = 0; i < blogList.size(); i++) {
            Blog blog =  blogList.get(i);
            System.out.println(blog);
        }
    } finally {
        sqlSession.close();
    }

}

4. choose (when, otherwise)語句使用

有時候,我們不想使用所有的條件,而只是想從多個條件中選擇一個使用。針對這種情況,MyBatis 提供了 choose 元素,它有點像 Java 中的 switch 語句。

  1. BlogMapper
List<Blog> getBlogsChoose(Map map);
  1. BlogMapper.xml
<select id="getBlogsChoose" parameterType="map" resultType="com.gangbb.model.pojo.Blog">
    select * from blog
    <where>
        <choose>
            <when test="title != null">
                title = #{title}
            </when>
            <when test="author != null">
                author = #{author}
            </when>
            <otherwise>
                views = 99999999
            </otherwise>
        </choose>
    </where>
</select>
  1. 測試類
@Test
public void BlogChoose(){
    SqlSession sqlSession = null;
    try {
        sqlSession = MybatisUtil.openSession();
        BlogMapper blogMapper = sqlSession.getMapper(BlogMapper.class);
        Map map = new HashMap();
        //下面兩個隨意填入條件測試
        //map.put("title", "學習如何找女朋友");
        //map.put("author", "Gangbb");
        List<Blog> blogList = blogMapper.getBlogsChoose(map);
        for (Blog blog : blogList) {
            System.out.println(blog);
        }
    } finally {
        sqlSession.close();
    }
}

5. trim (where,set)語句使用

where 元素只會在子元素返回任何內容的情況下才插入 “WHERE” 子句。而且,若子句的開頭為 “AND” 或 “OR”,where 元素也會將它們去除。

如果 where 元素與你期望的不太一樣,你也可以通過自定義 trim 元素來定製 where 元素的功能。比如,和 where 元素等價的自定義 trim 元素為:

<trim prefix="WHERE" prefixOverrides="AND |OR ">
  ...
</trim>

例項使用:

<update id="updateBlog" parameterType="map">
    update blog
    <set>
        <if test="title != null">
            title = #{title},
        </if>
        <if test="author != null">
            author = #{author}
        </if>
    </set>
    where id = #{id}
</update>

set 元素會動態地在行首插入 SET 關鍵字,並會刪掉額外的逗號(這些逗號是在使用條件語句給列賦值時引入的)。

等價於:

<trim prefix="SET" suffixOverrides=",">
  ...
</trim>

所謂的動態SQL,本質還是SQL語句 , 只是我們可以在SQL層面,去執行一個邏輯程式碼

6. 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. 在需要使用的地方使用Include標籤引用即可

    <select id="queryBlogIF" parameterType="map" resultType="blog">
        select * from mybatis.blog
        <where>
            <include refid="if-title-author"></include>
        </where>
    </select>
    

注意事項:

  • 最好基於單表來定義SQL片段!

  • 不要存在where標籤

7. Foreach語句

  1. BlogMapper
List<Blog> getBlogsChoose(Map map);
  1. BlogMapper.xml
<!--
        select * from mybatis.blog where 1=1 and (id=1 or id = 2 or id=3)

        我們現在傳遞一個萬能的map , 這map中可以存在一個集合!
-->
<select id="getBlogForeach" parameterType="map" resultType="blog">
    select * from blog

    <where>
        <foreach collection="ids" item="id" open="and (" close=")" separator="or">
            id = #{id}
        </foreach>
    </where>

</select>
  1. 測試類
@Test
public void BlogForeach(){
    SqlSession sqlSession = null;
    try {
        sqlSession = MybatisUtil.openSession();
        BlogMapper blogMapper = sqlSession.getMapper(BlogMapper.class);
        Map map = new HashMap();
        ArrayList<Integer> ids = new ArrayList<Integer>();
        ids.add(1);
        map.put("ids", ids);
        List<Blog> blogList = blogMapper.getBlogForeach(map);
        for (Blog blog : blogList) {
            System.out.println(blog);
        }
    } finally {
        sqlSession.close();
    }
}

動態SQL就是在拼接SQL語句,我們只要保證SQL的正確性,按照SQL的格式,去排列組合就可以了

建議:

  • 現在Mysql中寫出完整的SQL,再對應的去修改成為我們的動態SQL實現通用即可!