動態SQL(IF、where、SQL片段、foreach等)、快取
阿新 • • 發佈:2021-10-26
什麼是動態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;
建立一個基礎工程
-
導包
-
編寫配置檔案
-
編寫實體類
-
編寫實體類對應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片段
有的時候,我們可能會將一些功能的部分抽取出來,方便複用!
-
使用SQL標籤抽取公共的部分
<sql id="id-title-author">
<if test="title!=null">
and title = #{title}
</if>
<if test="author != null">
and author like #{author}
</if>
</sql> -
在需要使用的地方使用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
-
與資料庫同一次會話期間查詢的資料會放在本地快取中。
-
以後如果需要獲取相同的資料,直接從快取中拿,沒必要再去查詢資料庫;
-
測試步驟:
-
開啟日誌
-
測試在一個Session中查詢兩次相同記錄
-
查詢日誌輸出
快取失效的情況:
-
查詢不同的東西
-
增刪改操作,可能會改變原來的資料,所以必定會重新整理快取!
-
查詢不同的Mapper.xml
-
手動清理快取
小結:一級快取預設是開啟的,只在一次SqlSession中有效,也就是拿到連線到關閉連線這個區間段!
一級快取相當於一個Map。
13.4、二級快取
-
在要使用二級快取的Mapper中開啟
<!-- 在當前Mapper.xml中使用二級快取-->
<cache/>也可以自定義引數
<cache
eviction="FIFO"
flushInterval="60000"
size="512"
readOnly="true"/> -
測試
-
問題:我們需要將實體類序列化,否則就會報錯!
Caused by: java.io.NotSerializableException: com.kuang.pojo.User
小結:
-
只要開啟了二級快取,在同一個Mapper下就有效
-
所有的資料都會先放在一級快取中
-
-
13.5、快取原理
13.6、自定義快取