JPA规范和Join一起使用

时间:2019-07-08 19:12:38

标签: hibernate jpa spring-data-jpa jpa-2.0 jpa-2.1

我有一个实体叫单位,另外一个叫PriceElement

其中

@Entity
public class Unit {

  //

  @OneToMany(mappedBy = "unit", cascade = CascadeType.ALL, orphanRemoval = true)
  private Set<PriceElement> priceElements;

}

@Entity
public class PriceElement {

  //

  private Integer total; 

  @ManyToOne(fetch = FetchType.LAZY)
  @JoinColumn(name = "unit_Id")
  private Unit unit;

}

我想过滤在特定范围内其priceElements的总属性之和的单位

1 个答案:

答案 0 :(得分:1)

您可以尝试使用子查询进行过滤,如下所示:

//Initialize criteriaBuider and CriteriaQuery
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Unit> cq = cb.createQuery(Unit.class);

//Define Query
Root<Unit> rootUnit = cq.from(Unit.class);

//Create Subquery to get the sum
Subquery<Integer> sqSum = cq.subquery(Integer.class);
Root<PriceElement> rootSQPrice = sqSum .from(PriceElement.class);
Join<PriceElement,Unit> joinSQUnit = rootSQPrice.join(PriceElement_.unit);

//Set the condition, the unit of the subquery is the same as the unit of the main query
sqSum.where(cb.equals(joinSQUnit.get(Unit_.id),rootUnit .get(Unit_.id)))

//Set te result of the subquery as sum of totals
sqSum.select(cb.sum(rootSQPrice.get(PriceElement_.total)));

//Add the result of the subquery in query where clause
cq.where(cb.between(sqSum,Range0,Range1));

cq.select(rootUnit);

另一个选项(仅在JPA 2.1中是在内部join子句中添加子查询的条件)

Root<Unit> rootUnit = cq.from(Unit.class);
Join<Unit,PriceElement> joinPrice = rootUnit.join(Unit_.priceElements);
//Id condition is implicit in the initialization of the join, add between condition
joinPrice.on(cb.and(cb.between(sqSum,Range0,Range1)))