Answers:
JPA不提供对派生属性的任何支持,因此您必须使用提供程序特定的扩展。如您所述,@Formula
使用Hibernate时非常适合此操作。您可以使用一个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。
没有更多详细信息,我无法给出更准确的答案,但是以上链接应该会有所帮助。
@Formula
注释使用SQL,而不是HQL。
如本文所述,您有三个选择:
@Transient
方法计算属性@PostLoad
实体侦听器@Formula
注释虽然Hibernate允许您将@Formula与JPA 一起使用,但是您可以使用@PostLoad回调函数通过一些计算结果填充瞬态属性:
@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;
看一下在JPA之上工作并提供一流DTO支持的Blaze-Persistence实体视图。您可以将任何项目投影到实体视图中的属性,并且如果可能的话,它甚至可以将现有的联接节点重新用于关联。
这是一个示例映射
@EntityView(Order.class)
interface OrderSummary {
Integer getId();
@Mapping("SUM(orderPositions.price * orderPositions.amount * orderPositions.tax)")
BigDecimal getOrderAmount();
@Mapping("COUNT(orderPositions)")
Long getItemCount();
}
提取此内容将生成与此类似的JPQL / HQL查询
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
这是有关自定义子查询提供程序的博客帖子,您可能也会对此感兴趣:https://blazebit.com/blog/2017/entity-view-mapping-subqueries.html
我已经在我的代码上尝试过
@Formula(value = "(select DATEDIFF(expiry_date,issue_date) from document_storage)")
private String myColumn;
在运行并显示我的视图时甚至在尝试在小胡子上显示列时出现的错误是这样的
java.lang.NullPointerException
at java.base/java.lang.String$CaseInsensitiveComparator.compare(String.java:1241)
at java.base/java.lang.String$CaseInsensitiveComparator.compare(String.java:1235)
at java.base/java.util.TreeMap.getEntryUsingComparator(TreeMap.java:374)
at java.base/java.util.TreeMap.getEntry(TreeMap.java:343)
at java.base/java.util.TreeMap.get(TreeMap.java:277)
at com.mysql.cj.result.DefaultColumnDefinition.findColumn(DefaultColumnDefinition.java:182)
我问的问题是有没有办法使用JPA / Hibernate和mySQL获取Calculated列的值?
我究竟做错了什么 ?