1

在庫がゼロより大きいものをCriteriaBuilderすべて選択するクエリを作成しようとしています。Product在庫ありsum(DeliveryRow.amount) - sum(DispatchRow.amount)ます。どちらも当然の権利のみを含みますProduct

Subquery私は両方DeliveryRowを作成しようとしましDispatchRowたが、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 に関する調査を行っており、エンティティを取得するための 3 つの異なるアプローチ (NamedQueries、em.CreateQuery、および CriteriaBuilder) を研究しています。私の意見では、CriteriaBuilder は 3 つの中で最も使いにくいものです。この状況を処理するために 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 に答える