簡體   English   中英

解決多態子類屬性jpa hibernate查詢的標准

[英]Resolving Criteria on Polymorphic child class attribute jpa hibernate query

使用hibernate 3.6.10和hibernate jpa 2.0。

我的問題歸結為需要在一個有點復雜的加入查詢期間在子對象的列上設置一些標准。

我有一組類似於的對象:

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class Ball 
{
     private String name;
     //...getter and setter crud...
}


@Entity
public class BeachBall extend ball
{
    private boolean atTheBeach;
     //...getter and setter crud...

}

@Entity
public class SoccerBall extend ball
{
    private int numberOfKicks;
     //...getter and setter crud...
}

@Entity
public class Trunk 
{

    private Set<Ball> balls;


     @OneToMany(mappedBy = "trunk", cascade = CascadeType.ALL, orphanRemoval = true)
     public Set<Ball> getBalls()
     {
          return balls;
     }

}
@Entity
public class Car
{
    private Trunk trunk;
    private String carModel;

    //...getter and setter crud...
}

現在我需要查詢有多少足球在一輛特定型號的賽車中有20次踢球。

使用JPA我嘗試做類似的事情:

    CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
    CriteriaQuery<Car> criteriaQuery = criteriaBuilder.createQuery(Car.class);
    Root<Car> car= criteriaQuery.from(Car.class);
    Join<Car, Trunk> trunkJoin = car.join(Car_.trunk);
    Join<Trunk, Ball> ballJoin = trunkJoin.join(Trunk_.Balls);
    criteriaQuery.select(trunk);
    Predicate [] restrictions = new Predicate[]{  criteriaBuiler.equal(car.get(carModel), "Civic"), criteriaBuilder.equal(ballJoin.get("numberOfKicks"), 20)};
    criteriaQuery.where(restrictions);
    TypedQuery<Car> typedQuery = entityManager.createQuery(criteriaQuery);
    Car carWithSoccerBalls = typedQuery.getSingleResult();

在運行時,上面的代碼會因為numberOfKicks僅在soccerball上而死,並且由於它在Trunk中輸入的方式,它只知道球。 如果我手動創建一個從足球和設置標准加入它我可以查詢numberOfKicks,但我覺得必須有一種方法來通知查詢該集實際上是一個集。

請注意我無法發布任何實際代碼,因此以上所有示例都只是示例。

像上面這樣使用JPA和hibernate是否有辦法強制hibernate知道set <ball>實際上是設置<soccerball>?

由於時間的限制,我正在采取簡單的方法:(。如果有人能夠更好地回答那么我有什么我會很樂意選擇他們的答案超過我的。

為了使條件api認識到我正在尋找繼承的表,我將查詢代碼更改為:

   CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
    CriteriaQuery<Car> criteriaQuery = criteriaBuilder.createQuery(Car.class);
    Root<Car> car= criteriaQuery.from(Car.class);
    Root<Soccerball> soccerballs = criteriaQuery.from(SoccerBall.class);
    Join<Car, Trunk> trunkJoin = car.join(Car_.trunk);
    Join<Trunk, Ball> ballJoin = trunkJoin.join(Trunk_.Balls);
    criteriaQuery.select(trunk);
    Predicate [] restrictions = new Predicate[]{  criteriaBuiler.equal(car.get(carModel), "Civic"), criteriaBuilder.equal(soccerball.get("numberOfKicks"),20), criteriaBuilder.equal(soccerball.get(SoccerBall_.id),car.get(Car_.id))};
    criteriaQuery.where(restrictions);
    TypedQuery<Car> typedQuery = entityManager.createQuery(criteriaQuery);
    Car carWithSoccerBalls = typedQuery.getSingleResult();

以下內容檢索具有嵌套列表屬性的所有Cars,這些屬性滿足集合中子類類型的相等條件和根元素上的相等性。 我已經修改了查詢以使用原始問題中的數據模型。

CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Car> carQuery = criteriaBuilder.createQuery(Car.class);
Root<Car> carRoot = carQuery.from(Car.class);

Subquery<SoccerBall> ballQuery = carQuery.subquery(SoccerBall.class);
Root<SoccerBall> soccerBall = ballQuery.from(SoccerBall.class);

ballQuery.select(soccerBall);
ballQuery.where(criteriaBuilder.equal(soccerBall.get(SoccerBall_.numberOfKicks), 25));

Join<Car, Trunk> carTrunkJoin = carRoot.join(Car_.trunk);
SetJoin<Trunk, Ball> trunkBallJoin = carTrunkJoin.join(Trunk_.balls);

carQuery.select(carRoot);
carQuery.where(criteriaBuilder.and(
    trunkBallJoin.in(ballQuery),
    criteriaBuilder.equal(carRoot.get(Car_.carModel), "Civic")));


TypedQuery<?> typedQuery = entityManager.createQuery(carQuery);
List<?> result = typedQuery.getResultList();

等效的SQL是:

SELECT * FROM car JOIN trunk JOIN ball WHERE ball.id IN (SELECT soccerball.id FROM soccerball WHERE soccerball.numberOfKicks = 25)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM