【问题标题】:fetch just one child in a JPA CriteriaBuilder Join Query在 JPA CriteriaBuilder 加入查询中仅获取一个孩子
【发布时间】:2020-06-22 12:48:20
【问题描述】:

我有 2 个实体:

public class Tyre {

 @Id
 @Column(name = "tyreid")
 @GeneratedValue
 private int tyreid;
 @Column(name = "brand")
 private String brand;
 @Column(name = "tyretype")
 private String tyretype;
 @OneToMany(targetEntity = TyreAuto.class, cascade = CascadeType.ALL)
 @JoinColumn(name = "tyreid",referencedColumnName = "tyreid")
 private List<TyreAuto> tyreAutos;
}

和:

public class TyreAuto {
 @Id
 @Column(name = "tyreautoid")
 @GeneratedValue
 private int tyreautoid;
 @Column(name = "serie")
 private String serie;
 @Column(name = "tyreid")
 private int tyreid;
}

我有以下返回 json 响应的代码:

    CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
    CriteriaQuery<Tyre> criteriaQuery = criteriaBuilder.createQuery(Tyre.class);
    Metamodel m = entityManager.getMetamodel();
    EntityType<Tyre> Tyre_ = m.entity(Tyre.class);
    Root<Tyre> tyreRoot = criteriaQuery.from(Tyre_);
    Join<Tyre,TyreAuto> tyreAutos = tyreRoot.join("tyreAutos",JoinType.INNER);

    Predicate predicateForBrand
            = criteriaBuilder.equal(tyreRoot.get("brand"), "Firestone");
    Predicate predicateForSerie
            = criteriaBuilder.equal(tyreAutos.get("serie"),"XYZ");
    Predicate predicateForBrandAndSerie
            = criteriaBuilder.and(predicateForSerie,predicateForBrand);
    criteriaQuery.where(predicateForBrandAndSerie);
    List<Tyre> items = entityManager.createQuery(criteriaQuery).getResultList();

    if (!items.equals(null)) {
        return new ResponseEntity<>(items, HttpStatus.OK);
    } else {
        return new ResponseEntity(ResponseEntity.notFound().build(),HttpStatus.NOT_FOUND);
    }

这将返回以下 Json:

[
   {
    "tyreid": 1,
    "brand": "Firestone",
    "tyretype": "Big",
    "tyreAutos": [
        {
            "tyreautoid": 38,
            "serie": "XYZ",
            "tyreid": 13
        },
        {
            "tyreautoid": 39,
            "serie": "ABC",
            "tyreid": 13
        },
        {
            "tyreautoid": 40,
            "serie": "JKL",
            "tyreid": 13
        }
      ]
    }
 ]

我的问题是:

  • 如果我在过滤 系列:“XYZ”?
  • 如何只获取一个子元素而不是全部 3 个?

我怎样才能过滤出这样的响应:

[
   {
    "tyreid": 1,
    "brand": "Firestone",
    "tyretype": "Big",
    "tyreAutos": [
        {
            "tyreautoid": 38,
            "serie": "XYZ",
            "tyreid": 13
        }
      ]
    }
 ]

【问题讨论】:

    标签: jpa entity criteria entitymanager hibernate-criteria


    【解决方案1】:

    如果我过滤 Serie:“XYZ”,为什么我会收到多个孩子注册?

    您将获得完整的 Tyre 对象,声明为 criteriaBuilder.createQuery(Tyre.class),其中 brand = "Firestone"tyreAutos 包含 tyreAutoserie = "XYZ"

    我怎样才能只获得一个子元素而不是全部 3 个?

    要仅获得一个 TyreAuto,您可以使用像 criteriaBuilder.createQuery(TyreAuto.class) 这样的反向查询以这种方式更改您的实体

    public class TyreAuto {
        @Id
        @Column(name = "tyreautoid")
        @GeneratedValue
        private int tyreautoid;
    
        @Column(name = "serie")
        private String serie;
    
        @ManyToOne
        @JoinColumn(name = "tyreid")
        private Tyre tyre;
    }
    

    现在您可以从TyreAuto 访问tyre

    CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
    CriteriaQuery<TyreAuto> criteriaQuery = criteriaBuilder.createQuery(TyreAuto.class);
    Metamodel m = entityManager.getMetamodel();
    EntityType<TyreAuto> TyreAuto_ = m.entity(TyreAuto.class);
    Root<TyreAuto> tyreAutoRoot = criteriaQuery.from(TyreAuto_);
    Join<TyreAuto, Tyre> tyre = tyreAutoRoot.join("tyre",JoinType.INNER);
    
    Predicate predicateForBrand
            = criteriaBuilder.equal(tyre.get("brand"), "Firestone");
    Predicate predicateForSerie
            = criteriaBuilder.equal(tyreAutoRoot.get("serie"),"XYZ");
    
    criteriaQuery.select(tyreAutoRoot).where(predicateForSerie, predicateForBrand);
    List<TyreAuto> items = entityManager.createQuery(criteriaQuery).getResultList();
    

    另一种选择是使用dto 类作为查询结果。您可以根据需要配置它。 Here您可以获得更多信息。阅读标准查询中的 DTO 投影

    一章

    【讨论】:

    • 要仅获取特定字段,您应该使用投影而不是实体作为查询结果。我在答案底部给了你解释的链接
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-28
    • 1970-01-01
    • 1970-01-01
    • 2019-07-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多