1

これは私が望む単純なものでなければなりません。

請求書があり、その請求書には支払いのリストが含まれています。

Criteria API を使用して、請求書とその支払い合計のリストを返そうとしています。したがって、SQLでは次のようなものが必要です。

SELECT i.*, (SELECT SUM(PMT_AMOUNT) FROM INVOICE_PAYMENTS p WHERE p.INVOICE = i.INVOICE) FROM INVOICES i

Criteria API を使用してこれを達成する方法を理解することはできません。次のようなことをします:

Criteria crit = session.createCriteria(Invoice.class)
criteria.setProjection(Projections.projectionList()
          .add(Projections.sum("payements.paymentAmount").as("paymentTotal"))

単純に、すべての請求書の予想支払い合計を含む 1 行を返します。これは実際には予想どおりですが、これは私が得ることができる限り近いものです。

どんな助けでも大歓迎です。

4

3 に答える 3

3

Criteriaには、請求書のリストとその請求書の合計支払い額を返す方法があります。

理論的には、その答えは、予測クエリでグループ化プロパティを使用して、結果を請求書ごとの合計支払いにグループ化できるということです。2番目の部分は、請求書で一時的な「totalPayment」値を使用し、トランスフォーマーを使用して請求書構造への投影を選択できることです。これは、さまざまなプロパティのArrayListを処理するよりも簡単ですが、結果を何に使用する必要があるかによって異なります。

これを実証するために、小さな請求書クラスの重要な部分を次に示します。

public class Invoice{
   private String name;

   @Transient private int totalPayments;
   @OneToMany Set<Payment> payments = new HashSet<Payment>();

   // getters and setters
...
}

次に、これはあなたが使用できる基準です

Criteria criteria = session.createCriteria(Invoice.class)
            .createAlias("payments", "pay")
            .setProjection(Projections.projectionList()
                .add(Projections.groupProperty("id"))
                .add(Projections.property("id"), "id")
                .add(Projections.property("name"), "name")
                .add(Projections.sum("pay.total").as("totalPayments")))
            .setResultTransformer(Transformers.aliasToBean(Invoice.class));

List<Invoice> projected = criteria.list();

そしてこれは生成されるSQLです

Hibernate: 
   select this_.id as y0_, 
          this_.id as y1_, 
          this_.name as y2_, 
          sum(pay1_.total) as y3_ 
   from invoice this_ 
   inner join invoice_payment payments3_ on this_.id=payments3_.invoice_id 
   inner join payment pay1_ on payments3_.payments_id=pay1_.id 
   group by this_.id
于 2009-11-14T20:36:58.293 に答える
1

フィールドに @Formula を使用することもできtotalPaymentsます。欠点は、エンティティをロードするたびに「合計」が計算されることです。したがって、LAZY @Formula を使用することができます - ビルド時間の拡張または Pawel Kepka のトリック: http://justonjava.blogspot.com/2010/09/lazy-one-to-one-and-one-to-many.htmlつまり、より多くの LAZY @Fromula があり、そのうちの 1 つだけをヒットすると、すべてがロードされます。別の解決策は、 @MappedSuperclass とその他のサブクラスを使用することです。各サブクラスには、異なる @Formula フィールドがある場合があります。DB ビュー以外のもう 1 つのソリューション: Hibernate @Subselect です。

于 2010-11-02T19:47:20.027 に答える
1

プロジェクションでエンティティを返すことはできないと確信しています。

次の 2 つの可能性があります。

  • 2 つの条件クエリを実行します。1 つは実際の請求書用、もう 1 つは合計用です。
  • HQL を使用してクエリを実行する

私はこれをテストしていませんが、次のようになります。

select i, (select sum(p.amount) from InvoicePayments p where p.invoice = i.invoice) from Invoice i 

明日まで待つ必要があります。私は非常によく似たデータ構造を持っているので、それをテストできるはずです。

于 2009-10-14T20:23:09.950 に答える