如何用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
相关产品推荐
相关产品推荐

