1. 程式人生 > 其它 >動態SQL(IF、where、SQL片段、foreach等)、快取

動態SQL(IF、where、SQL片段、foreach等)、快取

12、動態SQL

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

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

- if
- choose (when, otherwise)
- trim (where, set)
- foreach

搭建環境

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;

建立一個基礎工程

  1. 導包

  2. 編寫配置檔案

  3. 編寫實體類

  4. 編寫實體類對應Mapper介面和Mapper.xml檔案

IF
 <select id="queryBlogIF" resultType="com.kuang.pojo.Blog" parameterType="map">
select * from mybatis.blog where 1=1
<if test="author != null">
and author=#{author}
</if>
<if test="views != null">
and views=#{views}
</if>
</select>
  public void queryBlogIF(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
HashMap map = new HashMap();
map.put("author","榮哥");
map.put("views","9999");
List<Blog> blogs = mapper.queryBlogIF(map);
for (Blog blog : blogs) {
System.out.println(blog);
}
sqlSession.close();
}

就能查出滿足author=榮哥,views=9999的記錄

choose、when、otherwise
  <select id="queryBlogChoose" parameterType="map" resultType="com.kuang.pojo.Blog">
select * from mybatis.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>
trim、where、set
     select * from mybatis.blog
//where 元素只會在子元素返回任何內容的情況下才插入 “WHERE” 子句,
//若子句的開頭為 “AND” 或 “OR”,where 元素也會將它們去除。
//如果沒有where標籤第一個and要去掉,不然報錯。
<where>
<if test="title!=null">
and title = #{title}
</if>
<if test="author != null">
and author like #{author}
</if>
<if test="views != null">
and views=#{views}
</if>
</where>
  //set 元素會動態地在行首插入 SET 關鍵字,並會刪掉額外的逗號(這些逗號是在使用條件語句給列賦值時引入的)。
<update id="updateBlog" 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>

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

SQL片段

有的時候,我們可能會將一些功能的部分抽取出來,方便複用!

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

      <sql id="id-title-author">
    <if test="title!=null">
    and title = #{title}
    </if>
    <if test="author != null">
    and author like #{author}
    </if>
    </sql>
  2. 在需要使用的地方使用include標籤引用即可

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

注意事項:

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

  • 不要存在where標籤

Foreach
select * from user where 1=1 and(id=1 or id=2 or id=3)

<foreach item="id" collection="ids"
open="(" separator="or" close=")">
#{id}
</foreach>
(id=1 or id=2 or id=3)

<!--select * from mybatis.blog where 1=1 and(id=1 or id=2 or id=3)

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

<where> //遍歷出來的集合為ids,對應的每一項就是一個ide(名字自己取)
<foreach collection="ids" item="ide" open="and (" separator="or" close=")">
id=#{ide}
</foreach>
</where>
</select>
  public void queryBlogForeach(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper mapper = 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 = mapper.queryBlogForeach(map);
for (Blog blog : blogs) {
System.out.println(blog);
}
sqlSession.close();
}
}

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

建議:

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

13、快取

13.1、簡介
查詢:  連線資料庫,耗資源!
一次查詢的結果,給他暫存一個可以直接取到的地方! --> 記憶體 :快取

我們再次查詢相同資料的時候,直接走快取,就不用走資料庫了

13.2、Mybatis快取

13.3、一級快取
  • 一級快取也叫本地快取(預設開啟):SqlSession

    • 與資料庫同一次會話期間查詢的資料會放在本地快取中。

    • 以後如果需要獲取相同的資料,直接從快取中拿,沒必要再去查詢資料庫;

測試步驟:

  1. 開啟日誌

  2. 測試在一個Session中查詢兩次相同記錄

  3. 查詢日誌輸出

快取失效的情況:

  1. 查詢不同的東西

  2. 增刪改操作,可能會改變原來的資料,所以必定會重新整理快取!

  3. 查詢不同的Mapper.xml

  4. 手動清理快取

小結:一級快取預設是開啟的,只在一次SqlSession中有效,也就是拿到連線到關閉連線這個區間段!

一級快取相當於一個Map。

13.4、二級快取

  1. 在要使用二級快取的Mapper中開啟

    <!--   在當前Mapper.xml中使用二級快取-->
    <cache/>

    也可以自定義引數

      <cache
    eviction="FIFO"
    flushInterval="60000"
    size="512"
    readOnly="true"/>

  2. 測試

    1. 問題:我們需要將實體類序列化,否則就會報錯!

      Caused by: java.io.NotSerializableException: com.kuang.pojo.User

    小結:

    • 只要開啟了二級快取,在同一個Mapper下就有效

    • 所有的資料都會先放在一級快取中

    • 只有當會話提交,或者關閉的時候,才會提交到二級快取中!

13.5、快取原理

13.6、自定義快取