Is first level cache different from query cache in hibernate? I have seen articles mentioning about first level and query cache, so i am confused.
Hibernate First level Cache vs Query Cache
3.9k views Asked by java_geek AtThere are 2 answers
Yes, are different things. Like Lee Chee Kiam says, First level cache is enabled by default and you can't disabled it. Basically it's where Hibernate put the fetched entities the first time so a second query of the same object doesn't instantiate a new object, even avoids the query if it's by ID. An example about this here.
//Open the hibernate session
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
//fetch the department entity from database first time
DepartmentEntity department = (DepartmentEntity) session.load(DepartmentEntity.class, new Integer(1));
System.out.println(department.getName());
//fetch the department entity again
department = (DepartmentEntity) session.load(DepartmentEntity.class, new Integer(1));
System.out.println(department.getName());
session.getTransaction().commit();
HibernateUtil.shutdown();
Output:
Hibernate: select department0_.ID as ID0_0_, department0_.NAME as NAME0_0_ from DEPARTMENT department0_ where department0_.ID=?
Human Resource
Human Resource
We could say that the First Level Cache is the Hibernate implementation of the IdentityMap pattern.
The Query Cache is strictly related to Entities and it draws an association between a search criteria and the Entities fulfilling that specific query filter (from here). A query cache only holds the raw results of the queries as primary keys, in hibernate speak, id's. It does not hold the actual hydrated objects.
How does the query cache work?
Suppose we have the following criteria query:
session.createCriteria(Person.class)
.add( Restrictions.eq("firstName", "Joey")
).setCacheable(true);
The query cache looks conceptually like an hash map where the key is composed by the query text and the parameter values, and the value is a list of entity Id's that match the query
*----------------------------------------------------------*
| Query Cache |
|----------------------------------------------------------|
| ["from Person where firstName=?", ["Joey"] ] -> [1, 2] ] |
*----------------------------------------------------------*
So, the next time we execute the same criteria query, Hibernate will look at that hash map and resolve that the Persons with id 1 and 2 match the restrictions. In this case you would be avoiding the cost of the query (that in this case is almost zero but could be an expensive query with joins,etc) but you'd still be hitting the database for query the Persons (now by id what is very fast) for construct the Person objects. The query cache is frequently used with Second Level Cache, that requires a third part implementation like Ehcache or infinispan.
The second level cache stores the entity data, but NOT the entities themselves. The data is stored in a 'dehydrated' format which looks like a hash map where the key is the entity Id, and the value is a list of primitive values. Here is an example on how the contents of the second-level cache look:
*-----------------------------------------*
| Person Data Cache |
|-----------------------------------------|
| 1 -> [ "Joey" , "Q" , "Public" , null ] |
| 2 -> [ "Joey" , "D" , "Public" , 1 ] |
| 3 -> [ "Sara" , "N" , "Public" , 1 ] |
*-----------------------------------------*
So, the query cache will gives us the ids 1 and 2, then Hibernate will construct the objects with the raw data in the second level cache that corresponds to Persons with id 1 and 2.
The query cache and second level cache are for entities with many reads and little or zero updates. Because the well known problem of inconsistency in every type of cache. So Hibernate will need invalidate or refresh the cache (with replication included if you have a clustered cache). With many updates you will be constantly invalidating the cache and it will be doing more harm than good.
Some explanations are taked from this great post and you should read this good answer too.
First level cache is enabled by default and is per session basis. Query cache is not enabled by default, is shared across multiple sessions and should always be used in conjunction with the second-level cache.
To enable query cache, the following properties should be used: