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

标准有一种方法可以返回发票列表以及该发票的总付款。

理论上,答案是您可以在投影查询中使用分组属性将结果分组为按发票支付的总金额。第二部分是您可以在 Invoice 上使用瞬态“totalPayment”值,并使用转换器选择投影到 Invoice 结构中。这比处理具有不同属性的 ArrayList 更容易,但取决于您需要将结果用于什么目的。

为了证明这一点,这里是一个小型 Invoice 类的重要部分:

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 并且你只击中了其中一​​个,它们都已加载。另一种解决方案可能是使用@MappedSuperclass 和更多子类。每个子类可能有不同的@Formula 字段。除了 DB 视图之外还有一个解决方案:Hibernate @Subselect。

于 2010-11-02T19:47:20.027 回答
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 回答