如何在QuerydslPredicateExecutor中实现忽略大小写的IN查询
Querydsl 实现忽略大小写IN匹配的方案
Querydsl 原生的in()方法没有提供字符串忽略大小写的参数,要实现需求可以用以下两种方案,根据自己的业务和索引情况选择:
方案一:统一转换大小写后做IN匹配(代码最简洁)
核心思路是数据库字段和传入的参数列表统一转成相同大小写后再做IN匹配,不用逐个拼接OR条件。
实现代码示例:
// 1. 先把传入的状态列表统一转成小写(转大写也可以,和数据库字段处理逻辑保持一致即可) List<String> processedStatusList = statusList.stream() .map(String::toLowerCase) .toList(); // 2. 构建查询条件时,对数据库的status字段也做lower()转换 QTransStuffing qTransStuffing = QTransStuffing.transStuffing; BooleanExpression isCanceledFalse = qTransStuffing.cancelStuffing.eq(false); // 用转成小写后的字段匹配转好的列表 BooleanExpression eStatusList = qTransStuffing.status.lower().in(processedStatusList); Predicate predicate = isCanceledFalse.and(eStatusList); transStuffingRepository.findAll(predicate);
方案说明:
- 生成的SQL类似:
where cancel_stuffing = false and lower(status) in (?, ?),传入的参数已经提前转成小写,和数据库字段的转换结果匹配。 - 如果数据量较大,建议给
status字段加函数索引(比如PostgreSQL的lower(status)索引、MySQL的生成列索引),避免全表扫描。
方案二:逐元素做忽略大小写匹配后OR拼接(适合有普通索引的场景)
核心思路是利用Querydsl StringPath自带的equalsIgnoreCase()方法,对每个传入的状态值单独构建忽略大小写的匹配条件,最后用OR拼接所有条件。
实现代码示例:
QTransStuffing qTransStuffing = QTransStuffing.transStuffing; BooleanBuilder builder = new BooleanBuilder(); // 先加原有固定条件 builder.and(qTransStuffing.cancelStuffing.eq(false)); // 遍历状态列表,逐个加忽略大小写的匹配条件,用OR拼接 for (String status : statusList) { builder.or(qTransStuffing.status.equalsIgnoreCase(status)); } Predicate predicate = builder; transStuffingRepository.findAll(predicate);
方案说明:
- 生成的SQL会根据数据库方言自动适配,比如部分数据库会生成基于排序规则的条件,不会强制对字段做函数转换,如果
status字段有普通的B树索引,更容易命中索引。 - 如果状态列表长度较长,拼接的SQL会变长,适合列表元素不多的场景。
注意事项
- 两种方案的大小写转换规则要统一:如果选方案一转小写,就不要只转传入列表、不转数据库字段,否则会出现匹配不到的问题。
- 如果传入的状态列表可能有空值,要提前过滤,避免
toLowerCase()或equalsIgnoreCase()抛空指针异常。
内容的提问来源于stack exchange,提问作者Ke Vin
相关产品推荐
相关产品推荐

