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

如何使用Criteria Query查询关联继承链中的多实体属性?

跨JPA继承实体的Criteria Query实现

要实现跨Anuncio、Produto、Bovino三个实体的属性查询,核心是处理JPA的JOINED继承关系,通过treat操作访问子类属性,同时关联主实体与父类实体。以下是修正后的实现方案:

关键步骤说明

  1. 关联主实体与父类:从Anuncio根对象关联到Produto实体,使用INNER JOIN确保只返回关联了有效Produto的Anuncio。
  2. 特化父类为子类:通过CriteriaBuilder.treat()将Produto的关联对象转换为Bovino类型,这样就能直接访问Bovino的专属属性。
  3. 添加类型过滤:必须添加Produto类型为Bovino的条件,避免因其他子类不存在目标属性导致的查询错误。

完整代码实现

public List<Anuncio> getFilteredBuilder(Integer qualidadeGado, Integer racaGado, Integer idadeStart, Integer idadeEnd){
        
    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<Anuncio> cq = cb.createQuery(Anuncio.class);
    Root<Anuncio> rootAn = cq.from(Anuncio.class);
    
    // 关联Anuncio到Produto(一对一关联,用INNER JOIN)
    Join<Anuncio, Produto> produtoJoin = rootAn.join("produto", JoinType.INNER);
    // 将Produto特化为Bovino子类,允许访问子类属性
    Join<Anuncio, Bovino> bovinoJoin = cb.treat(produtoJoin, Bovino.class);
    
    List<Predicate> preds = new ArrayList<>();
    
    // 添加类型过滤:确保Produto是Bovino类型
    preds.add(cb.equal(produtoJoin.type(), cb.literal(Bovino.class)));
    
    // 针对Bovino的属性构建查询条件
    if (qualidadeGado != null) {
        preds.add(cb.equal(bovinoJoin.get("qualidade"), qualidadeGado));
    }
    if (racaGado != null) {
        preds.add(cb.equal(bovinoJoin.get("raca"), racaGado));
    }
    if (idadeStart != null ) {
        preds.add(cb.ge(bovinoJoin.get("idadeOuMedia"), idadeStart));
    }
    if (idadeEnd != null) {
        preds.add(cb.le(bovinoJoin.get("idadeOuMedia"), idadeEnd));
    }
    
    cq.where(preds.toArray(new Predicate[0]));
    
    return em.createQuery(cq).getResultList();
}

注意事项

  • 如果需要同时支持多个Produto子类的查询,可以通过cb.or()组合不同子类的类型判断与对应属性条件。
  • 确保实体类中Bovino确实存在qualidade、raca、idadeOuMedia这些属性,否则需要调整get()方法中的属性名。

内容的提问来源于stack exchange,提问作者Fabrício Gustavo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 14:36:19