1. 程式人生 > 其它 >演示預設學習使用者scott,預設密碼是tiger

演示預設學習使用者scott,預設密碼是tiger

1.動態SQL

  • 【官方宣告】

    動態 SQL 是 MyBatis 的強大特性之一。如果你使用過 JDBC 或其它類似的框架,你應該能理解根據不同條件拼接 SQL 語句有多痛苦,例如拼接時要確保不能忘記新增必要的空格,還要注意去掉列表最後一個列名的逗號。利用動態 SQL,可以徹底擺脫這種痛苦。

    使用動態 SQL 並非一件易事,但藉助可用於任何 SQL 對映語句中的強大的動態 SQL 語言,MyBatis 顯著地提升了這一特性的易用性。

    如果你之前用過 JSTL 或任何基於類 XML 語言的文字處理器,你對動態 SQL 元素可能會感覺似曾相識。在 MyBatis 之前的版本中,需要花時間瞭解大量的元素。藉助功能強大的基於 OGNL 的表示式,MyBatis 3 替換了之前的大部分元素,大大精簡了元素種類,現在要學習的元素種類比原來的一半還要少。

1.1 IF關鍵字

1.1.1 動態SQL測試

  1. dao層 介面 => 【BlogsMapper】

    import java.util.List;
    import java.util.Map;
    
    public interface BlogsMapper {
    	// 建立【插入測試資料】的方法
        int addBlog(Blogs blog);
    
        // 建立【實現動態SQL查詢】的方法
        List<Blogs> getBlogsByDynamicSQL(Map<String,String> map);
    }
    
  2. XML對映檔案 => 【BlogsMapper.xml】

    <select id="getBlogsByDynamicSQL">
        <!-- 注意: where 1 = 1 儘量不使用 -->
    	select * from test.blog where 1 = 1
        <!-- <if>標籤: 當向資料庫傳送的請求中,【title】欄位不為空時,則新增【title】欄位的查詢過濾條件 -->
        <if test="title != null">
            and title = #{title}
        </if>
        <!-- <if>標籤: 當向資料庫傳送的請求中,【author】欄位不為空時,新增【author】欄位的查詢過濾條件 -->
        <if test="author != null">
            and author = #{author}
        </if>
    </select>
    
  3. 測試實現類 => 【DaoTest】

    @Test
    public void getBlogsByDynamicSQL(){
        
        MyBatisUtils mybatis = new MyBatisUtils();
        SqlSession sqlSession = mybatis.getSqlSession();
        BlogsMapper mapper = sqlSession.getMapper(BlogsMapper.class);
        
        List<Blogs> blogs = mapper.getBlogsByDynaticSQL();
        for (Blogs blog : blogs){
            System.out.print(blog);
        }
        
        sqlSession.close();
    }
    

1.2 where、set

  • 【官方例項】

    • 失敗案例

      • 前面幾個例子已經合宜地解決了一個臭名昭著的動態 SQL 問題。現在回到之前的 “if” 示例,這次我們將 “state = ‘ACTIVE’” 設定成動態條件,看看會發生什麼。

        <select id="findActiveBlogLike"
             resultType="Blog">
          SELECT * FROM BLOG
          WHERE
          <if test="state != null">
            state = #{state}
          </if>
          <if test="title != null">
            AND title like #{title}
          </if>
          <if test="author != null and author.name != null">
            AND author_name like #{author.name}
          </if>
        </select>
        
      • 如果沒有匹配的條件會怎麼樣?最終這條 SQL 會變成這樣:

        SELECT * FROM BLOG
        WHERE
        
      • 這會導致查詢失敗。如果匹配的只是第二個條件又會怎樣?這條 SQL 會是這樣:

        SELECT * FROM BLOG
        WHERE
        AND title like ‘someTitle’
        
    • 成功案例

      • 這個查詢也會失敗。這個問題不能簡單地用條件元素來解決。這個問題是如此的難以解決,以至於解決過的人不會再想碰到這種問題。MyBatis 有一個簡單且適合大多數場景的解決辦法。而在其他場景中,可以對其進行自定義以符合需求。而這,只需要一處簡單的改動:

        <select id="findActiveBlogLike"
             resultType="Blog">
          SELECT * FROM BLOG
          <where>
            <if test="state != null">
                 state = #{state}
            </if>
            <if test="title != null">
                AND title like #{title}
            </if>
            <if test="author != null and author.name != null">
                AND author_name like #{author.name}
            </if>
          </where>
        </select>
        
  • 【官方宣告】

    • <where>標籤:

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

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

        //此案例實際上就是where這個標籤的工作原理,在拼接sql前方/開頭新增where,並去掉拼接語句整體最前方的and/or 單詞
        <trim prefix="WHERE" prefixOverrides="AND |OR ">
          <!-- 【prefixOverrides】屬性:忽略通過管道符分隔的文字序列(注意此例中的空格是必要的)。會移除所有 prefixOverrides 屬性中指定的內容,並且插入 prefix 屬性中指定的內容。-->
        </trim>
        
    • <set>標籤:

      • 用於動態更新語句的類似解決方案叫做 setset 元素可以用於動態包含需要更新的列,忽略其它不更新的列。

        <update id="updateAuthorIfNecessary">
          update Author
            <set>
              <if test="username != null">username=#{username},</if>
              <if test="password != null">password=#{password},</if>
              <if test="email != null">email=#{email},</if>
              <if test="bio != null" >bio=#{bio}</if>
            </set>
          where id=#{id}
        </update>
        

