简体   繁体   中英

JPA/Hibernate Query Returns Stale Results

I am using an EXTENDED Persistent Context because it will allow me to Lazily Load a one-many relationship on an object and it also won't require a SELECT before I "merge" an object with the persistent context.

I have an DummyObject with:

  1. A "Last Updated" Date Field

  2. A One-Many Relationship

This Object is being updated every 5 seconds in one JVM through a em.merge(DummyObject) call.

In another JVM, I query for the DummyObject doing a call like the following

em.createQuery("from DummyObject").getResultList();  

I am also doing this Query every 5 seconds.

The problem is, is that the Objects resulted from the Query all have a Timestamp of the very first Query after successive calls, even though Hibernate is generating the correct SQL statement (when I have statement logging on), and the Database is getting the updates correctly (I have verified).

I have also tried all sorts of optimistic locking with @Version to no avail. (See comments)

Another thing is that this does work correctly when:

  1. I change the PersistentContextType to TRANSACTIONAL (something that will not allow me to lazily load the ONE-MANY relationship)

  2. I do an EntityManager.clear() call before I do the Query above (Something that will also not allow me to lazily load the ONE-MANY relationship).

Why does my Query return stale data? I have no Second Level Caching or Query Caching enabled.

Am I doing something wrong? Is there something I can set through query.setHint(, )?

Maybe I don't understand " EXTENDED " vs TRANSACTIONAL correctly.

The hibernate session is caching the persistent objects. So because you are modifying in one JVM (A) and reading in another JVM(B), B's sessions needs to be refreshed to see the changes. You could open a new session or evict/refresh the persistent objects. You can also replicate the sessions across both JVMs which might take care of your problem. Or you could try changing the query to only return pieces of the 'DummyObject' which you need and only read the persistent object when it is required. You might also try a stateless session.

Have you tried doing a flush() before your fetch?

Interesting. To me it seems that the entity instance in your persistence context is not updated with the results from the query. This might be by design - you could accidentally overwrite local changes by executing a query.

What's worse is that there is no way in JPA to detach a single instance. You either clear the entire context or you don't. So that is not a possible solution either.

There is a refresh() method available in the PersistanceContext class that grabs changes from the database and updates the entity instance accordingly. But I can see how that might not be applicable in an actual implementation. So my answer turns out to be: you probably can't get it to work.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM