L1 Cache object updating issue



I'm not an expert in Hibernate, but I don't believe you have to be one when it comes to this particular issue. The issue is that Hibernate L1 cache (session) does NOT update the cached object even though it gets retrieved from the database.

How to reproduce
This will cause a serious issue when entity relations come into the play. Suppose we have a Parent entity that relates to a Child entity with a one-to-many relationship. The parent with an id = 1 has 3 children, one of the children has an id = 1. If we queried the parent table to get the parent with the child of an id=1 as follows:
SELECT u from User u LEFT JOIN FETCH u.childrenList as s WHERE s.id = 1

We will get the parent entity with a childrenList of size = 1. So let's say within the same block of code we needed to get all the other children of the same parent. We will query the database with
SELECT u from User u LEFT JOIN FETCH u.childrenList WHERE u.id = :id

This will result of querying the database with the right query, and all the children of the parent will get retrieved from the database. However, once it reaches the L1 cache, the parent will not get updated and the childrenList will not change. This means we've lost the other children that should be added to the parent childrenList and stuck with the child of id = 1.

I don't actually get it. Why wouldn't the L1 cached entity get updated even though it got retrieved from the database.
I know that I can call entityManager.clear() as a work around for this issue. But why would I do this when we can solve the issue considering we know the root cause of the issue.




Stefan Möller
July 19, 2020, 1:34 AM

Not a solution but a simple workaround:
Instead of
SELECT u from User u LEFT JOIN FETCH u.childrenList as s WHERE s.id = 1
the query must be
SELECT u from User u LEFT JOIN u.childrenList as s JOIN FETCH u.childrenList WHERE s.id = 1

Christian Beikov
July 22, 2020, 6:54 AM

This is expected and is actually the reason why the ONclause is disallowed for fetch joins. Changing the elements of a collection through a filter condition changes the persistent state that Hibernate observes, so this kind of query might even lead to elements being deleted.

You should never use a filter condition on a join alias of a fetch joined collection or singular attribute reached through a fetch join of a collection.

You should use a custom projection without join fetching instead.




Omar Muhtaseb

Fix versions






Suitable for new contributors


Requires Release Note


Pull Request