1.2.1 測試

  1. Dao層介面新增實現方法 => 【BlogsMapper】

    int updateBlogInfoBySet(Map map);
    
  2. XML對映檔案 => 【BlogsMapper.xml】

    <update id="updateBlogInfoBySet" parameterType="blogs">
        update test.blog 
        <set>
        	<if test="title != null"> title = #{title}</if>
            <if test="author != null"> author = #{author}</if>
            <if test="create_time != null"> create_time = #{createTime}</if>
            <if test="views != null"> views = #{views></if>
        </set>
    </update>
    
  3. 測試實現類 => 【DaoTest】

    @Test
    public void dynamicSqlUpdateBySet(){
        MyBatisUtils myBatisUtils = new MyBatisUtils();
        SqlSession sqlSession = myBatisUtils.getSqlSession();
        BlogsMapper mapper = sqlSession.getMapper(BlogsMapper.class);
    
        HashMap<String,String> map = new HashMap<String, String>();
        map.put("title","updatedTitle");
        map.put("author","updatedAuthor");
        map.put("createTime", String.valueOf(new Date()));
        map.put("views","1");
        map.put("id","5bde3e48b521443bb40524988456a668");
    
        int i = mapper.updateBlogInfoBySet(map);
        if (i > 0 ){
            System.out.println("Update Succeed!");
        }
        sqlSession.close();
    }
    

14.3 choose、when、otherwise

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

    • 例子

      <select id="findActiveBlogLike"
           resultType="Blog">
        SELECT * FROM BLOG WHERE state = ‘ACTIVE’
        <choose>
          <when test="title != null">
            AND title like #{title}
          </when>
          <when test="author != null and author.name != null">
            AND author_name like #{author.name}
          </when>
          <otherwise>
            AND featured = 1
          </otherwise>
        </choose>
      </select>
      

1.3.1 測試

1.3.1.1 環境搭建

  1. dao層介面新增方法 => 【BlogsMapper】

    List<Blogs> queryBlogsByChoose(Map map);
    
  2. xml對映檔案 => 【BlogsMapper.xml】

    //choose標籤類似於Java中的switch
    <select id="queryBlogsByChoose" resultType="blogs" parameterType="map">
        select * from test.blog
        <!-- <choose>標籤: 選擇性返回
             |-   <when>標籤: 當其內部條件成立時返回
             |-   <otherwise>標籤: 當所有條件都不滿足時執行
    	-->
     <sql id="allchoose">
         <where>
             <choose>
                 <when test="title!=null">
                     title=#{title}
                 </when>
                 <when test="author!=null">
                     and author=#{author}
                 </when>
                 <otherwise>
                     and views=5000
                 </otherwise>
             </choose>
         </where>
     </sql>
     
     <select id="queryBlogChoose" parameterType="map" resultType="blog">
         select * from mybatis.blog
         <include refid="allchoose"></include>
     </select>
    
  3. 測試實現類 => 【DaoTest】 (按測試情況進行配置 )

