Disturbing use case in a read commited transaction

I recently came across a disturbing use case, could someone explain to me what’s happening ?

  1. i start a transaction, isolation =default (read commited, i’m using postgres)
  2. i fetch an entity from my database with : Book book = entityManager.createQuery(“from Book where name=‘A’”, Book.class).getSingleResult();
  3. i pause the current thread, and update the book in my database to set the name ‘B’ instead of ‘A’ in another thread / commited transaction
  4. back to my first thread, i fetch again the entity from my database but using this query : Book book2 = entityManager.createQuery(“from Book where name=‘B’”, Book.class).getSingleResult();
  5. A request to the database is issued, and it indeed return a book BUT the resulting entity book2 is NOT updated, its name is still ‘A’

Any idea why hibernate won’t update his entity in his session even after retrieving it from the database ? Even if this is a read commited isolation, to me the ending result looks like…if i were in a repeatable read isolation situation !

Thanks for your help

The problem is that an entity with the same identifier is already associated with your persistence context. So when you query an entity and that it contained in the persistence context, you will receive that entity. Hibernate can’t alter the state of that existing entity as a result of executing a query. If you want to actually refresh the state of the entity, you need to use entityManager.refresh(book2). If you just want the new state without refreshing the entity, you will have to use a scalar query. Maybe Blaze-Persistence Entity-Views can help you here if you need more state in a structured form.

Thanks for your answer ! Would you have any insights on why Hibernate can’t alter the state of an existing entity (and hence, its stored snapshot) ?
if it looks weird in my particular use case, i’m sure it makes sens globally speaking.
Thanks for your answer

That’s just how it is. IMO it is unnatural if the entity could change at any time when querying something. The main goal of Hibernate is to synchronize the entity state to the database state. The only method for synchronizing the state of the database back to entities is through EntityManager.refresh.

Ok, to me it feels unnatural to set transaction isolation to read commited and have repeatable read isolation as a result. But i understand your point of view.
Thanks for your time !

You can join us on Zulip and start a discussion about this with the other developers though: https://hibernate.zulipchat.com/#narrow/stream/132096-hibernate-user