MyBatis 的强大特性之一便是它的动态 SQL。如果你有使用 JDBC 或其它类似框架的经验,就能体会到根据不同条件拼接 SQL 语句的痛苦。在Java项目中,通过动态SQL批量查询数据是很常见的情形,作为传值的字段可以是一个数组或集合。如何正确引用,在此做一个实践总结。
目录
扫描二维码关注公众号,回复:
15252899 查看本文章
运行环境:
- Windows-7-Ultimate-x64、Windows-10-BusinessEditions-21H2-x64
- OracleJDK-1.8_u201、OracleJDK-11、OracleJDK-17
- OpenJDK-8、OpenJDK-11+28、OpenJDK-17+35
- IntelliJ IDEA Community Edition 2022.2.3
- MyBatis-3.5.9
1、数组
1.1、DAO层参数定义
如:字段为 String 数组。
// 数组
private String[] roleCodes;
1.2、XML动态SQL写法
以 基础数据类型 或 其包装器类 举例
- 是否为空:数组对象.length > 0
- 子项引用:${变量别名}
- 举例说明:字符型 在首尾使用半角单引号包裹 '${item}'、其他类型 直接用 ${item}
<if test="roleCodes != null and roleCodes.length > 0">
AND a.role_code
<foreach collection="roleCodes" index="index" item="item" open="IN (" separator="," close=")">
'${item}'
</foreach>
</if>
注意:此场景实为拼接SQL,有 SQL注入风险,不建议使用!
2、集合(列表、Map、Set)
本文以 List列表 单个字段 的 查询操作 举例,介绍XML动态SQL用法。Map 和 Set 使用较少,见详结尾总结用法。
2.1、DAO层参数定义
常用有两种类型:
- 字段为 基础数据类型 或 其包装器类 列表
- 字段为 自定义的Java对象 列表(推荐)
// 基础数据类型 或 其包装器类 列表
private List<String> roleCodeList;
// 对象类 列表
private List<KeyObjSet> roleCodeList;
2.1、XML动态SQL写法
2.1.1、基础数据类型 及 其包装器类 列表
- 是否为空:集合对象.size() > 0
- 子项引用:#{变量别名}
- 举例说明:#{item}
<!-- 对象列表 -->
<if test="roleList!= null and roleList.size() > 0">
and role_code
<foreach collection="roleList" index="index" item="item" open="IN (" separator="," close=")">
#{item}
</foreach>
</if>
2.1.2、自定义数据对象 列表
- 是否为空:集合对象.size() > 0
- 子项引用:#{变量别名.键名}
- 举例说明:#{item.key}
<!-- 对象列表 -->
<if test="roleList!= null and roleList.size() > 0">
and role_code
<foreach collection="roleList" index="index" item="item" open="IN (" separator="," close=")">
#{item.key}
</foreach>
</if>
说明:此处的 键名 key 即Java对象的属性名。
3、实践总结
可以将任何 可迭代对象(如:List
、
Set
等)、
Map
对象 或 数组对象 传递给
foreach
作为集合参数,它们的使用区别如下:
-
当使用 可迭代对象 或 数组 时, index 是 当前迭代的次数 , item 的值是 本次迭代获取的元素
-
当使用 Map 对象 (或者 Map.Entry 对象的集合)时, index 是 键 , item 是 值
附录: