在 MyBatis XML 里写大于小于号,一不小心就踩坑
整理了 MyBatis XML 里处理大于、小于等特殊符号的两种方式,以及动态 SQL 里容易报错的写法,配了可直接上手的示例。
支持通配符SSL证书、多域名证书、IP证书。适配ACME接口, 支持Zerossl、Let's Encrypt和Google等渠道。登录已有账号
2026-08-11 12:00:37 MyBatis foreach IN查询 @Param
MyBatis 里写 IN 查询,传个 List 或者数组进去,差不多是个高频需求。
核心就两步:接口上用 @Param 给集合起个名字,XML 里用 标签把 IN 后面的括号和占位符拼出来。这俩配合好,绝大多数场景都够用了。
先说最简写法。
接口里别直接传 List,拿 @Param 明确指定一个参数名。不然 MyBatis 默认用 "list" 或 "array",多参数时容易乱,而且代码读起来不直观。
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface UserMapper {
List<User> findUsersByIdList(@Param("userIds") List<Integer> idList);
}
XML 这边, 几个属性这样用:
拼出来的 SQL 大概就是 WHERE id IN ( ? , ? , ? ) 的样子。
<select id="findUsersByIdList" resultType="User">
SELECT id, username, email
FROM users
WHERE id IN
<foreach item="id" collection="userIds" open="(" separator="," close=")">
#{id}
</foreach>
</select>
传数组的情况几乎一模一样,只是参数类型从 List 换成 Integer[],XML 里 collection 指向数组对应的 @Param 名就行。
List<User> findUsersByIdArray(@Param("idArray") Integer[] ids);
<foreach collection="idArray" item="id" open="(" separator="," close=")">
#{id}
</foreach>
这里其实容易踩坑的地方是——多参数场景。
如果除了集合还有别的条件,每个参数都必须用 @Param 命名,少一个都会导致绑定异常。比如同时传 ID 列表和一个 status:
List<User> findUsersByCriteria(
@Param("userIds") List<Integer> ids,
@Param("status") Integer status
);
XML 里 的 collection 依然写 "userIds",剩下的参数正常用 #{status} 引用,别混了。
<select id="findUsersByCriteria">
SELECT * FROM users
WHERE id IN
<foreach collection="userIds" item="id" open="(" separator="," close=")">
#{id}
</foreach>
AND status = #{status}
</select>
实际写的时候有几个点值得留心。
始终用 @Param 给集合起个有意义的名字,别图省事用默认的 list。一两个月后回来看代码,readability 会好很多,排查线上问题时也少绕一步。
空集合的问题要提前在业务层拦住。如果集合是空的还传给 MyBatis, 拼不出任何占位符,最终跑到数据库的就是 WHERE id IN ( ),直接报语法错误。要么调用 mapper 前判断一下直接返回空列表,要么在 SQL 里加个 判空分支,但前者更干净。
大集合 IN 查询,数据库那边也可能扛不住。几百上千个 ID 砸进去,SQL 解析变慢,IN 列表太长甚至触发数据库自身的限制。
这种情况该分批查就分批查,单次控制在几百条以内,或者考虑用临时表连表查询。别等线上慢查询告警了再改。
安全方面多说一句。动态拼接表名、排序字段这种场景才去用 ${},IN 查询这里都用 #{} 预编译,跟 配合是安全的。
但如果哪天有人想灵活到把字段名也动态传进来,一定要做白名单校验,否则 SQL 注入的风险就在那。
完整代码差不多就长这样,方便复制的时候有个参考。
接口:
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface UserMapper {
List<User> findUsersByIdList(@Param("userIds") List<Integer> idList);
List<User> findUsersByCriteria(
@Param("userIds") List<Integer> ids,
@Param("status") Integer status
);
}
XML 映射文件:
<?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="com.example.mapper.UserMapper">
<select id="findUsersByIdList" resultType="User">
SELECT id, username, email
FROM users
WHERE id IN
<foreach item="id" collection="userIds" open="(" separator="," close=")">
#{id}
</foreach>
</select>
<select id="findUsersByCriteria" resultType="User">
SELECT * FROM users
WHERE id IN
<foreach item="id" collection="userIds" open="(" separator="," close=")">
#{id}
</foreach>
AND status = #{status}
</select>
</mapper>
就这么点东西,搞清楚 @Param 和 的关系,基本不会写出问题。踩过一次空集合的坑以后,自然就养成手动判空的习惯了。
整理了 MyBatis XML 里处理大于、小于等特殊符号的两种方式,以及动态 SQL 里容易报错的写法,配了可直接上手的示例。
写MyBatis动态SQL一不留神就XML解析报错,这篇总结一下实体转义和CDATA两种处理特殊符号的方式,以及什么场景用哪种更舒服。
记录一次线上ORDER BY拼接漏掉空格导致SQL语法错误的排查过程,以及对应的修复合规和SQL注入防护。
在MyBatis XML映射文件中,特殊符号如`<`、`>`、`&`等常常引发解析错误。本文将为你深入剖析两种核心转义方案:XML实体转义符与CDATA区块。我们将详细阐述它们的适用场景、优缺点,并提供实战建议,帮助你根据SQL复杂度灵活选择,确保XML文件正确解析,告别繁琐的转义工作,全面提升代码可维护性与团队开发效率。
当MyBatis多表关联查询返回的数据总是“缺斤少两”,甚至一对多只剩一条记录时,你是否感到束手无策?本文将化身技术侦探,深入剖析字段冲突、ResultMap配置陷阱及SQL逻辑漏洞,手把手教你运用别名、id标签和逐步验证法,彻底解决结果集缺失问题,确保数据完整无误。