原文位址: http://www.work100.net/training/monolithic-frameworks-mybatis-sql.html 更多教程: 光束雲 - 免費課程
MyBatis 動态 SQL
序号 | 文内章節 | 視訊 |
---|---|---|
1 | 概述 | - |
2 | 注意事項 | |
3 | if标簽 | |
4 | where标簽 | |
5 | choose标簽 | |
6 | foreach标簽-周遊數組 | |
7 | foreach标簽-周遊集合 | |
8 | sql标簽 |
請參照如上
章節導航
進行閱讀
1.概述
動态 SQL,主要用于解決查詢條件不确定的情況:在程式運作期間,根據使用者送出的查詢條件進行查詢。
送出的查詢條件不同,執行的 SQL 語句不同。若将每種可能的情況均逐一列出,對所有條件進行排列組合,将會出現大量的 SQL 語句。
此時,可使用動态 SQL 來解決這樣的問題。
動态 SQL,即通過 MyBatis 提供的各種标簽對條件作出判斷以實作動态拼接 SQL 語句。
這裡的條件判斷使用的表達式為 OGNL 表達式。常用的動态 SQL 标簽有
<if>
、
<where>
<choose>
<foreach>
等。
2.注意事項
在 mapper 的動态 SQL 中若出現大于号(
>
)、小于号(
<
)、大于等于号(
>=
),小于等于号(
<=
)等符号,最好将其轉換為實體符号。
否則,XML 可能會出現解析出錯問題。
特别是對于小于号(
<
),在 XML 中是絕對不能出現的。否則,一定出錯。
原符号 | 替換符号 |
---|---|
| |
| |
| |
| |
| |
| |
| |
3.if标簽
對于該标簽的執行,當
test
的值為
true
時,會将其包含的 SQL 片斷拼接到其所在的 SQL 語句中。
本例實作的功能是:查詢出滿足使用者送出查詢條件的所有學生。使用者送出的查詢條件可以包含一個姓名的模糊查詢,同時還可以包含一個年齡的下限。當然,使用者在送出表單時可能兩個條件均做出了設定,也可能兩個條件均不做設定,也可以隻做其中一項設定。
這引發的問題是,查詢條件不确定,查詢條件依賴于使用者送出的内容。此時,就可使用動态 SQL 語句,根據使用者送出内容對将要執行的 SQL 進行拼接。
定義映射檔案
為了解決兩個條件均未做設定的情況,在
where
後添加了一個“
1=1
”的條件。
這樣就不至于兩個條件均未設定而出現隻剩下一個
where
,而沒有任何可拼接的條件的不完整 SQL 語句。
<?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="net.work100.training.stage2.mybatis.dao.DynamicStudentDao">
<!-- if -->
<select id="selectByIf" resultType="net.work100.training.stage2.mybatis.entity.Student">
SELECT
id,
name,
age,
score
FROM
student
WHERE 1 = 1
<if test="name != null and name != ''">
AND name LIKE concat('%', #{name}, '%')
</if>
<if test="age != null and age > 0">
AND age > #{age}
</if>
</select>
</mapper>
4.where标簽
<if/>
标簽的中存在一個比較麻煩的地方:需要在
where
後手工添加
1=1
的子句。
因為,若
where
後的所有
<if/>
條件均為
false
,而
where
後若又沒有
1=1
子句,則 SQL 中就會隻剩下一個空的
where
,SQL 出錯。
是以,在
where
後,需要添加永為真子句
1=1
,以防止這種情況的發生。但當資料量很大時,會嚴重影響查詢效率。
<!-- where-->
<select id="selectByWhere" resultType="net.work100.training.stage2.mybatis.entity.Student">
SELECT
id,
name,
age,
score
FROM
student
<where>
<if test="name != null and name != ''">
AND name LIKE concat('%', #{name}, '%')
</if>
<if test="age != null and age > 0">
AND age > #{age}
</if>
</where>
</select>
5.choose标簽
該标簽中隻可以包含
<when/> <otherwise/>
,可以包含多個
<when/>
與一個
<otherwise/>
。
它們聯合使用,完成 Java 中的開關語句
switch..case
功能。
本例要完成的需求是,若姓名不空,則按照姓名查詢;若姓名為空,則按照年齡查詢;若沒有查詢條件,則沒有查詢結果。
<!-- choose -->
<select id="selectByChoose" resultType="net.work100.training.stage2.mybatis.entity.Student">
SELECT
id,
name,
age,
score
FROM
student
<where>
<choose>
<when test="name != null and name != ''">
AND name LIKE concat('%', #{name}, '%')
</when>
<when test="age != null and age > 0">
AND age > #{age}
</when>
<otherwise>
AND 1 != 1
</otherwise>
</choose>
</where>
</select>
6.foreach标簽-周遊數組
<foreach/>
标簽用于實作對于數組與集合的周遊。對其使用,需要注意:
-
表示要周遊的集合類型,這裡是數組,即collection
array
-
open
close
為對周遊内容的 SQL 拼接。separator
本例實作的需求是,查詢出 id 為 2 與 4 的學生資訊。
動态 SQL 的判斷中使用的都是 OGNL 表達式。
OGNL 表達式中的數組使用
array
表示,數組長度使用
array.length
表示。
<!-- foreach -->
<select id="selectByForeach" resultType="net.work100.training.stage2.mybatis.entity.Student">
<!-- select * from student where id in (2, 4) -->
SELECT
id,
name,
age,
score
FROM
student
<if test="array != null and array.length > 0">
WHERE id IN
<foreach collection="array" open="(" close=")" item="id" separator=",">
#{id}
</foreach>
</if>
</select>
7.foreach标簽-周遊集合
周遊集合的方式與周遊數組的方式相同,隻不過是将
array
替換成了
list
周遊泛型為基本類型的 List
定義 DAO 接口
/**
* 使用 foreach 标簽以 list 基本類型的形式查詢
* @param ids
* @return
*/
public List<Student> selectByForeachWithListBase(List<Long> ids);
<!-- foreach -->
<select id="selectByForeachWithListBase" resultType="net.work100.training.stage2.mybatis.entity.Student">
<!-- select * from student where id in (2, 4) -->
SELECT
id,
name,
age,
score
FROM
student
<if test="list != null and list.size > 0">
WHERE id IN
<foreach collection="list" open="(" close=")" item="id" separator=",">
#{id}
</foreach>
</if>
</select>
周遊泛型為自定義類型的 List
/**
* 使用 foreach 标簽以 list 自定義類型的形式查詢
* @param students
* @return
*/
public List<Student> selectByForeachWithListCustom(List<Student> students);
<!-- foreach -->
<select id="selectByForeachWithListCustom" resultType="net.work100.training.stage2.mybatis.entity.Student">
<!-- select * from student where id in (2, 4) -->
SELECT
id,
name,
age,
score
FROM
student
<if test="list != null and list.size > 0">
WHERE id IN
<foreach collection="list" open="(" close=")" item="student" separator=",">
#{student.id}
</foreach>
</if>
</select>
8.sql标簽
<sql/>
标簽用于定義 SQL 片斷,以便其它 SQL 标簽複用。
而其它标簽使用該 SQL 片斷, 需要使用
<include/>
子标簽。
該
<sql/>
标簽可以定義 SQL 語句中的任何部分,是以
<include/>
子标簽可以放在動态 SQL 的任何位置。
修改映射檔案
<sql id="select">
SELECT
id,
name,
age,
score
FROM
student
</sql>
<!-- foreach -->
<select id="selectByForeachWithListCustom" resultType="net.work100.training.stage2.mybatis.entity.Student">
<!-- select * from student where id in (2, 4) -->
<include refid="select" />
<if test="list != null and list.size > 0">
WHERE id IN
<foreach collection="list" open="(" close=")" item="student" separator=",">
#{student.id}
</foreach>
</if>
</select>
上一篇:
MyBatis 單表 CRUD 操作如果對課程内容感興趣,可以掃碼關注我們的或
公衆号
,及時關注我們的課程更新
QQ群
