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

Fra*_*ois 98 java orm hibernate jpa hibernate-mapping

我的Java bean有一个childCount属性.此属性未映射到数据库列.相反,它应该由数据库计算,其COUNT()函数是在我的Java bean及其子代的连接上运行的.如果这个属性可以按需计算/"懒惰"会更好,但这不是强制性的.

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

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

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

Pas*_*ent 153

JPA不提供对派生属性的任何支持,因此您必须使用特定于提供者的扩展.正如您所提到的,@Formula在使用Hibernate时,这是完美的.您可以使用SQL片段:

@Formula("PRICE*1.155")
private float finalPrice;
Run Code Online (Sandbox Code Playgroud)

甚至是其他表上的复杂查询:

@Formula("(select min(o.creation_date) from Orders o where o.customer_id = id)")
private Date firstOrderDate;
Run Code Online (Sandbox Code Playgroud)

idid当前实体的.

以下博客文章值得一读:Hibernate派生属性 - 性能和可移植性.

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

也可以看看:

  • @NeilMcGuigan:``@ Formula``注释使用SQL,而不是HQL. (13认同)
  • 刚刚了解了在查询周围加上括号的重要性.始终以SQL异常结束,因为当加载主机对象时,此查询当然会成为子查询.MySQL不喜欢没有括号的内联选择. (7认同)

Vla*_*cea 46

本文所述,您有三种选择:

  • 要么是使用@Transient方法计算属性
  • 你也可以使用@PostLoad实体监听器
  • 或者您可以使用Hibernate特定的@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;
}
Run Code Online (Sandbox Code Playgroud)

对于更复杂的查询,您可以使用Hibernate @Formula,如本文所述:

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

  • 但是,这不允许更复杂的查询 (7认同)
  • 我更新了答案,现在您也可以获得更复杂查询的解决方案. (2认同)