Spring Boot CriteriaBuilder添加OneToOne关联字段查询条件
JPA Criteria 关联字段动态条件实现方案
直接通过Criteria路径导航访问OneToOne关联的实体字段即可,无需额外复杂配置,具体修改如下:
- 修复原代码语法问题:原代码在
estatSolicitud条件判断块末尾多了一个多余的全角单引号´,直接删除即可正常编译。 - 新增codiCanal动态条件逻辑:因为
Solicitud和Canal是@OneToOne关联,直接通过root.get("canal").get("codiCanal")就能导航到关联表的字段,JPA会自动生成关联查询SQL,不需要手动写Join(特殊连接类型需求可以手动声明)。
如果你的查询入参是把codiCanal值封装在传入的Solicitud对象的canal属性中,直接在现有条件判断块后追加以下逻辑即可:
// 新增codiCanal过滤 if (object.getCanal() != null && !StringUtils.isEmpty(object.getCanal().getCodiCanal())) { p = cb.and(p, cb.equal(root.get("canal").get("codiCanal"), object.getCanal().getCodiCanal())); }
修改后的完整方法代码如下:
@Override public List<Solicitud> getSoliWithobject(Solicitud object, Pageable pageable) { List<Solicitud> solicitudes = soliRepo.findAll((Specification<Solicitud>) (root, cq, cb) -> { Predicate p = cb.conjunction(); if (!StringUtils.isEmpty(object.getIdFactura())) { p = cb.and(p, cb.equal(root.get("idFactura"), object.getIdFactura())); } if (!StringUtils.isEmpty(object.getDataInici()) ) { p = cb.and(p, cb.between(root.get("dataInici"), object.getDataInici(),currentDate)); } if (!StringUtils.isEmpty(object.getEstatSolicitud())) { p = cb.and(p, cb.equal(root.get("estatSolicitud"), object.getEstatSolicitud())); } // Canal关联的codiCanal字段动态条件 if (object.getCanal() != null && !StringUtils.isEmpty(object.getCanal().getCodiCanal())) { p = cb.and(p, cb.equal(root.get("canal").get("codiCanal"), object.getCanal().getCodiCanal())); } return p; }, pageable).getContent(); return solicitudes; }
可选优化场景
- 如果你不想把查询参数封装到关联的Canal对象里,可以在
Solicitud实体类中加一个瞬态查询字段,专门接收codiCanal查询参数,避免干扰原实体关联结构:
// 加在Solicitud类中,@Transient标记为不映射数据库字段 @Transient private String queryCodiCanal; // 补充对应getter、setter
对应条件判断逻辑改成:
if (!StringUtils.isEmpty(object.getQueryCodiCanal())) { p = cb.and(p, cb.equal(root.get("canal").get("codiCanal"), object.getQueryCodiCanal())); }
- 如果你需要左连接(避免Canal关联为空时Solicitud记录被过滤掉),可以显式声明连接类型:
// 先在方法内定义左连接 Join<Solicitud, Canal> canalLeftJoin = root.join("canal", JoinType.LEFT); // 条件判断时用join对象取字段 if (object.getCanal() != null && !StringUtils.isEmpty(object.getCanal().getCodiCanal())) { p = cb.and(p, cb.equal(canalLeftJoin.get("codiCanal"), object.getCanal().getCodiCanal())); }
注意:默认路径导航生成的是内连接(INNER JOIN),只有两张表关联匹配的数据才会被查出来,符合大多数按关联字段精确过滤的业务场景。
内容的提问来源于stack exchange,提问作者zerfer
相关产品推荐
相关产品推荐

