MyBatis 精确查询逗号分隔字符串

MyBatis实战:如何精确查询逗号分隔字符串中的目标值?

在日常开发中,我们经常会遇到这样的场景:数据库某个字段存储的是逗号分隔的字符串(比如 "44,4401""4401,44"),需要精确查询包含某个独立值(比如 "44")的记录。

如果直接用 LIKE '%44%',很容易误匹配到 "4401""144" 这类包含 "44" 但并非目标值的情况。今天就来分享一种在 MyBatis 中高效解决这个问题的方案。

问题场景再现

假设数据库表 t_code 中有一个字段 codes,存储的值可能是:

  • "44,4401"(44 和 4401 两个值)
  • "4401,44"(4401 和 44 两个值)
  • "44"(单独的 44)
  • "4401"(不含 44,仅 4401)

现在需要查询所有 codes包含独立的 "44" 的记录,预期结果是前三种情况,而 "4401" 不应被匹配。

为什么普通 LIKE 不行?

如果直接写:

sql 复制代码
SELECT * FROM t_code WHERE codes LIKE '%44%'

此时 "4401" 会被误匹配(因为字符串中包含 "44"),不符合「精确查询独立值」的需求。

核心解决方案:用逗号"包裹"目标值

关键思路是:让目标值和字段中的每个子项都处于相同的"逗号包围"状态,再进行匹配。

具体操作:

  1. 给数据库字段 codes 前后各拼接一个逗号,变成 ",原字符串,"(比如 "44,4401" 变成 ",44,4401,");
  2. 给目标值前后也各拼接一个逗号,变成 ",目标值,"(比如 "44" 变成 ",44,");
  3. LIKE 判断拼接后的字段是否包含拼接后的目标值。

这样就能确保只匹配独立的子项,不会误判包含目标值的其他字符串。

MyBatis 代码实现

1. Mapper.xml 编写 SQL

在 Mapper.xml 中,通过 CONCAT 函数完成拼接,SQL 如下:

xml 复制代码
<select id="selectByTargetCode" resultType="com.example.entity.CodeEntity">
    SELECT * FROM t_code
    WHERE 
        -- 字段前后加逗号,目标值前后加逗号,确保精确匹配独立项
        CONCAT(',', codes, ',') LIKE CONCAT('%,', #{targetCode}, ',%')
</select>
  • CONCAT(',', codes, ','):给字段值前后加逗号(处理边界情况,比如值在开头或结尾);
  • CONCAT('%,', #{targetCode}, ',%'):给目标值前后加逗号,并用 % 匹配任意位置。

2. Mapper 接口定义

对应的 Mapper 接口需要接收目标值参数:

java 复制代码
public interface CodeMapper {
    /**
     * 精确查询包含目标值的记录
     * @param targetCode 目标值(如"44")
     * @return 匹配的记录列表
     */
    List<CodeEntity> selectByTargetCode(@Param("targetCode") String targetCode);
}

3. 效果验证

数据库 codes 拼接后的值 目标值"44"拼接后 是否匹配 结果是否符合预期
"44,4401" ",44,4401," ",44," 符合
"4401,44" ",4401,44," ",44," 符合
"44" ",44," ",44," 符合
"4401" ",4401," ",44," 符合

方案优势

  1. 精确性:彻底避免误匹配(如"4401"不会被当作"44"查询出来);
  2. 通用性 :适用于任何数据库(CONCATLIKE 是 SQL 标准函数);
  3. 简洁性:无需复杂逻辑,一行 SQL 即可解决问题;
  4. 兼容性:无论目标值在字符串的开头、中间还是结尾,都能正确匹配。

注意事项

  • 如果字段可能为 NULL,建议先处理空值(比如 CONCAT(',', IFNULL(codes, ''), ','));
  • 若数据量极大,这种方式可能影响查询性能(因为 CONCAT 会使索引失效),此时建议考虑拆分字段为关联表(更符合数据库设计规范)。

总结

当需要在逗号分隔的字符串中精确查询独立值时,通过「前后拼接逗号 + LIKE 匹配」的方式,能简单高效地解决问题。这种方案在 MyBatis 中只需几行代码即可实现,兼容性和精确性都能得到保证。

相关推荐
消失的旧时光-19433 小时前
搞懂 Kotlin 的 List、Set、Map、HashMap、LinkedHashMap,以及 asSequence() 的底层原理与实战场景。
kotlin·数据处理·1024程序员节
明道源码3 小时前
Kotlin 面向对象编程、主构造函数、次构造函数、伴生对象、数据类、继承
kotlin·1024程序员节
遥远_3 小时前
Spring Boot微服务健康检测:保障系统稳定性的关键实践
spring boot·微服务·1024程序员节·健康检测
苹果醋33 小时前
学习札记-Java8系列-1-Java8新特性简介&为什么要学习Java8
java·运维·spring boot·mysql·nginx
程序员杰哥3 小时前
如何使用Postman做接口自动化测试及完美的可视化报告?
自动化测试·软件测试·python·测试工具·jenkins·postman·1024程序员节
计算机毕业设计小帅3 小时前
【2026计算机毕业设计】基于Django的智慧办公hr招聘辅助管理系统
1024程序员节
千歌叹尽执夏3 小时前
Quartus25.3:Agilex5A EMIF学习调用(DDR5)
fpga开发·1024程序员节·ddr5·agilex5·emif
计算机毕业设计小帅3 小时前
【2026计算机毕业设计】基于Django的新闻资讯平台的设计与实现
1024程序员节
武子康3 小时前
Java-159 MongoDB 副本集容器化 10 分钟速查卡|keyfile + –auth + 幂等 init 附 docker-compose
java·数据库·mongodb·docker·性能优化·nosql·1024程序员节