问题
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.
回答1:
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)
回答2:
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;
回答3:
Take a look at Blaze-Persistence Entity Views which works on top of JPA and provides first class DTO support. You can project anything to attributes within Entity Views and it will even reuse existing join nodes for associations if possible.
Here is an example mapping
@EntityView(Order.class)
interface OrderSummary {
Integer getId();
@Mapping("SUM(orderPositions.price * orderPositions.amount * orderPositions.tax)")
BigDecimal getOrderAmount();
@Mapping("COUNT(orderPositions)")
Long getItemCount();
}
Fetching this will generate a JPQL/HQL query similar to this
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
Here is a blog post about custom subquery providers which might be interesting to you as well: https://blazebit.com/blog/2017/entity-view-mapping-subqueries.html
回答4:
i have tried this on my code
@Formula(value = "(select DATEDIFF(expiry_date,issue_date) from document_storage)")
private String myColumn;
the errors i get when i run and display my view even before trying to display the column on mustache is something like this
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)
the question i asked was is there a way to get values of Calculated column using JPA / Hibernate with mySQL?
what am i doing wrong ?
来源:https://stackoverflow.com/questions/61312395/is-there-a-way-to-get-values-of-calculated-column-using-jpa-hibernate-with-mys