SpringBoot+MyBatis進(jìn)行XML中循環(huán)處理List參數(shù)的終極指南
重要提醒:使用@Param注解時(shí),務(wù)必導(dǎo)入正確的包!
import org.apache.ibatis.annotations.Param;
很多開發(fā)者容易錯(cuò)誤導(dǎo)入Spring的@Param,導(dǎo)致參數(shù)綁定失??!
一、為什么需要傳遞List參數(shù)?
最常見的場(chǎng)景是動(dòng)態(tài)構(gòu)建IN查詢:
SELECT * FROM users WHERE id IN (1, 2, 3, 4)
當(dāng)我們需要根據(jù)前端傳入的多個(gè)值查詢時(shí),就需要將List集合作為參數(shù)傳遞給Mapper。
二、基礎(chǔ)版:MyBatis原生List傳參
1. Mapper接口定義(注意@Param導(dǎo)入)
// ?。?!必須導(dǎo)入MyBatis的@Param包!?。?
import org.apache.ibatis.annotations.Param;
public interface UserMapper {
// 使用@Param注解指定參數(shù)名
List<User> selectByIds(@Param("idList") List<Long> idList);
}
2. XML映射文件實(shí)現(xiàn)
<select id="selectByIds" resultType="User">
SELECT * FROM users
WHERE id IN
<foreach collection="idList" item="id"
open="(" separator="," close=")">
#{id}
</foreach>
</select>
核心標(biāo)簽解析:
| 屬性 | 說(shuō)明 | 示例值 |
|---|---|---|
| collection | 傳入的集合參數(shù)名 | idList |
| item | 循環(huán)中當(dāng)前元素的別名 | id |
| open | 循環(huán)開始前的字符串 | ( |
| separator | 元素間的分隔符 | , |
| close | 循環(huán)結(jié)束后的字符串 | ) |
3. 實(shí)際生成的SQL
當(dāng)傳入List<Long> ids = Arrays.asList(1L, 2L, 3L)時(shí):
SELECT * FROM users WHERE id IN (1, 2, 3)
三、避坑重點(diǎn):@Param的正確使用
常見錯(cuò)誤1:導(dǎo)入錯(cuò)誤包
// ? 錯(cuò)誤:導(dǎo)入了Spring的Param包 import org.springframework.data.repository.query.Param; // ? 正確:必須使用MyBatis的Param包 import org.apache.ibatis.annotations.Param;
常見錯(cuò)誤2:忘記添加@Param注解
// ? 錯(cuò)誤:缺少@Param注解會(huì)導(dǎo)致XML中無(wú)法識(shí)別參數(shù)
List<User> selectByIds(List<Long> idList);
// ? 正確:必須添加@Param注解
List<User> selectByIds(@Param("idList") List<Long> idList);
四、MyBatis Plus的優(yōu)雅實(shí)現(xiàn)
1. 使用QueryWrapper(無(wú)需XML)
public List<User> getUsersByIds(List<Long> ids) {
return userMapper.selectList(
new QueryWrapper<User>().in("id", ids)
);
}
2. Lambda表達(dá)式寫法(推薦)
public List<User> getUsersByIds(List<Long> ids) {
return userMapper.selectList(
Wrappers.<User>lambdaQuery()
.in(User::getId, ids)
);
}
注意:MyBatis Plus的Wrapper方式不需要@Param注解
五、擴(kuò)展應(yīng)用場(chǎng)景
場(chǎng)景1:List處理
// Mapper
List<User> selectByNames(@Param("nameList") List<String> nameList);
// XML
<foreach collection="nameList" item="name" open="(" separator="," close=")">
#{name}
</foreach>
場(chǎng)景2:List<實(shí)體對(duì)象>
// Mapper
List<User> selectByConditions(@Param("userList") List<User> userList);
// XML
<foreach collection="userList" item="user" separator=" OR ">
(name = #{user.name} AND age > #{user.age})
</foreach>
場(chǎng)景3:多List參數(shù)
// Mapper
List<User> searchUsers(@Param("ids") List<Long> ids,
@Param("names") List<String> names);
// XML
<where>
<if test="ids != null and !ids.isEmpty()">
id IN
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</if>
<if test="names != null and !names.isEmpty()">
AND name IN
<foreach collection="names" item="name" open="(" separator="," close=")">
#{name}
</foreach>
</if>
</where>
六、特殊類型處理技巧
1. 枚舉類型處理
// Mapper
List<User> selectByStatus(@Param("statusList") List<UserStatus> statusList);
// XML
<foreach collection="statusList" item="status" open="(" separator="," close=")">
#{status, typeHandler=org.apache.ibatis.type.EnumTypeHandler}
</foreach>
2. 日期范圍查詢
// Mapper
List<User> selectByDates(@Param("dateList") List<Date> dates);
// XML
<foreach collection="dateList" item="date" separator=" OR ">
create_time BETWEEN #{date} AND DATE_ADD(#{date}, INTERVAL 1 DAY)
</foreach>
七、性能優(yōu)化與避坑指南
1. 空集合安全處理
<select id="safeSelect">
SELECT * FROM users
<where>
<if test="idList != null and !idList.isEmpty()">
id IN
<foreach collection="idList" ... />
</if>
</where>
</select>
2. 大數(shù)據(jù)量分批查詢
// 每500條執(zhí)行一次查詢
public List<User> batchSelect(List<Long> allIds) {
List<User> result = new ArrayList<>();
int batchSize = 500;
for (int i = 0; i < allIds.size(); i += batchSize) {
List<Long> batchIds = allIds.subList(i, Math.min(i + batchSize, allIds.size()));
result.addAll(userMapper.selectByIds(batchIds));
}
return result;
}
3. SQL注入防護(hù)
<!-- 安全寫法:使用#{}預(yù)編譯 -->
<foreach collection="names" item="name">
#{name} <!-- 安全 -->
</foreach>
<!-- 危險(xiǎn)寫法:${}直接拼接 -->
<foreach collection="names" item="name">
'${name}' <!-- 存在SQL注入風(fēng)險(xiǎn)! -->
</foreach>
八、完整可運(yùn)行示例
Controller
@RestController
@RequestMapping("/users")
public class UserController {
@PostMapping("/by-ids")
public List<User> getUsersByIds(@RequestBody List<Long> ids) {
return userService.getUsersByIds(ids);
}
}
Service
@Service
@RequiredArgsConstructor
public class UserService {
private final UserMapper userMapper;
public List<User> getUsersByIds(List<Long> ids) {
if (ids == null || ids.isEmpty()) {
return Collections.emptyList();
}
// 超過(guò)1000條自動(dòng)分批
return ids.size() > 1000 ? batchSelect(ids) : userMapper.selectByIds(ids);
}
}
Mapper XML
<mapper namespace="com.example.mapper.UserMapper">
<select id="selectByIds" resultType="User">
SELECT id, name, email
FROM users
<where>
<if test="idList != null and !idList.isEmpty()">
id IN
<foreach collection="idList" item="id"
open="(" separator="," close=")">
#{id}
</foreach>
</if>
</where>
</select>
</mapper>
總結(jié):核心要點(diǎn)回顧
1.必須使用正確的@Param包 import org.apache.ibatis.annotations.Param;
2.XML循環(huán)核心語(yǔ)法
<foreach collection="參數(shù)名" item="元素名"
open="開始符" separator="分隔符" close="結(jié)束符">
#{元素名}
</foreach>
3.最佳實(shí)踐選擇
- 簡(jiǎn)單查詢:MyBatis Plus Wrapper
- 復(fù)雜SQL:MyBatis XML + foreach
- 超大數(shù)據(jù):分批查詢
4.安全防護(hù)
- 始終使用
#{}防止SQL注入 - 空集合檢查避免全表掃描
5.特殊類型處理
- 枚舉:添加typeHandler
- 日期:指定jdbcType=TIMESTAMP
最后提醒: 當(dāng)遇到參數(shù)綁定問(wèn)題時(shí),首先檢查@Param導(dǎo)入的包是否正確,這是最常見的錯(cuò)誤根源!
到此這篇關(guān)于SpringBoot+MyBatis進(jìn)行XML中循環(huán)處理List參數(shù)的終極指南的文章就介紹到這了,更多相關(guān)SpringBoot處理List參數(shù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java基礎(chǔ)詳解之集合框架工具Collections
這篇文章主要介紹了Java基礎(chǔ)詳解之集合框架工具Collections,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java的小伙伴們有很好地幫助,需要的朋友可以參考下2021-04-04
SpringBoot項(xiàng)目 文件上傳臨時(shí)目標(biāo)被刪除異常的處理方案
這篇文章主要介紹了SpringBoot項(xiàng)目 文件上傳臨時(shí)目標(biāo)被刪除異常的處理方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-07-07
Java實(shí)現(xiàn)入?yún)?shù)據(jù)批量數(shù)據(jù)校驗(yàn)詳解
在業(yè)務(wù)處理中一般入?yún)⑹菃螚l數(shù)據(jù),這樣數(shù)據(jù)校驗(yàn)比較容易,但是這種方法對(duì)于集合數(shù)據(jù)的校驗(yàn)不適用,下面我們就來(lái)看看如何對(duì)入?yún)?shù)據(jù)進(jìn)行批量數(shù)據(jù)校驗(yàn)吧2024-02-02
spring Security配置攔截規(guī)則小結(jié)
本文介紹了使用Spring Security解決后臺(tái)管理系統(tǒng)在訪問(wèn)靜態(tài)資源如圖片時(shí)需要登錄驗(yàn)證的問(wèn)題,通過(guò)配置攔截規(guī)則,將靜態(tài)資源路徑添加到白名單,感興趣的可以了解一下2025-09-09
JavaFX實(shí)現(xiàn)UI美觀效果代碼實(shí)例
這篇文章主要介紹了JavaFX實(shí)現(xiàn)UI美觀效果代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-07-07
MyBatis動(dòng)態(tài)SQL與緩存原理深入分析
這篇文章主要介紹了MyBatis動(dòng)態(tài)SQL與緩存原理,Mybatis框架的動(dòng)態(tài)SQL技術(shù)是一種根據(jù)特定條件動(dòng)態(tài)拼裝SQL語(yǔ)句的功能,它存在的意義是為了解決拼接SQL語(yǔ)句字符串時(shí)的痛點(diǎn)問(wèn)題2023-02-02

