我的Java Bean有一个childCount属性。这个属性没有映射到数据库列,相反,应该使用COUNT()
函数在Java Bean和其子节点的连接上进行计算,由数据库来计算。如果可以按需/“懒惰”方式计算此属性会更好,但这不是必须的。
在最坏的情况下,我可以使用HQL或Criteria API设置此Bean的属性,但我希望不要这样做。
Hibernate的@Formula
注释可能有所帮助,但我几乎找不到任何文档。
非常感谢您的帮助。谢谢。
我的Java Bean有一个childCount属性。这个属性没有映射到数据库列,相反,应该使用COUNT()
函数在Java Bean和其子节点的连接上进行计算,由数据库来计算。如果可以按需/“懒惰”方式计算此属性会更好,但这不是必须的。
在最坏的情况下,我可以使用HQL或Criteria API设置此Bean的属性,但我希望不要这样做。
Hibernate的@Formula
注释可能有所帮助,但我几乎找不到任何文档。
非常感谢您的帮助。谢谢。
JPA不支持派生属性,因此您需要使用提供程序特定的扩展。如您所述,当使用Hibernate时,@Formula
非常适合此用途。您可以使用SQL片段:
@Formula("PRICE*1.155")
private float finalPrice;
甚至可以对其他表进行复杂的查询:
@Formula("(select min(o.creation_date) from Orders o where o.customer_id = id)")
private Date firstOrderDate;
其中id
是当前实体的id
。
推荐阅读以下博客文章:Hibernate Derived Properties - Performance and Portability。
没有更多细节,我无法给出更精确的答案,但上面的链接应该会有所帮助。
你有三个选择:
@Transient
方法计算属性。@PostLoad
实体监听器。@Formula
注释。Hibernate允许你使用@Formula,而在JPA中,你可以使用@PostLoad回调来用某些计算结果填充一个transient属性:
@Column(name = "price")
private Double price;
@Column(name = "tax_percentage")
private Double taxes;
@Transient
private Double priceWithTaxes;
@PostLoad
private void onLoad() {
this.priceWithTaxes = price * taxes;
}
因此,您可以像这样使用 Hibernate @Formula
:
@Formula("""
round(
(interestRate::numeric / 100) *
cents *
date_part('month', age(now(), createdOn)
)
/ 12)
/ 100::numeric
""")
private double interestDollars;
@EntityView(Order.class)
interface OrderSummary {
Integer getId();
@Mapping("SUM(orderPositions.price * orderPositions.amount * orderPositions.tax)")
BigDecimal getOrderAmount();
@Mapping("COUNT(orderPositions)")
Long getItemCount();
}
SELECT
o.id,
SUM(p.price * p.amount * p.tax),
COUNT(p.id)
FROM
Order o
LEFT JOIN
o.orderPositions p
GROUP BY
o.id