I have trouble understanding when hibernate hits the second level cache and when does it invalidate the cache.
This is what I currently understand:
What I don't understand is
Or am I thinking caching totally wrong? What would be more appropriate uses of second level cache in that case? The hibernate documentation is not at all clear how the cache works in reality. There are only instructions on how to get it set up.
Update: So I've come to understand that second level cache(without query cache) would be good for loading data by id's. For example I have user object that I want to check for permissions in every request in a web application. Would this be a good case to reduce database access by caching the user in the second level cache? Like I would store the user id in the session or wherever and when I need to check for permissions I would load the user by it's id and check permissions.
First of all, let's talk about process level cache (or 2nd level cache as they call it in Hibernate). To make it work, you should
You tell to the cache provider how many objects it should store and when/why they should be invalidated. So let's say you have a Book and an Author entities, each time you're getting them from the DB, only those that are not in cache will be selected from actually DB. This increases performance significantly. It's useful when:
So when does cache work?
session.get()
or session.load()
the object that was previously selected and resides in cache. Cache is a storage where ID is the key and the properties are the values. So only when there is a possibility to search by ID you could eliminate hitting the DB.But it doesn't work when:
from Authors where name = :name
, then you don't hit cache.where id = ?
). fetch="join"
, this means that to load associations joins will be used everywhere instead of separate select statements. Process level cache works on children objects only if fetch="select"
is used.fetch="select"
but then in HQL you use joins to select associations - those joins will be issued right away and they will overwrite whatever you specified in hbm.xml or annotations.Now, about Query Cache. You should note that it's not a separate cache, it's an addition to the process level cache. Let's say you have a Country entity. It's static, so you know that each time there will be the same result set when you say from Country
. This is a perfect candidate for query cache, it will store a list of IDs in itself and when you next time select all countries, it will return this list to the process level cache and the latter, in turn, will return objects for each ID as these objects are stored already in the 2nd level cache.
Query cache is invalidated each time anything related to the entity changes. So let's say you configured from Authors
to be placed into a Query Cache. It won't be effective as Author changes often. So you should use Query Cache only for more or less static data.