14.3.1.2 測試結果

  • 單個條件成立

    • 測試實現類 => 【DaoTest】

      @Test
      public void dynamicSqlChoose(){
          MyBatisUtils myBatisUtils = new MyBatisUtils();
          SqlSession sqlSession = myBatisUtils.getSqlSession();
          BlogsMapper mapper = sqlSession.getMapper(BlogsMapper.class);
      
          HashMap<String,String> map = new HashMap<String, String>();
          //建立單條件成立的集合
          map.put("title","MyBatis");
          System.out.println(mapper.queryBlogsByChoose(map));
      
          sqlSession.close();
      }
      
  • 多個條件成立

    • 測試實現類 => 【DaoTest】

      @Test
          public void dynamicSqlChoose(){
              MyBatisUtils myBatisUtils = new MyBatisUtils();
              SqlSession sqlSession = myBatisUtils.getSqlSession();
              BlogsMapper mapper = sqlSession.getMapper(BlogsMapper.class);
      
              HashMap<String,String> map = new HashMap<String, String>();
              //建立多個條件滿足的集合
              map.put("title","MyBatis");
            	map.put("author","Camelot");
              System.out.println(mapper.queryBlogsByChoose(map));
      
              sqlSession.close();
          }
      
  • <when>都為false,<otherwise>為true

    • 測試實現類 => 【DaoTest】

      @Test
      public void dynamicSqlChoose(){
          MyBatisUtils myBatisUtils = new MyBatisUtils();
          SqlSession sqlSession = myBatisUtils.getSqlSession();
          BlogsMapper mapper = sqlSession.getMapper(BlogsMapper.class);
      
          //建立空集合傳入
          HashMap<String,String> map = new HashMap<String, String>();
          System.out.println(mapper.queryBlogsByChoose(map));
      
          sqlSession.close();
      }
      
  • 結論

    <choose>標籤會在多個條件都滿足的情況下,僅會返回第一個傳參的返回值。

    但當其他條件都不滿足時,可以新增<otherwise>標籤,用於返回一個固有值。

14.4 Trim

  • Trim可以自定義SQL語句中的規範,當<where>標籤、<set>標籤不滿足時,可以使用Trim自定義。

14.4.1 Trim自定義測試

  • 使用Trim複寫<where>、<set>規則

14.4.1.1 <trim>實現<where>

  1. Dao層介面 => 【BlogsMapper】

    List<Blogs> queryBlogsByTrim(Map<String,String> map)
    
  2. XML對映器 => 【BlogsMapper.xml】

    <select id="queryBlogsByTrim" parameterType="blogs">
    	select * from test.blog
        <trim prefix="WHERE" prefixOverride="AND |OR ">//prefix去字首
            <if test="titleMap != null"> AND title = #{titleMap}</if>
            <if test="authorMap != null"> OR author = #{authorMap}</if>
        </trim>
    </select>
    
  3. 測試實現類 => 【DaoTest】

    @Test
    public void dynamicSqlSelectByTrim(){
        MyBatisUtils mybatis = new MyBatisUtils;
        SqlSession sqlSession = mybatis.getSqlSession();
        BlogsMapper mapper = sqlSession.getMapper(BlogsMapper.class);
    
        HashMap<String,String> map = new HashMap<String,String>();
        map.put("titleMap","MyBatis");
        map.put("authorMap","Altria");
    
        for (Blogs blog : mapper.queryBlogsByTrim(map)) {
            System.out.println(blog);
        }
    	
        sqlSession.close();
    }
    

1.4.1.2 <trim>實現<set>

  1. Dao層介面 => 【BlogsMapper】

    int updateBlogInfoByTrim(Map<String,String> map)
    
  2. XML對映檔案 => 【BlogsMapper.xml】

    <update id="updateBlogInfoByTrim" parameterType="map">
    	update test.blog
        <trim prefix="SET" suffixOverride=",">//suffix去後綴
            <if test="titleMap != null"> title = #{titleMap},</if>
            <if test="authorMap != null"> author = #{authorMap},</if>
        </trim>
        where id = #{idMap}
    </update>
    
  3. 測試實現類 => 【DaoTest】

    @Test
    public void dynamicSqlUpdateByTrim(){
        
        MyBatisUtils mybatis = new MyBatisUtils();
        SqlSession sqlSession = mybatis.getSqlSession();
        BlogsMapper mapper = mybatis.getMapper(BlogsMapper.class);
        
        Map<String,String> map = new HashMap<String,String>();
        map.put("authorMap","Altria");
        map.put("titleMap","Spring Framework Updated");
        map.put("idMap","5aa45402bc764755b3ae406be6b27d33");
        
        int i = mapper.updateBlogInfoByTrim(map);
        if( i > 0 ){
            System.out.println("Update Succeed!");
        }
    }