Query with JPA without using caching

Hey guys,

I have implemented a generic in my project for queries and using JPA with Hibernate.
In the configuration of persistence is already without using the cache, but it is not working.

For example: there are two systems operating in parallel and they both manipulate a database table, but when I look up a record in one system and this same record was later changed on the other system, when I look at the record again it is not updated, as if it was coming from the cache, however I need the screen to return the record updated in the query.

I’ve already used the entitymanager clear, but this affects other open system windows.
I also used refresh on the object, it even worked, the bad thing is that the query returns a “list” and that forces me to create a “for” to update all the results.

Does anyone have a solution to solve, which was in the query itself, in the “criteria” or “resultlist” in the JPA?

Thanks!!

You are not seeing the updates of other transactions in your object because of the I in ACID meaning that your transaction is isolated. I don’t know what kind of application you are developing, but it seems to me that this is some kind of fat-client i.e. Swing/AWT or JavaFX application. If you loaded a list of objects, the objects get into the first-level cache of Hibernate which is necessary for automatic flushing within a transaction. It seems though, that what you want is to not write back results, so it would be best to end the transaction and close the Hibernate Session right after loading. This way, when you query the list again, you will see the current state of the database at that point in time.

Hi @beikov

Exactly, I am using JPA+hibernate with JavaFX application.
I created a generic class for querying with JPA/Hibernate and implemented the query methods in it with a resultlist or singleresult.
I found an example of setHint in the Query resultlist in some forums, but it didn’t work.
How could I do this Hibernate session release in my query?
For the queries I’m using the Criteria from javax.persistence.criteria
Connection and pool settings are in persistence.xml

Thanks!

I have no idea how your code looks like, but usually, the lifecycle of objects is handled by a dependency injection container. You can implement this yourself though:

EntityManager em = sessionFactory.createEntityManager();
EntityTransaction tx = em.getTransaction();
boolean success = false;
try {
  tx.begin();
  List l = em.createQuery("..").getResultList();
  success = true;
  return l;
} finally {
  try {
    if (success) {
      tx.commit();
    } else {
      tx.rollback();
    }
  } finally {
    em.close();
  }
}

If this is really just a read only query, you can omit the transaction stuff.

I don’t speak Spanish, so I can’t help you any further.

It would be like using the Entity Manager calling the .clear() method?
This call has an effect on other windows open in the application, with data already loaded. These appear as unmanageable, requiring object refresh to use the data.

Loading data in a separate transaction and entity manager will make these entities detached as soon as the entity manager is closed, so I guess you could say it is similar to calling clear, yes.
I don’t know how your application architecture looks like, but if your application requires entity instances to be attached all the time, you will have to use EntityManager#refresh in order to see the updates done by another application to the underlying database state. If you can live entity instances being “replaced” you could detach all the entity of a previous list, then run a query and return this new list of objects.

I understood…
but in the application logic, I no longer have access to the array with the data to put them as detached.
Is there any way for me to do the query without going through the cache, for hibernate to go straight to the database?
I found in some research, using the properties of hibernate in the query, but I was not successful with this logic:

return entityManager.createQuery(query)
                 .setHint("org.hibernate.cacheable", false)
                 .setHint("javax.persistence.cache.storeMode", "REFRESH")
                 .resultList as MutableList<out Any>?

These properties control the second level and query cache, so they won’t help you.
I don’t know what else to tell you. If you don’t have “access” to these objects anymore, why can’t you use EntityManager.clear() to detach all entities? Or simply detach the entities you don’t need anymore right after querying.