1. 程式人生 > 實用技巧 >Mybatis-09-動態Sql

Mybatis-09-動態Sql

  • 定義

    根據不同的條件生成不同的sql語句,本質還是sql語句,只是我們可以在sql層面執行邏輯程式碼

  • 環境搭建

    • blog表

      id
      title
      author
      creat_time
      views
    • 實體類:Blog

      @Data
      public class Blog {

      private String id;
      private String title;
      private String author;
      private Date creatTime;
      private int views;
      }
    • 配置檔案

      <configuration>

      <settings>
      <setting name="logImpl" value="STDOUT_LOGGING"/>
      <!--開啟駝峰命名-->
      <setting name="mapUnderscoreToCamelCase" value="true"/>
      </settings>

      <environments default="development">
      <environment id="development">
      <transactionManager type="JDBC"/>
      <dataSource type="POOLED">
      <property name="driver" value="com.mysql.jdbc.Driver"/>
      <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>
      <property name="username" value="root"/>
      <property name="password" value="root"/>
      </dataSource>
      </environment>
      </environments>

      <mappers>
      <mapper class="com.hmx.mapper.BlogMapper"/>
      </mappers>

      </configuration>
  • if

    • 這條語句提供了可選的查詢文字功能

    • 傳入哪個就按哪個查詢,如果不傳入,就按select裡的原始sql語句查詢

    • 測試

      • 介面類

        public interface BlogMapper {
        List<Blog> queryBlogIf(Map map);
        }
      • 介面類的實現類

        <mapper namespace="com.hmx.mapper.BlogMapper">

        <select id="queryBlogIf" parameterType="map" resultType="Blog">
        select * from blog
        <!--
        where 元素只會在子元素返回任何內容的情況下才插入 “WHERE” 子句
        而且,若子句的開頭為 “AND” 或 “OR”,where 元素也會將它們去除
        -->
        <where>
        <!--
        test裡面是判斷條件
        表示式為true,把if中的語句拼接到select中的sql上
        表示式為false,忽略此語句
        -->
        <if test="title != null">
        and title = #{title}
        </if>
        <if test="author !=null" >
        and author = #{author}
        </if>
        </where>
        </select>

        </mapper>
      • 測試實現

        public static void queryBlogIf() {

        SqlSession sqlSession = MybatisUtils.getSqlSession();

        BlogMapper blogMapper = sqlSession.getMapper(BlogMapper.class);
        HashMap map = new HashMap();
        //查詢title為"Mybatis如此簡單"的記錄
        map.put("title", "Mybatis如此簡單");

        //查詢author為"Andy"的記錄
        //map.put("author","Andy");

        List<Blog> blogs = blogMapper.queryBlogIf(map);
        for (Blog blog : blogs) {
        System.out.println(blog);
        }

        sqlSession.close();
        }
  • choose,when,otherwise

    • 從多個條件中選擇一個使用

    • 傳入了哪個就按哪個查詢,第一個when優先順序最高,都沒有傳入,就按otherwise裡的查詢

    • 測試

      • 介面類

        public interface BlogMapper {
        List<Blog> queryBlogChoose(Map map);
        }
      • 介面的實現類

        <mapper namespace="com.hmx.mapper.BlogMapper">

        <select id="queryBlogChoose" parameterType="map" resultType="Blog">
        select * from blog
        <where>
        <choose>
        <when test="title != null">
        title = #{title}
        </when>
        <when test="author !=null">
        and author = #{author}
        </when>
        <otherwise>
        and views = #{views}
        </otherwise>
        </choose>
        </where>
        </select>

        </mapper>
      • 測試實現

        public static void queryBlogChoose() {
        
            SqlSession sqlSession = MybatisUtils.getSqlSession();
        
            BlogMapper blogMapper = sqlSession.getMapper(BlogMapper.class);
            
            HashMap hashMap = new HashMap();
            hashMap.put("title", "Mybatis如此簡單");
            //hashMap.put("author","洪夢霞");
            //hashMap.put("views","888");
            
            List<Blog> blogs = blogMapper.queryBlogChoose(hashMap);
            for (Blog blog : blogs) {
                System.out.println(blog);
            }
        
            sqlSession.close();
        }
  • trim,where,set

    • where

      • where 元素只會在子元素返回任何內容的情況下才插入 “WHERE” 子句,

        而且,若子句的開頭為 “AND” 或 “OR”,where 元素也會將它們去除。

      • 加入trim定製where元素的功能

        <!--拼接sql語句時會加上WHERE,並且刪除多餘的AND和OR-->
        <trim prefix="WHERE" prefixOverrides="AND |OR ">
          ...
        </trim>
    • set

      • set 元素可以用於動態包含需要更新的列,忽略其它不更新的列,它會動態地在行首插入 SET 關鍵字,並會刪掉額外的逗號,在update語句中會用到

      • 加入trim定製set元素的功能

        <!--拼接sql語句時會加上SET,並且刪除多餘的","-->
        <trim prefix="SET" suffixOverrides=",">
          ...
        </trim>
  • foreach

    • 對集合進行遍歷(尤其是在構建 IN 條件語句的時候)

    • 測試:select * from blog where 1 = 1 and (id = 1 or id = 2 or id = 3)

      • 介面類

        public interface BlogMapper {
            List<Blog> queryBlogForEach(Map map);
        }
      • 介面的實現類

        <mapper namespace="com.hmx.mapper.BlogMapper">
            
            <select id="queryBlogForEach" parameterType="map" resultType="Blog">
                select * from blog
                <where>
                    <!--
                        從collection這個集合中遍歷,是map中存在的集合
                        遍歷出的每一項叫做item中的值
                        index為下標
                        開始為open裡的值
                        結束為close裡的值
                        separator為分隔符
                    -->
                    <foreach collection="ids" item="id" open="and (" close=")" separator="or">
                        id = #{id}
                    </foreach>
                </where>
            </select>
        
        </mapper>
      • 測試

        public static void queryBlogForEach() {

        SqlSession sqlSession = MybatisUtils.getSqlSession();

        BlogMapper blogMapper = sqlSession.getMapper(BlogMapper.class);
        HashMap map = new HashMap();

        ArrayList<Integer> ids = new ArrayList<Integer>();
        ids.add(1);
        ids.add(2);
        ids.add(3);
        map.put("ids", ids);

        List<Blog> blogs = blogMapper.queryBlogForEach(map);
        for (Blog blog : blogs) {
        System.out.println(blog);
        }

        sqlSession.close();
        }
  • sql片段

    • 將一些公共的功能抽取出來,方便複用

    • 注意:

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

      • 不要存在where標籤

    • 使用步驟

      • 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標籤引用

        <include refid="if-title-author"></include>