-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 7 posts ] 
Author Message
 Post subject: HQL/JPQL and session cache
PostPosted: Mon Apr 07, 2014 10:46 am 
Newbie

Joined: Mon Apr 07, 2014 10:20 am
Posts: 12
I am using Hibernate 4.3.4 and running into an issue where HQL returns stale data due to the session cache. This problem can be illustrated in the following (simple) scenario:
Code:
Entity: Employee (name PK, emp_type)
    name            emp_type
    John Doe        'C'
    Jane Doe        'P'

Start hibernate transaction:
    1. Run HQL: "SELECT e FROM Employee e WHERE e.name = 'John Doe'"
    2. Run query: "UPDATE employee SET emp_type = 'F' where name = 'John Doe'"
    3. Run HQL: "SELECT e FROM Employee e WHERE e.employeeType = 'F'"


This is just a contrived example of the scenario, but illustrates the problem.

- Step 1 hits the database and hydrates an entity for the 'John Doe' employee record.
- Step 2 is simply illustrating some transaction committing a change to the state of the database (and not necessarily in the current Hibernate transaction).
- Step 3 again hits the database and does return the John Doe entity (since it has been updated to emp_type = 'F'); however, calling employee.getType() will return the original 'C' value and not the updated 'F' value. This is due to the session cache returning the entity that was hydrated in step 1. This seems to contradict the documentation here:

http://docs.jboss.org/hibernate/orm/4.3/manual/en-US/html/ch11.html
Quote:
However, Hibernate does guarantee that the Query.list(..) will never return stale or incorrect data.


Obviously, I can simply call "refresh" on the entity but that is not a good solution when the HQL actually results in several hundred rows. Is this a bug or is stale data defined differently than I assume?

The most efficient method I can think of to perform a bulk read/refresh is to do something like this:
Code:
    Query = ...
    List entities = Query.list();
    for (Entity entity : entities) {
        session.evict(entity);
    }
    entities = Query.list();


This requires two queries rather than one which is still far better than performing a refresh on several hundred entities. Unfortunately, this has the potential to leave evicted entities associated with existing objects which can obviously cause its own problems.

Anyway, my core questions are - is there something I'm missing here? Would this be considered a bug or is there some switch/hint I can utilize with which to ask Hibernate to rehydrate these cached entities for me?


Top
 Profile  
 
 Post subject: Re: HQL/JPQL and session cache
PostPosted: Mon Apr 14, 2014 10:44 am 
Newbie

Joined: Mon Apr 07, 2014 10:20 am
Posts: 12
Just bumping for one last check to see if anybody knows if this would be considered a bug, expected behavior (which would seem to contradict documentation?), or if some method of changing the behavior exists?


Top
 Profile  
 
 Post subject: Re: HQL/JPQL and session cache
PostPosted: Mon Apr 14, 2014 11:25 am 
Newbie

Joined: Mon Apr 14, 2014 11:03 am
Posts: 8
Location: Orlando, FL
I'm assuming the second step is a SQL update. Hibernate is oblivious to changes on the underlying data. It has no way of knowing that it changed.

Calling org.hibernate.Session.refresh(Object) is your best bet.


Top
 Profile  
 
 Post subject: Re: HQL/JPQL and session cache
PostPosted: Mon Apr 14, 2014 1:16 pm 
Newbie

Joined: Mon Apr 07, 2014 10:20 am
Posts: 12
ryan2049 wrote:
I'm assuming the second step is a SQL update. Hibernate is oblivious to changes on the underlying data. It has no way of knowing that it changed.


Thanks for the response!

The second step is simply illustrating a change to the underlying database (either via a native query or some other transaction). I do understand how the session cache works; however, Hibernate isn't completely oblivious to the changes else it wouldn't locate the "John Doe" record in the last query.

From what I can tell, Hibernate executes the query directly against the database and gets all records back. However, when it goes to then create entities for the results set, it first checks to see if each record exists in the session cache. If so, it simply returns the cached entity. Since it has a results set for these entities, it seems like it should "re-hydrate" them. Unfortunately, it does not seem to do this causing it to return stale data.

This (seems to) contradict the documentation I linked above: "However, Hibernate does guarantee that the Query.list(..) will never return stale or incorrect data."

This is why I was asking if it this would be a bug or if there is some Hibernate configuration I may have incorrect.


Top
 Profile  
 
 Post subject: Re: HQL/JPQL and session cache
PostPosted: Mon Apr 14, 2014 8:32 pm 
Newbie

Joined: Mon Apr 14, 2014 11:03 am
Posts: 8
Location: Orlando, FL
Quote:
Except when you explicitly flush(), there are absolutely no guarantees about when the Session executes the JDBC calls, only the order in which they are executed. However, Hibernate does guarantee that the Query.list(..) will never return stale or incorrect data.


That statement is based off the concept that any persistence operations you perform aren't committed until a flush is performed. By default the flush strategy is set to FlushModeType.COMMIT and that is what gets executed whenever the query is performed. This would typically recognize the changes that Hibernate is waiting to commit to the database and refresh the dirty fields in question. However, in your case you have probably updated the value without Hibernate's knowledge.

I believe you are correct in that it returns the row because it queried for it and then it pulled what it had from cache because it wasn't notified of the change.

I'm not sure that it's a bug so much as it's a limitation. I'm not an expert, but this is my understanding of how it works.

Does the refresh method on that specific object really fire off that many additional queries?


Top
 Profile  
 
 Post subject: Re: HQL/JPQL and session cache
PostPosted: Mon Apr 14, 2014 10:18 pm 
Newbie

Joined: Mon Apr 07, 2014 10:20 am
Posts: 12
Quote:
I'm not sure that it's a bug so much as it's a limitation. I'm not an expert, but this is my understanding of how it works.


Yeah, I'm no expert either which is why I asked! :) Either way, it seems like a pretty big limitation for such a popular ORM to not allow a bulk refresh in a session like this.

Quote:
Does the refresh method on that specific object really fire off that many additional queries?


In my actual program it's not a single specific object. It's potentially hundreds of records in the returned results set. Calling a refresh on every single one would be a massive performance killer.

For now I'm just retrieving the results for certain objects via native SQL calls and mapping the result set to the objects manually. It would be nice if I could actually turn these objects into mapped entities which would allow for HQL joins, but that would require being able to ask Hibernate to NOT use the session cache for these objects (it's specific tables that are frequently updated by multiple components/processes throughout the system and I absolutely need non-stale data on demand) or at least to allow me to force a bulk refresh on demand.

Anyway, thanks for the assistance. Your interpretation on that documentation may very well be correct. I guess I'll chalk it up to a limitation in the ORM framework.


Top
 Profile  
 
 Post subject: Re: HQL/JPQL and session cache
PostPosted: Tue Apr 15, 2014 9:40 pm 
Newbie

Joined: Mon Apr 14, 2014 11:03 am
Posts: 8
Location: Orlando, FL
I would assume that you have already tried the hibernate DML operation. http://docs.jboss.org/hibernate/orm/3.3/reference/en-US/html/batch.html#batch-direct

Other than that I can't really offer any other alternative, unfortunately.

You could evict all objects from the session of a particular type. That's another route.

Hope you find a decent solution.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 7 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.