How to Map Calculated Properties with JPA and Hibernate

How to map calculated properties with JPA and Hibernate

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)

JPA calculated field from other fields

Create a new method, e.g updateCalories() that calculates current calories from distance and speed. Call this method everytime when distance, speed or other relevant fields change (setters, constructor) or use entity listeners to automatically invoke the method when entity is created/updated (@PreUpdate, @PrePersist...)

Spring Data or plain JPA with dynamic calculated column

You can use:

1) @PostLoad annotation to make custom calculation of your transient property on application level:

@PostLoad
public void calculateDistance() {
this.distance = ...;
}

2) @Formula annotation to make calculation on database level (using your native SQL dialect):

@Formula(value = "...") // your calculation here in native SQL
private BigDecimal distance;

(@Transient annotation must be excluded in this case.)

JPA: how can i map a property to a derived column that is based on a COUNT from other tables (Without incurring in n+1 select problems?)

Using @Formula would not cause any N+1 select problem (different to @PostLoad), since the specified expression is evaluated as part of the initial select query.

(Infact, you would need to enable Hibernates byte code enhancement to be able to lazy-load the calculated @Formula property: Controlling lazy/eager loading of @Formula columns dynamically )

So even though it is a Hibernate-specific feature which needs native SQL, @Formula is probably a good and simple way to realize this.

In case the performance drawback of the correlated subquery gets significant and there are cases when the calculated property is not needed, you might additionally create a DTO projection only containing needed properties.



Related Topics



Leave a reply



Submit