这应该是一个我希望的简单。
我有发票,发票上有付款清单。
使用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行,其中包含所有发票的预计付款总额,这实际上是您所期望的,但这是我能够得到的。
非常感谢任何帮助。
答案 0 :(得分:3)
有一种方法可以让Criteria返回发票清单以及该发票的总付款。
理论上,答案是您可以在投影查询中使用分组属性,将结果分组为发票总付款。第二部分是您可以在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
答案 1 :(得分:1)
我很确定你无法在投影中返回实体。
有两种可能:
我没有测试过这个,但它应该是这样的:
select i, (select sum(p.amount) from InvoicePayments p where p.invoice = i.invoice) from Invoice i
将要等到明天,我有一个非常相似的数据结构在工作我应该能够测试它。
答案 2 :(得分: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。