Syncing data between two processes with JPA and hibernate without refresh

I have two processes using the same entities in the same table. When I read the row from process A, then write from process B, then read again from process A, i get the value before the write of B.

I know that I can use entityManager.refresh(entity) on the entity after each find() operation to get the correct one, but since hibernate receives the updated value from the database even WITHOUT doing refresh(), I would like to ask: What other options do I have?

Here are the log lines with log level TRACE, starting with the line that shows hibernate receives the update value (en-US) from the database, and ending with the log line from my code showing that the entity has the old value (de-DE)
[18:32:52] [ForkJoinPool.commonPool-worker-2/TRACE] [org.hibernate.orm.jdbc.extract]: extracted value ([4] : [VARCHAR]) - [en-US]
[18:32:52] [ForkJoinPool.commonPool-worker-2/TRACE] [org.hibernate.orm.results.loading]: StandardRowReader#readRow
[18:32:52] [ForkJoinPool.commonPool-worker-2/TRACE] [org.hibernate.orm.results.loading.entity]: (o.h.s.r.g.e.i.EntityResultInitializer) Beginning Initializer#resolveKey process for entity : mypackage.SettingValueEntity(e)
[18:32:52] [ForkJoinPool.commonPool-worker-2/DEBUG] [org.hibernate.orm.results]: Extracted JDBC value [0] - [3]
[18:32:52] [ForkJoinPool.commonPool-worker-2/DEBUG] [org.hibernate.orm.results.loading.entity]: (EntityResultInitializer) Hydrated EntityKey (mypackage.SettingValueEntity(e)): 3
[18:32:52] [ForkJoinPool.commonPool-worker-2/TRACE] [org.hibernate.orm.results.loading.entity]: (o.h.s.r.g.e.i.EntityResultInitializer) Beginning Initializer#resolveInstance process for entity (mypackage.SettingValueEntity(e)) : 3
[18:32:52] [ForkJoinPool.commonPool-worker-2/DEBUG] [org.hibernate.orm.results]: Extracted JDBC value [2] - [LANGUAGE]
[18:32:52] [ForkJoinPool.commonPool-worker-2/TRACE] [org.hibernate.orm.results.loading.entity]: (o.h.s.r.g.e.i.EntitySelectFetchInitializer) Beginning Initializer#resolveInstance process for entity (mypackage.SettingValueEntity(e).setting) : LANGUAGE
[18:32:52] [ForkJoinPool.commonPool-worker-2/DEBUG] [org.hibernate.orm.results.loading]: Calling top-level assembler (0 / 1) : org.hibernate.sql.results.graph.entity.internal.EntityAssembler@27100cef
[18:32:52] [ForkJoinPool.commonPool-worker-2/TRACE] [org.hibernate.orm.results.loading]: StandardRowReader#afterRow
[18:32:52] [ForkJoinPool.commonPool-worker-2/TRACE] [org.hibernate.engine.internal.StatefulPersistenceContext]: Initializing non-lazy collections
[18:32:52] [Velocity - Task Executor #0/INFO] [com.velocitypowered.proxy.console.VelocityConsole]: SettingBasedLocaleService.loadLocale(df252223-4d16-4abc-a8cd-f7228a25fa88) => de-DE

It strongly depends on what you want to achieve. You can acquire a PESSIMISTIC_WRITE lock when invoking find() to ensure you have the latest state and no other process can change the state while your transaction runs. You can also use optimistic locking if it’s ok for you to rollback changes in case of conflicts.

Using an optimistic lock works, but since I only change the value from a single process, while the other process only reads the value and is only doing one read per transaction, it feels like there should be some “lighter” tool for the job.

If you tell me what these processes do exactly, maybe I can suggest something, but with the little information that you gave, this is the best I can say.

I want to store language settings for users. Process A has a UI for setting the language, and both process A and B read this language setting to get the translations for the user set language.

The basics work, however currently some part of Hibernate caches the stuff, so when changing the language using the UI in Process A, process B does not get the updated value on the next query, even though logging shows hibernate received the updated value from the database.

If you need more info, please ask a more specific question.

Hibernate ORM doesn’t just randomly cache stuff, it has well defined semantics. In a persistence context, an entity that was read from the database retains its in-memory state, unless you explicitly ask the EntityManager to refresh it. When you have a persistence context open for too long, then you might get this behavior, but usually, you should only keep it open for the length of a transaction, which should always be as short as possible.

If you enable second level or query caching, then Hibernate ORM will cache data in the configured cache. When that happens, Hibernate ORM in one JVM has no knowledge about changes done to the database by another JVM. This is a common “problem” that you could solve with either clustering, a short TTL or invalidating the second level or query cache when you know that a change happened.

That is probably the problem I have, I will investigate that at a later date. For now thanks for all the help.