SpringBoot+MyBatis进行XML中循环处理List参数的终极指南
目录
- 一、为什么需要传递List参数?
- 二、基础版:MyBATis原生List传参
- 1. Mapper接口定义(注意@Param导入)
- 2. XML映射文件实现
- 3. 实际生成的SQL
- 三、避坑重点:@Param的正确使用
- 常见错误1:导入错误包
- 常见错误2:忘记添加@Param注解
- 四、MyBatis Plus的优雅实现
- 1. 使用QueryWrapper(无需XML)
- 2. Lambda表达式写法(推荐)
- 五、扩展应用场景
- 场景1:List处理
- 场景2:List<实体对象>
- 场景3:多List参数
- 六、特殊类型处理技巧
- 1. 枚举类型处理
- 2. 日期范围查询
- 七、性能优化与避坑指南
- 1. 空集合安全处理
- 2. 大数据量分批查询
- 3. SQL注入防护
- 八、完整可运行示例
- Controller
- Service
- Mapper XML
- 总结:核心要点回顾
重要提醒:使用@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参数内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关编程客栈文章希望大家以后多多支持编程客栈(www.devze.com)!
精彩评论