動態 SQL 標簽對比表
標簽 | 用途 | 關鍵屬性 | 默認行為 |
---|---|---|---|
<if> | 條件判斷 | test | 條件成立則拼接 |
<where> | 處理 WHERE | 無 | 去除 AND/OR 開頭,加 WHERE |
<set> | 處理 SET | 無 | 去除末尾逗號,加 SET |
<foreach> | 遍歷集合 | collection , item , separator | 無默認,必須指定 |
<choose> /<when> /<otherwise> | 多路選擇 | test | 只執行第一個匹配 |
<trim> | 自定義修剪 | prefix , suffix , prefixOverrides | 靈活控制前后綴 |
<bind> | 創建變量 | name , value | 執行 OGNL 表達式 |
<sql> + <include> | 代碼復用 | id , refid | 抽取公共 SQL |
? 最佳實踐建議
優先使用
<where>
和<set>
:避免手動處理AND
和逗號。<foreach>
必須注意collection
命名:單參數List
是list
,數組是array
,多參數用@Param
。復雜邏輯用
<trim>
:比<where>
和<set>
更靈活。避免過度嵌套:動態 SQL 層級不要太深,否則難以維護。
使用
<sql>
復用字段列表:避免重復寫SELECT *
或字段名。<bind>
用于模糊查詢:避免在 Java 層拼接%
。
🛠? 常見錯誤排查
問題 | 原因 | 解決方案 |
---|---|---|
Mapped Statements collection does not contain... | 方法名與 XML id 不匹配 | 檢查命名、namespace |
A different statement with this id already exists | 多個 Mapper 有相同 id | 確保 namespace + id 唯一 |
Collection 'xxx' not found | collection 寫錯 | 檢查 list /array /@Param |
SQL 報 AND ... 錯誤 | <where> 未正確使用 | 用 <where> 或 <trim> |
批量插入報錯 | <foreach> separator 缺失 | 加 separator="," |
一.select
1.select的屬性
id 用來引入這條語句,例如和接口名相同,用于實現接口
parameterType 傳來參數的類型
resultMap:適合使用返回值是自定義實體類的情況(用于多表)
resultType:適合使用返回值得數據類型是非自定義的,即jdk的提供的類型(用于單表)
2.select——傳遞單個參數
User getUserById(Integer id);
<select id="getUserById" parameterType="int" resultType="com.fzy.entity.User"> select * from user where id=#{id}</select>
單個參數不需要@parm
2.select——傳遞list、數組、map
用foreach遍歷,foreach的屬性有
tem表示集合中每一個元素進行迭代時的別名,
index指定一個名字,用于表示在迭代過程中,每次迭代到的位置,
open表示該語句以什么開始,
separator表示在每次進行迭代之間以什么符號作為分隔符,
close表示以什么結束,
collection屬性
1、如果傳入的是單參數且參數類型是一個List的時候,collection屬性值為list。
List<User> getUserList(List<Integer> ids);
<select id="getUserList" resultType="com.fzy.entity.User">select * from user where id in<foreach collection="list" item="uid" index="1" separator="," open="(" close=")">#{uid}</foreach> </select>
2、如果傳入的是單參數且參數類型是一個Array數組的時候,collection的屬性值為array 。
List<User> getUserArray(int[] array);
<select id="getUserArray" resultType="com.fzy.entity.User">select * from user where id in<foreach collection="array" item="uid" index="1" separator="," open="(" close=")">#{uid}</foreach> </select>
3、如果傳入的參數是多個的時候,我們就需要把它們封裝成一個Map了,當然單參數也可以封裝成map,實際上如果你在傳入參數的時候,在MyBatis里面也是會把它封裝成一個Map的,map的key就是參數名,所以這個時候collection屬性值就是傳入的List或Array對象在自己封裝的map里面的key。
List<User> getUserMap(Map<String,String> map);
<select id="getUserMap" resultType="com.fzy.entity.User">select * from user where username=#{username} and password= #{password} </select>
3.select——模糊查詢
SELECT * FROM table WHERE name LIKE CONCAT('%', #{text},'%');
SELECT * FROM tableName WHERE name LIKE '%${_parameter}%';
#{}和${}
在之前的默認情況下,使用#{}格式的語法會通知MyBatis創建預處理語句屬性并安全地設置值(比如通過?占位符)。這樣做更安全,更迅速,通常也是首選做法,不過有時只是想直接在 SQL語句中插入一個不改變的字符串。
比如,像 ORDER BY,可以這樣來使用: ORDER BY ${columnName}
#{}通過占位符的方式在sql執行前進行預編譯,給占位符賦值,安全性更高;
${}通過拼接的方式給sql賦值,可能會一起sql注入的問題,安全性降低;
sql注入
Select * from user where name=”zhansgan “ or ” and pwd=”123456”
4.select——resultMap
esultMap的設計目標就是為復雜語句通過配置文件描述數據庫表結果和Java實體類的關系(OR映射)