简体   繁体   English

解决多态子类属性jpa hibernate查询的标准

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

Using hibernate 3.6.10 with hibernate jpa 2.0. 使用hibernate 3.6.10和hibernate jpa 2.0。

My problem boils down to needing to set some criteria on a column of a child object during a somewhat complex joining query. 我的问题归结为需要在一个有点复杂的加入查询期间在子对象的列上设置一些标准。

I have a set of objects similar to: 我有一组类似于的对象:

@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...
}

Now i need to query how many soccer balls have 20 kicks in a car with a specific model. 现在我需要查询有多少足球在一辆特定型号的赛车中有20次踢球。

Using JPA I tried to do something like: 使用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();

At runtime the above code dies because numberOfKicks is only on soccerballs and due to how its typed in Trunk it only knows about ball. 在运行时,上面的代码会因为numberOfKicks仅在soccerball上而死,并且由于它在Trunk中输入的方式,它只知道球。 If i manually create a from on the soccerballs and setup criteria to join it i can query numberOfKicks, however i feel like there must be a way to inform the query that the set is in fact a set. 如果我手动创建一个从足球和设置标准加入它我可以查询numberOfKicks,但我觉得必须有一种方法来通知查询该集实际上是一个集。

Please note i cannot post any of the actual code so all above examples are just examples. 请注意我无法发布任何实际代码,因此以上所有示例都只是示例。

Using JPA and hibernate like above is there a way to force hibernate to know that the set< ball > is actually set< soccerball >? 像上面这样使用JPA和hibernate是否有办法强制hibernate知道set <ball>实际上是设置<soccerball>?

Due to time restrictions i'm taking the easy way out :(. If anyone can answer better then what i have i'll gladly choose their answer over mine. 由于时间的限制,我正在采取简单的方法:(。如果有人能够更好地回答那么我有什么我会很乐意选择他们的答案超过我的。

To make the criteria api recognize that i'm looking for the inherited table i changed my query code to be: 为了使条件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();

The following retrieves all Cars with nested list attributes satisfying equality criteria for subclass type in a collection and equality on root element. 以下内容检索具有嵌套列表属性的所有Cars,这些属性满足集合中子类类型的相等条件和根元素上的相等性。 I've modified the query to work with the datamodel in the original question. 我已经修改了查询以使用原始问题中的数据模型。

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();

The equivalent SQL is: 等效的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