-->
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.  [ 16 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Second Level Cache not caching the data
PostPosted: Tue Nov 27, 2007 5:06 am 
Beginner
Beginner

Joined: Tue Sep 11, 2007 5:57 am
Posts: 36
I have configured Second level cache, and marked class Superbill to be cached as

<add
key="hibernate.cache.provider_class" value="NHibernate.Caches.Prevalence.PrevalenceCacheProvider, NHibernate.Caches.Prevalence"
/>

When I build the sessionfactory, I see count=1 against cached region under sessionfactory implementation.
Then I create a session object, and execute

_session.CreateCriteria(typeof(Superbill)).List();

and the profiler says that the query was fired on the database and not on the cache. I thought , the data is cached when it is loaded for the first time, so using the same session object I executed same query and still could see the trace on the profiler.

Can someone please tell, when does the second level cache , actually cache data, while creating the session factory or when it is first time loaded?

Also , why does the profiler show the trace everytime I execute the query?

Am I missing on something?

thanks in advance.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 27, 2007 8:25 am 
Regular
Regular

Joined: Thu Nov 23, 2006 10:29 am
Posts: 106
Location: Belgium
Hi,

You'll only hit the second level cache when fetching an object based on it's ID. The first time you load an object, it'll get cached, independently of the way you queried it. Afterwards, if you query it based on it's ID, NHibernate will use the second-level cache.

When querying for a List() or using criteria other than the ID, NHibernate will always make a roundtrip to the database to fetch the objects.

_________________
Please rate this post if it helped.

X.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 27, 2007 8:45 am 
Beginner
Beginner

Joined: Tue Sep 11, 2007 5:57 am
Posts: 36
Hello,
Unfortunately it didn't work.
Initially I used _session.CreateCriteria(typeof(Superbill)).List()

to load all objects, and then I used

_session.CreateQuery("FROM Superbill where SuperbillUID='CE22FD11-53FB-41F4-A2DB-4B960598FB09'").List()

but , both the times, it went to database.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 27, 2007 8:51 am 
Regular
Regular

Joined: Thu Nov 23, 2006 10:29 am
Posts: 106
Location: Belgium
Hello,

I know, HQL will go directly to the database. Oops, forgot to mention that.

Try _session.Get<type>(id) : you should see it working now.
Or use ICriteria queries to query on the ID.

_________________
Please rate this post if it helped.

X.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 27, 2007 9:06 am 
Beginner
Beginner

Joined: Tue Sep 11, 2007 5:57 am
Posts: 36
Great!!
That worked, but unfortunately that's not gonna help me a lot.
Also does first level cache also get cached data only when queried on the ID?


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 27, 2007 9:14 am 
Regular
Regular

Joined: Thu Nov 23, 2006 10:29 am
Posts: 106
Location: Belgium
Hello,

Yep, that was my first thought also.

But then I thought: when I query a specific object, most of the time I want it to be fetched straight from the database (to be sure I get the last version). So for those, I'm wouldn't use caching anyway.
Most of my second-level cached objects are objects that are very heavily used by my application but aren't queried directly very often.

An example: I have a User class that is linked multiple times to each of my business objects (f.e. user that created the object, user that last modified the object, etc...). Those links are associations (yep, on the ID).
So when I get a business object, NHibernate will fetch the associated User objects from the second-level cache (except the first time that User is needed).

Think of all the associations in your business objects : you'll see quickly that the second-level cache definitely has it's merits (of course, do not set fetch='join' on your associations, or second-level cache won't be used).

_________________
Please rate this post if it helped.

X.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 27, 2007 11:58 pm 
Beginner
Beginner

Joined: Tue Sep 11, 2007 5:57 am
Posts: 36
Thanks, but what about the First level cache?
Does it also fetch data when queried against the ID only?


Top
 Profile  
 
 Post subject:
PostPosted: Wed Nov 28, 2007 11:37 am 
Hibernate Team
Hibernate Team

Joined: Tue Jun 13, 2006 11:29 pm
Posts: 315
Location: Calgary, Alberta, Canada
Queries are not cached in the session cache (aka, first-level cache). You will always by-pass the session cache if you do this:
Code:
Person p = session.CreateQuery("from Person p where p.ID = 1").UniqueResult<Person>();

On the contrary, the following will look in the session cache first:
Code:
Person p = session.Get<Person>(1);

Second level cache is a different story, see here:
http://forum.hibernate.org/viewtopic.ph ... 65#2357765

_________________
Karl Chu


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 30, 2007 1:00 am 
Beginner
Beginner

Joined: Tue Sep 11, 2007 5:57 am
Posts: 36
Thanks for the information.
But as far as I know, any object that is marked as to be cached is cached in the second level cache when it is loaded for the very first time, irrespective of the way it is loaded. Meaning it doesn't matter how you loaded the object using Load, get, createquery or createcriteria.Same with the first level cache. If that's true they why does it impose a criteria while looking up in the cache , like using only Get and Load will make NHibernate look up in the cache?

Also can you please list the way I should look for an object to make NHibernate look up in the cache?(like get and load).

Also suppose I have an object named Superbill with one column as CreatedByUid which refers to object User. The object user is marked as to be cached for second level cache. Then when I fetch an object of Superbill NHibernate looks in the second level cache for object of User, as Superbill has reference to it's primary key. My question is , for making this happen is there any criteria for searching the object of Superbill?


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 30, 2007 1:52 am 
Hibernate Team
Hibernate Team

Joined: Tue Jun 13, 2006 11:29 pm
Posts: 315
Location: Calgary, Alberta, Canada
The session cache only caches individual entities; it does not cache queries (e.g. anything retrieved by an IQuery or ICriteria). That's pretty much the end of that as far as session cache goes.

The following only pertains to second-level cache.

Individual entities are only "keyed" in the cached by their IDs (as defined by the <id> element). There is no way to search in the cache any other way; otherwise, you might as well just go to the database.

When you fetch something using an IQuery without setting it to cacheable, the individual entities get cached (in the second level cache). When you issue the same query again, NHibernate can do one of two things:
  1. Retrieve all the IDs produced by that query and then see if those entities are already cached. If so, use them in the result; if not, issue a separate query to get what it doesn't already have
  2. Since we are making a trip to the database anyway, just run the query and get everything

Option#1 above obviously does not make sense as you may end up hitting the database twice. Whereas the second option guarantees that you will get what you want in one round trip. NHibernate does, in my opinion, the sensible thing and implements option#2 above.

In a cached query scenario, the link I gave above should have explained it pretty well.

_________________
Karl Chu


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 30, 2007 2:03 am 
Beginner
Beginner

Joined: Tue Sep 11, 2007 5:57 am
Posts: 36
I didn't get how does the option 1 requires two trips to the database?
Does it execute first query just to get the ID's?


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 30, 2007 2:15 am 
Hibernate Team
Hibernate Team

Joined: Tue Jun 13, 2006 11:29 pm
Posts: 315
Location: Calgary, Alberta, Canada
Just so I am clear, option#1 is not how it is implemented in NHibernate. It was only presented to illustrate what NHibernate does do (i.e. option#2) is the sensible thing.

Some might think that to "save network bandwidth", we should use as much as possible that are already in cache. So let's just get the IDs with a query and we can then get the entities out from cache. What if an external application inserted a new record to the database in the mean time? Now you have to go back to the database to get this new record/entity with a second trip.

_________________
Karl Chu


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 30, 2007 2:58 am 
Beginner
Beginner

Joined: Tue Sep 11, 2007 5:57 am
Posts: 36
Thanks,
Can you please list the way I should look for an object to make NHibernate look up in the cache?(like get and load).


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 30, 2007 11:08 am 
Hibernate Team
Hibernate Team

Joined: Tue Jun 13, 2006 11:29 pm
Posts: 315
Location: Calgary, Alberta, Canada
Get() and Load() will look in cache. When using IQuery or ICriteria, calling SetCacheable(true) will look in cache.

_________________
Karl Chu


Top
 Profile  
 
 Post subject:
PostPosted: Mon Dec 03, 2007 4:57 am 
Beginner
Beginner

Joined: Tue Sep 11, 2007 5:57 am
Posts: 36
Thanks Karl,
Both Get() and Load() require an object id to fetch the object from database.Whereas my requirement is to give user as much flexibility as possible.Suppose Patient class has 2 columns namely, ExternalID and ProviderID and the class is marked cacheable, then the user should be able to search against any of these columns.Therefore my wrapper looks like

PatientCollection objPat = new PatientAgent(ObjectContext).Find("ExternalID='4229'"); //uses createquery

PatientCollection objPatColl = new PatientAgent(ObjectContext).FindAll(); //uses createcriteria

Patient objPat = new PatientAgent(ObjectContext).FindUnique("ExternalID='4229'"); //uses createquery

FindUnique throws exception if failed to fetch unique result.

Example my Find method will execute

string Predicate = "From Patient Where ExternalID='4229";
return _session.CreateQuery(Predicate).List<T>();

And here I am not using Get() or Load(), therefore it will not go to cache(assuming it's already loaded in the second level cache). Now if I do

return _session.CreateQuery(Predicate).SetCacheable(true).List<T>();

then will it look up in the cache or will it cache the result set of these query seperately? As SetCacheable(true) will enable caching of the result set.

Also, I have not explicitly done _session.Flush() after I fire the queries, but on debugging I found that NHibernate does it. So do I need to do it explicitly?


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 16 posts ]  Go to page 1, 2  Next

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.