重要提醒:使用@param注解时,务必导入正确的包!
import org.apache.ibatis.annotations.param;
很多开发者容易错误导入spring的@param,导致参数绑定失败!
一、为什么需要传递list参数?
最常见的场景是动态构建in查询:
select * from users where id in (1, 2, 3, 4)
当我们需要根据前端传入的多个值查询时,就需要将list集合作为参数传递给mapper。
二、基础版:mybatis原生list传参
1. mapper接口定义(注意@param导入)
// !!!必须导入mybatis的@param包!!!
import org.apache.ibatis.annotations.param;
public interface usermapper {
// 使用@param注解指定参数名
list<user> selectbyids(@param("idlist") list<long> idlist);
}
2. xml映射文件实现
<select id="selectbyids" resulttype="user">
select * from users
where id in
<foreach collection="idlist" item="id"
open="(" separator="," close=")">
#{id}
</foreach>
</select>
核心标签解析:
| 属性 | 说明 | 示例值 |
|---|---|---|
| collection | 传入的集合参数名 | idlist |
| item | 循环中当前元素的别名 | id |
| open | 循环开始前的字符串 | ( |
| separator | 元素间的分隔符 | , |
| close | 循环结束后的字符串 | ) |
3. 实际生成的sql
当传入list<long> ids = arrays.aslist(1l, 2l, 3l)时:
select * from users where id in (1, 2, 3)
三、避坑重点:@param的正确使用
常见错误1:导入错误包
// ❌ 错误:导入了spring的param包 import org.springframework.data.repository.query.param; // ✅ 正确:必须使用mybatis的param包 import org.apache.ibatis.annotations.param;
常见错误2:忘记添加@param注解
// ❌ 错误:缺少@param注解会导致xml中无法识别参数
list<user> selectbyids(list<long> idlist);
// ✅ 正确:必须添加@param注解
list<user> selectbyids(@param("idlist") list<long> idlist);
四、mybatis plus的优雅实现
1. 使用querywrapper(无需xml)
public list<user> getusersbyids(list<long> ids) {
return usermapper.selectlist(
new querywrapper<user>().in("id", ids)
);
}
2. lambda表达式写法(推荐)
public list<user> getusersbyids(list<long> ids) {
return usermapper.selectlist(
wrappers.<user>lambdaquery()
.in(user::getid, ids)
);
}
注意:mybatis plus的wrapper方式不需要@param注解
五、扩展应用场景
场景1:list处理
// mapper
list<user> selectbynames(@param("namelist") list<string> namelist);
// xml
<foreach collection="namelist" item="name" open="(" separator="," close=")">
#{name}
</foreach>
场景2:list<实体对象>
// 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>
场景3:多list参数
// 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>
七、性能优化与避坑指南
1. 空集合安全处理
<select id="safeselect">
select * from users
<where>
<if test="idlist != null and !idlist.isempty()">
id in
<foreach collection="idlist" ... />
</if>
</where>
</select>
2. 大数据量分批查询
// 每500条执行一次查询
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注入防护
<!-- 安全写法:使用#{}预编译 -->
<foreach collection="names" item="name">
#{name} <!-- 安全 -->
</foreach>
<!-- 危险写法:${}直接拼接 -->
<foreach collection="names" item="name">
'${name}' <!-- 存在sql注入风险! -->
</foreach>
八、完整可运行示例
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();
}
// 超过1000条自动分批
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>
总结:核心要点回顾
1.必须使用正确的@param包 import org.apache.ibatis.annotations.param;
2.xml循环核心语法
<foreach collection="参数名" item="元素名"
open="开始符" separator="分隔符" close="结束符">
#{元素名}
</foreach>
3.最佳实践选择
- 简单查询:mybatis plus wrapper
- 复杂sql:mybatis xml + foreach
- 超大数据:分批查询
4.安全防护
- 始终使用
#{}防止sql注入 - 空集合检查避免全表扫描
5.特殊类型处理
- 枚举:添加typehandler
- 日期:指定jdbctype=timestamp
最后提醒: 当遇到参数绑定问题时,首先检查@param导入的包是否正确,这是最常见的错误根源!
到此这篇关于springboot+mybatis进行xml中循环处理list参数的终极指南的文章就介绍到这了,更多相关springboot处理list参数内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论