1

我正在尝试创建一个查询,CriteriaBuilder用于选择所有Product股票大于零的股票。库存是sum(DeliveryRow.amount) - sum(DispatchRow.amount)。两者当然只包含正确的Product

我已经尝试Subquery为两者创建DeliveryRowDispatchRow虽然我觉得这应该使用join().

课程

Product { 
    (...)
}

DeliveryRow {
    @ManyToOne
    private Product product;

    private int amount;
}

DispatchRow {
    @ManyToOne
    private Product product;

    private int amount;
}

询问

在这个查询中,我不确定如何处理xxx. 我尝试过创建子查询,但没有成功。

CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Product> query = cb.createQuery(Product.class);
Root product = query.from(Product.class);
query.select(product);

// sum of DeliveryRow.amount where DeliveryRow.product = Product
// minus 
// sum of DispatchRow.amount where DispatchRow.product = Product
Expression stock = xxx;  

query.where(cb.gt(stock, Integer.parseInt(0)));
return em.createQuery(query).getResultList();

关于如何解决这个问题的任何建议?

4

1 回答 1

1

我最近一直在研究 JPA/JPQL,研究检索实体的三种不同方法:NamedQueries、em.CreateQuery 和 CriteriaBuilder。在我看来,CriteriaBuilder 是三者中最难使用的。我建议创建一个 NamedQuery 来处理这种情况,它会更容易实现和阅读。

使用此 JPQL 表达式,您可以检索库存大于零的所有产品:

SELECT p.name, SUM(delRow.amount) - SUM(disRow.amount) 
FROM Product p join p.deliveryRows delRow join p.dispatchRows disRow
HAVING SUM(delRow.amount) - SUM(disRow.amount) > 0

/* This assumes product has a Collection<DispatchRow> named dispatchRows 
   and a Collection<DeliveryRow> named deliveryRows.
*/

将此作为“产品”实体中的命名查询

//This should be concatenated or on one line
@NamedQuery(name="Product.hasStock" 
    query="SELECT p.name, SUM(delRow.amount) - SUM(disRow.amount) 
    FROM Product p join p.deliveryRows delRow join p.dispatchRows disRow
    HAVING SUM(delRow.amount) - SUM(disRow.amount) > 0");

然后使用EntityManager

@PersistenceContext
EntityManager em;

public void execute(){
  List<Object[]> products = 
      em.createNamedQuery("Product.hasStock").getResultList();

  /* Projections return a List<Object[]> where position 1 in the object array
     corresponds with the first field in the select statement, position two
     corresponds with the second field and so on...  These can also be strongly typed
     if an object is created and the constructor is specified in JPQL statement
  */
}

我知道这是与使用 Criteria API 不同的方法,但在我看来 JPQL 查询远远优于 Criteria API。与与 SQL 非常相似的 JPQL 语法相比,API 感觉不那么简洁和直观。如果您决定采用这条路线,我创建了一个视频教程,演示@NamedQueries并展示了如何对包含投影的查询结果进行强类型化。可以在这里找到。

于 2013-05-11T15:33:38.360 回答