如何使用JPA和Hibernate映射计算的属性

时间:2010-06-06 23:14:23

标签: java hibernate jpa orm hibernate-mapping

我的Java bean有一个childCount属性。此属性未映射到数据库列。相反,应该由数据库计算,并使用COUNT()函数对我的Java bean及其子代的连接进行操作。如果这个属性可以按需计算/“懒惰”,那就更好了,但这不是强制性的。

在最糟糕的情况下,我可以使用HQL或Criteria API设置此bean的属性,但我不愿意。

Hibernate @Formula注释可能会有所帮助,但我几乎找不到任何文档。

任何帮助非常感谢。感谢。

4 个答案:

答案 0 :(得分:150)

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

如果没有更多细节,我无法给出更准确的答案,但上述链接应该会有所帮助。

另见:

答案 1 :(得分:41)

正如this article中所述,您有三种选择:

  • 要么使用@Transient方法计算属性
  • 您还可以使用@PostLoad实体监听器
  • 或者您可以使用特定于Hibernate的@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,如this article中所述:

@Formula(
    "round(" +
    "   (interestRate::numeric / 100) * " +
    "   cents * " +
    "   date_part('month', age(now(), createdOn)" +
    ") " +
    "/ 12) " +
    "/ 100::numeric")
private double interestDollars;

答案 2 :(得分:1)

看看enter image description here,它在JPA之上起作用,并提供一流的DTO支持。您可以将任何项目投影到实体视图中的属性,并且如果可能的话,甚至可以将现有的联接节点重用于关联。

这是示例映射

@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

以下是有关自定义子查询提供程序的博客文章,您可能也会对此感兴趣:Blaze-Persistence Entity Views

答案 3 :(得分:0)

我已经在我的代码上尝试过

 @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)

我问的问题是is there a way to get values of Calculated column using JPA / Hibernate with mySQL?

我在做什么错了?