My Java bean has a childCount property. This property is not mapped to a database column. Instead, it should be calculated by the database with a COUNT()
function operating on the join of my Java bean and its children. It would be even better if this property could be calculated on demand / \"lazily\", but this is not mandatory.
In the worst case scenario, I can set this bean\'s property with HQL or the Criteria API, but I would prefer not to.
The Hibernate @Formula
annotation may help, but I could barely find any documentation.
Any help greatly appreciated. Thanks.
JPA doesn\'t offer any support for derived property so you\'ll have to use a provider specific extension. As you mentioned, @Formula
is perfect for this when using Hibernate. You can use an SQL fragment:
@Formula(\"PRICE*1.155\")
private float finalPrice;
Or even complex queries on other tables:
@Formula(\"(select min(o.creation_date) from Orders o where o.customer_id = id)\")
private Date firstOrderDate;
Where id
is the id
of the current entity.
The following blog post is worth the read: Hibernate Derived Properties - Performance and Portability.
Without more details, I can\'t give a more precise answer but the above link should be helpful.
See also:
- Section 5.1.22. Column and formula elements (Hibernate Core documentation)
- Section 2.4.3.1. Formula (Hibernate Annotations documentation)
As explained in this article, you have three options:
- either you are calculating the attribute using a
@Transient
method
- you can also use
@PostLoad
entity listener
- or you can use the Hibernate specific
@Formula
annotation
While Hibernate allows you to use @Formula, with JPA, you can use the @PostLoad callback to populate a transient property with the result of some calculation:
@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;
}
For more complex queries, you can use the Hibernate @Formula
, as explained in this article:
@Formula(
\"round(\" +
\" (interestRate::numeric / 100) * \" +
\" cents * \" +
\" date_part(\'month\', age(now(), createdOn)\" +
\") \" +
\"/ 12) \" +
\"/ 100::numeric\")
private double interestDollars;