You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Criteria Builder自动过滤空参数?避免重复空值判断

问题描述

我定义了如下Java对象:

public class ParametriAnagraficaFullMonitorBO implements ParametriFullMonitorBO {
    UserTypeEnum tipoCliente;
    String nome;
    String cognome;
    String denominazione;
    String codiceFiscale;
    String partitaIva;
    String numeroRea;
    String provinciaCciaa;
}

我希望用该对象的所有属性通过Criteria Builder构建查询,当前做法如下:

if (Objects.nonNull(nome)) {
    //queryConditions是一个列表
    queryConditions.add(criteriaBuilder.equal(root.get("nome"), nome));
}

但重复编写这类空值判断的if语句十分冗余,想了解Criteria Builder是否支持自动检测空值并排除对应的查询条件?

解决方案

Criteria Builder本身不支持自动检测空值并排除查询条件,但可以通过以下几种方式避免冗余的空值判断代码:

1. 封装通用工具方法

把"空值检查+添加查询条件"的逻辑封装成工具方法,复用代码:

public class CriteriaUtils {
    public static <T> void addEqualCondition(CriteriaBuilder cb, Root<?> root, String fieldName, T value, List<Predicate> conditions) {
        if (Objects.nonNull(value)) {
            conditions.add(cb.equal(root.get(fieldName), value));
        }
    }
}

调用时只需一行代码搞定一个属性:

CriteriaUtils.addEqualCondition(criteriaBuilder, root, "nome", nome, queryConditions);
CriteriaUtils.addEqualCondition(criteriaBuilder, root, "cognome", cognome, queryConditions);
// 其他属性同理调用

2. 结合Optional简化判断(Java 8+)

用Optional.ofNullable()替代显式的if判断,让代码更简洁:

Optional.ofNullable(nome).ifPresent(n -> queryConditions.add(criteriaBuilder.equal(root.get("nome"), n)));
Optional.ofNullable(cognome).ifPresent(c -> queryConditions.add(criteriaBuilder.equal(root.get("cognome"), c)));
// 其他属性依次处理

3. 反射批量处理(属性较多时适用)

通过反射遍历BO类的所有属性,自动生成等值查询条件,适合属性数量多且都是简单等值匹配的场景:

public List<Predicate> buildPredicates(Root<?> root, CriteriaBuilder cb, ParametriAnagraficaFullMonitorBO params) throws IllegalAccessException {
    List<Predicate> predicates = new ArrayList<>();
    for (Field field : params.getClass().getDeclaredFields()) {
        field.setAccessible(true);
        Object value = field.get(params);
        if (Objects.nonNull(value)) {
            predicates.add(cb.equal(root.get(field.getName()), value));
        }
    }
    return predicates;
}

如果有模糊查询、不等匹配等特殊逻辑,可以给字段加自定义注解来标记处理规则。

4. 用Spring Data JPA Specification(Spring生态下)

如果项目用了Spring Data JPA,Specification结合Lambda能进一步简化代码:

public Specification<YourEntity> buildSpecification(ParametriAnagraficaFullMonitorBO params) {
    return (root, query, cb) -> {
        List<Predicate> predicates = new ArrayList<>();
        Optional.ofNullable(params.getNome()).ifPresent(n -> predicates.add(cb.equal(root.get("nome"), n)));
        Optional.ofNullable(params.getCognome()).ifPresent(c -> predicates.add(cb.equal(root.get("cognome"), c)));
        // 其他属性依次处理
        return cb.and(predicates.toArray(new Predicate[0]));
    };
}

内容的提问来源于stack exchange,提问作者Lore

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 14:35:14