构建含OR条件的JPQL查询,如何避免逐个判断首个条件?
解决JPQL多OR条件拼接时无需判断首个条件的几种方法
方法1:用恒真条件占位开头
直接在WHERE后加1=1,所有有效条件统一用OR [条件]拼接,不用纠结是否为第一个条件。即使没有有效筛选条件,1=1也会返回全量数据,符合无筛选的预期。
修正后的代码示例:
StringBuilder stringQuery = new StringBuilder(); stringQuery.append("select school from School school where 1=1 "); if(schooSearch.name() != null && !schooSearch.name().isEmpty()){ stringQuery.append("OR contains(school.name, :name) > 0 "); } if(schooSearch.adr() != null && !schooSearch.adr().isEmpty()){ stringQuery.append("OR school.adr like :adr "); } // 其他字段的条件都按此格式添加
方法2:收集有效条件到列表再拼接
先把所有符合条件的JPQL片段存入List,最后用OR连接列表内容,再判断是否需要添加WHERE子句,逻辑更清晰,避免冗余判断。
代码示例:
List<String> conditions = new ArrayList<>(); if(schooSearch.name() != null && !schooSearch.name().isEmpty()){ conditions.add("contains(school.name, :name) > 0"); } if(schooSearch.adr() != null && !schooSearch.adr().isEmpty()){ conditions.add("school.adr like :adr"); } // 其他字段的条件判断逻辑 StringBuilder stringQuery = new StringBuilder("select school from School school"); if(!conditions.isEmpty()){ stringQuery.append(" where ").append(String.join(" OR ", conditions)); }
方法3:用JPA Criteria API(推荐)
如果项目允许,直接使用Criteria API构建查询,无需手动拼接字符串,框架会自动处理条件连接、参数绑定,还能避免JPQL语法错误和注入风险。
代码示例:
CriteriaBuilder cb = entityManager.getCriteriaBuilder(); CriteriaQuery<School> query = cb.createQuery(School.class); Root<School> school = query.from(School.class); List<Predicate> predicates = new ArrayList<>(); // 处理name条件 if(schooSearch.name() != null && !schooSearch.name().isEmpty()){ // 不同JPA实现的contains函数调用可能略有差异,此处以Hibernate为例 Predicate namePredicate = cb.gt( cb.function("contains", Integer.class, school.get("name"), cb.parameter(String.class, "name")), 0 ); predicates.add(namePredicate); } // 处理adr条件 if(schooSearch.adr() != null && !schooSearch.adr().isEmpty()){ Predicate adrPredicate = cb.like(school.get("adr"), cb.parameter(String.class, "adr")); predicates.add(adrPredicate); } // 其他字段的Predicate构建逻辑 if(!predicates.isEmpty()){ query.where(cb.or(predicates.toArray(new Predicate[0]))); } TypedQuery<School> typedQuery = entityManager.createQuery(query); // 绑定参数 if(schooSearch.name() != null && !schooSearch.name().isEmpty()){ typedQuery.setParameter("name", schooSearch.name()); } if(schooSearch.adr() != null && !schooSearch.adr().isEmpty()){ typedQuery.setParameter("adr", schooSearch.adr()); } List<School> result = typedQuery.getResultList();
内容的提问来源于stack exchange,提问作者robert trudel
相关产品推荐
相关产品推荐

