1. 動態SQL
1.1 介紹
-
概念:**動態SQL指的是根據不同的查詢條件 , 生成不同的Sql語句.*
官網描述:
MyBatis 的強大特性之一便是它的動態 SQL。如果你有使用 JDBC 或其它類似框架的經驗,你就能體會到根據不同條件拼接 SQL 語句的痛苦。例如拼接時要確保不能忘記新增必要的空格,還要注意去掉列表最後一個列名的逗號。利用動態 SQL 這一特性可以徹底擺脫這種痛苦。
雖然在以前使用動態 SQL 並非一件易事,但正是 MyBatis 提供了可以被用在任意 SQL 對映語句中的強大的動態 SQL 語言得以改進這種情形。
動態 SQL 元素和 JSTL 或基於類似 XML 的文字處理器相似。在 MyBatis 之前的版本中,有很多元素需要花時間瞭解。MyBatis 3 大大精簡了元素種類,現在只需學習原來一半的元素便可。MyBatis 採用功能強大的基於 OGNL 的表示式來淘汰其它大部分元素。
- if - choose (when, otherwise) - trim (where, set) - foreach -------------------------------
1.2 搭建環境
-
新建一個表:blog
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;
-
外掛IDUtil工具類
public class IDUtil { public static String genId(){ return UUID.randomUUID().toString().replaceAll("-",""); } }
-
編寫實體類
public class Blog { private String id; private String title; private String author; private Date createTime; private int views; // 無參構造 // 有參構造 // get、set、toString }
-
編寫Mapper介面及mapper配置檔案
public interface BlogMapper { int addBlog(Blog blog); }
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="top.linzeliang.mapper.BlogMapper"> <insert id="addBlog" parameterType="blog"> insert into blog (id, title, author, create_time, views) values (#{id},#{title},#{author},#{createTime},#{views}); </insert> </mapper>
-
在MyBatis配置檔案中設定下駝峰線自動轉換
<settings> <setting name="mapUnderscoreToCamelCase" value="true"/> <setting name="logImpl" value="STDOUT_LOGGING"/> </settings> <!--註冊Mapper.xml--> <mappers> <mapper resource="top/linzeliang/mapper/BlogMapper.xml"/> </mappers>
-
初始化部落格方法
@Test public void addInitBlog(){ SqlSession session = MybatisUtils.getSession(); BlogMapper mapper = session.getMapper(BlogMapper.class); Blog blog = new Blog(); blog.setId(IDUtil.genId()); blog.setTitle("Mybatis如此簡單"); blog.setAuthor("妙啊"); blog.setCreateTime(new Date()); blog.setViews(9999); mapper.addBlog(blog); blog.setId(IDUtil.genId()); blog.setTitle("Java如此簡單"); mapper.addBlog(blog); blog.setId(IDUtil.genId()); blog.setTitle("Spring如此簡單"); mapper.addBlog(blog); blog.setId(IDUtil.genId()); blog.setTitle("微服務如此簡單"); mapper.addBlog(blog); session.close(); }
2. IF和WHERE語句
if
語句就是判斷是否滿足某個條件,滿足的話就新增標籤內容到sql語句中where
語句:如果包含的標籤中含有返回值得話,他就會自動插入一個where,如果返回值的內容的第一個開頭是and
或者or
,則會自動剔除
需求:根據作者名字和部落格名字來查詢博,如果作者名字為空,那麼只根據部落格名字查詢,反之,則根據作者名來查詢
-
編寫介面類
List<Blog> queryBlogIf(Map map);
-
編寫對應的mapper配置檔案
- 傳入的引數是map,那麼在if標籤中直接寫的是map中的key,不用加
#{}
<select id="queryBlogIf" resultType="blog" parameterType="map"> select * from blog <where> <if test="title != null"> and title = #{title} </if> <if test="author != null"> and author = #{author} </if> </where> </select>
- 傳入的引數是map,那麼在if標籤中直接寫的是map中的key,不用加
3. SET語句
- 如果在進行更新操作的時候,含有 set 關鍵詞,則使用set標籤,效果和
where
也是一樣的
-
編寫介面方法
int updateBlog(Map map);
-
編寫對應的mapper配置檔案
<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>
4. CHOOSE語句
- 有時候,我們不想用到所有的查詢條件,只想選擇其中的一個,查詢條件有一個滿足即可,使用 choose 標籤可以解決此類問題,類似於 Java 的 switch 語句
-
編寫介面方法
List<Blog> queryBlogChoose(Map map);
-
編寫對應的mapper配置檔案
<select id="selectBlogChoose" resultType="blog" parameterType="map"> select * from blog <where> <choose> <when test="title != null"> title = #{title} </when> <when test="author != null"> and author = #{author} </when> <otherwise> adn views = #{views} </otherwise> </choose> </where> </select>
5. SQL片段
-
有時候可能某個 sql 語句我們用的特別多,為了增加程式碼的重用性,簡化程式碼,我們需要將這些程式碼抽取出來,然後使用時直接呼叫
-
提取SQL片段:
<sql id="if-title-author"> <if test="title != null"> title = #{title} </if> <if test="author != null"> and author = #{author} </if> </sql>
-
引用SQL片段:
<select id="queryBlogIf" parameterType="map" resultType="blog"> select * from blog <where> <!-- 引用 sql 片段,如果refid 指定的不在本檔案中,那麼需要在前面加上 namespace --> <include refid="if-title-author"></include> <!-- 在這裡還可以引用其他的 sql 片段 --> </where> </select>
-
最好基於 單表來定義 sql 片段,提高片段的可重用性
-
在 sql 片段中不要包括
where
6. ForEach
需求:我們需要查詢 blog 表中 id 分別為1,2,3的部落格資訊
-
編寫介面
List<Blog> queryBlogForeach(Map map);
-
編寫對應的mapper配置檔案
<select id="queryBlogForeach" parameterType="map" resultType="blog"> select * from blog <where> <!-- collection:指定輸入物件中的集合屬性 item:每次遍歷生成的物件 open:開始遍歷時的拼接字串 close:結束時拼接的字串 separator:遍歷物件之間需要拼接的字串 select * from blog where 1=1 and (id=1 or id=2 or id=3) --> <foreach collection="ids" item="id" open="and (" close=")" separator="or"> id = #{id} </foreach> </where> </select>
-
總結:其實動態
sql
語句的編寫往往就是一個拼接的問題,為了保證拼接準確,我們最好首先要寫原生的sql
語句出來,然後在通過mybatis
動態sql
對照著改,防止出錯