Hibernate Tips: Cache preprocessed, non-persistent attributes

By Thorben Janssen

Mapping

Hibernate Tips is a series of posts in which I describe a quick and easy solution for common Hibernate questions. If you have a question you like me to answer, please leave a comment below.

Question:

I often need to provide a value that gets calculated based on an entity attribute, like the age of a person. How can I cache this calculated attribute in the entity without storing it in the database?

Solution:

There are different ways to provide a calculated value to the user of the entity:

  1. You can use a @Formula to provide an SQL expression which returns the value.
  2. You can use field access and calculate the value in a getter method.
  3. You can use a transient entity attribute which stores calculated value without persisting it in the database.

I already explained option 1 in a previous post and will, therefore, focus on option 2 and 3.

Calculate in a getter method

Option 2 is easy to implement. When you use field access, you can add additional getter methods to your entity. You can for example, add a getAge() method that calculates and returns the age of the Author.

This approach requires you to calculate the value for each call of the getAget() method and is, therefore, not a good solution for complex calculations.

Transient entity attributes

The transient attribute approach requires a little more code but allows you to store the calculated value in an entity attribute without persisting it. The @Transient annotation tells Hibernate, and any other JPA implementation, to ignore the attribute when writing or reading the entity. You can, therefore, use it in your getAge() method to store the calculation result after it was calculated. This can be useful, if you need to perform a complex calculation that you don’t want to repeat for each call.

Learn more

You can also use @ColumnTransformer and AttributeConverter if you want to replace the presentation of an attribute.
 

Hibernate Tips Book


Get more recipes like this one in my new book Hibernate Tips: More than 70 solutions to common Hibernate problems.

It gives you more than 70 ready-to-use recipes for topics like basic and advanced mappings, logging, Java 8 support, caching and statically and dynamically defined queries.

Get it now as a paperback, ebook or PDF.


Tags

Mapping


About the author

Thorben is an independent consultant, international speaker, and trainer specialized in solving Java persistence problems with JPA and Hibernate.
He is also the author of Amazon’s bestselling book Hibernate Tips - More than 70 solutions to common Hibernate problems.

Books and Courses

Coaching and Consulting

Leave a Repl​​​​​y

Your email address will not be published. Required fields are marked

This site uses Akismet to reduce spam. Learn how your comment data is processed.

  1. Trying to use option 3 with object that is query-cached. It seems that each time the object is retrieved, a new object (different object ID) is generated so the transient field has to be recomputed. My computation is expensive. Is there anyway to have the query cache deliver the same object rather than creating a new one?

    1. No, you can’t avoid that.
      Hibernate stores entities in the dehydrated form (only attribute values, no entity instance) always instantiates a new entity object.

  2. Better than calculating on the getter method, I prefer to use a @PostLoad to do this kind of computation, leaving my getters clean.

    1. That’s also an option. But you need to be aware, that the value will not be available for newly created entities. It depends on the use case, if that’s an issues or not.

{"email":"Email address invalid","url":"Website address invalid","required":"Required field missing"}