This Hibernate First Level Cache Example tutorial will help you understand about First Level Cache mechanism of Hibernate. Notice thant if you use Hibernate Cache correctly it will be very useful in increasing application performance. The idea of Hibernate cache is to reduce number of database queries, hence improving performance of the application.
Hibernate supports different types of Cache:
First Level Cache: Hibernate first level cache is associated with the Session object or is known as Session cache. It is enabled by default and a mandatory cache through which all requests must pass. Any object cached in a session will not be visible to other sessions and when the session is closed, all the cached objects of a session will also be lost. Beside, Hibernate also provides methods through which we can delete selected objects from the cache or clear the cache completely.
Second Level Cache: Hibernate Second Level cache is optional cache and we can enable it through configuration. Hibernate have not implemented the Second Level cache yet. But we can use Cache providers like EHCache or Infinispan, etc that implements this cache.
Query Cache is caching the combination of query and values provided as parameters as key, and list of identifiers of objects returned by query execution as values. Notice that Hibernate will load objects using cached identifiers from second level.
Other interesting posts you may like
Let’s begin discovery the Hibernate First Level Cache Examples
We will create java project by using Maven in Eclipse. This project is with directory structure like below
First example about Hibernate First Level Cache Example
This example will demonstrate two cases: getting same object with the same session and getting same object with each seperated sessions
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
package com.javabycode.hibernate; import org.hibernate.Session; import org.hibernate.Transaction; import com.javabycode.hibernate.model.Student; public class HibernateCacheExample1 { public static void main(String[] args) throws InterruptedException { Session session = HibernateUtil.getSessionFactory().openSession(); Transaction tx = session.beginTransaction(); printLog("--------Step 1--------"); // Get student with id=23 Student student = (Student) session.load(Student.class, new Integer(23)); printLog(student, 1); // Waiting for sometime to change the data in database backend printLog("Waiting for 15000 milliseconds..."); Thread.sleep(15000); // Fetch same data again, and no query fired Student student1 = (Student) session.load(Student.class, new Integer(23)); printLog(student1, 2); printLog("--------Step 2--------"); // Create new session printLog("Create new session and get student by the same id"); Session newSession = HibernateUtil.getSessionFactory().openSession(); // Get student with id=23, query is fired because hibernate get it from database Student student2 = (Student) newSession.load(Student.class, new Integer(23)); printLog(student2, 3); tx.commit(); System.exit(0); } private static void printLog(Student student, int count) { System.out.println("Get student => Name=" + student.getName() + ", Nationality=" + student.getNationality()); } private static void printLog(String msg) { System.out.println(msg); } } |
Run above the program and we get the output like this:
1 2 3 4 5 6 7 8 9 |
--------Step 1-------- Hibernate: select student0_.id as id1_0_0_, student0_.code as code2_0_0_, student0_.ENTERING_DATE as ENTERING3_0_0_, student0_.NAME as NAME4_0_0_, student0_.NATIONALITY as NATIONAL5_0_0_ from STUDENT student0_ where student0_.id=? Step 1 => Name=David Pham, Nationality=USA Waiting for 15000 milliseconds... Step 2 => Name=David Pham, Nationality=USA --------Step 2-------- Create new session and get student by the same id Hibernate: select student0_.id as id1_0_0_, student0_.code as code2_0_0_, student0_.ENTERING_DATE as ENTERING3_0_0_, student0_.NAME as NAME4_0_0_, student0_.NATIONALITY as NATIONAL5_0_0_ from STUDENT student0_ where student0_.id=? Step 3 => Name=David Villa, Nationality=USA |
As you can see how Hibernate first level cache works on the above program. We can understand that Hibernate first level cache is session specific, that’s why when we are getting the same data in same session there is no query fired whereas in other session query is fired to load the data.
First level cache can have old values, as you can see above that we have put my program to sleep for 15 seconds then I update the value (name from David Pham to David Villa) in database but it is not reflected in the same session. But in other session, it get the updated value.
Second example about Hibernate First Level Cache Example
This example will demonstrate how to use evict method to remove object in session:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
package com.javabycode.hibernate; import org.hibernate.Session; import org.hibernate.Transaction; import com.javabycode.hibernate.model.Student; public class HibernateCacheExample2 { public static void main(String[] args) throws InterruptedException { Session session = HibernateUtil.getSessionFactory().openSession(); Transaction tx = session.beginTransaction(); printLog("--------Step 1--------"); // Get student with id=23 Student student = (Student) session.load(Student.class, new Integer(23)); printLog(student, 1); // Fetch same data again, and no query fired Student student1 = (Student) session.load(Student.class, new Integer(23)); printLog(student1, 2); printLog("--------Step 2--------"); // Evict the Student object with id=1 from first level cache printLog("Evict the Student object id=23 from first level cache"); session.evict(student); printLog("Session contains student with id=23? " + session.contains(student)); // You will see query in logs because Hibernate get it from database. printLog("--------Step 3--------"); Student student4 = (Student) session.load(Student.class, new Integer(23)); printLog(student4, 3); tx.commit(); System.exit(0); } private static void printLog(Student student, int count) { System.out.println("Get student => Name=" + student.getName() + ", Nationality=" + student.getNationality()); } private static void printLog(String msg) { System.out.println(msg); } } |
Run above main and we get the output like below
1 2 3 4 5 6 7 8 9 10 |
--------Step 1-------- Hibernate: select student0_.id as id1_0_0_, student0_.code as code2_0_0_, student0_.ENTERING_DATE as ENTERING3_0_0_, student0_.NAME as NAME4_0_0_, student0_.NATIONALITY as NATIONAL5_0_0_ from STUDENT student0_ where student0_.id=? Get student => Name=David Pham, Nationality=USA Get student => Name=David Pham, Nationality=USA --------Step 2-------- Evict the Student object id=23 from first level cache Session contains student with id=23? false --------Step 3-------- Hibernate: select student0_.id as id1_0_0_, student0_.code as code2_0_0_, student0_.ENTERING_DATE as ENTERING3_0_0_, student0_.NAME as NAME4_0_0_, student0_.NATIONALITY as NATIONAL5_0_0_ from STUDENT student0_ where student0_.id=? Get student => Name=David Pham, Nationality=USA |
As you see the above program. Now we can use session evict() method to remove a single object from the first level cache.
Third Example about Hibernate First Level Cache Example
This example will demonstrate how to use clear method to remove cache object in session:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
package com.javabycode.hibernate; import org.hibernate.Session; import org.hibernate.Transaction; import com.javabycode.hibernate.model.Student; public class HibernateCacheExample3 { public static void main(String[] args) throws InterruptedException { Session session = HibernateUtil.getSessionFactory().openSession(); Transaction tx = session.beginTransaction(); printLog("--------Step 1--------"); // Get student with id=23 Student student = (Student) session.load(Student.class, new Integer(23)); printLog(student, 1); // Fetch same data again, check logs that no query fired Student student1 = (Student) session.load(Student.class, new Integer(23)); printLog(student1, 2); printLog("--------Step 2--------"); // Clear example to remove everything from first level cache printLog("Clear everything from first level cache"); session.clear(); Student student2 = (Student) session.load(Student.class, new Integer(23)); printLog(student2, 7); Student student3 = (Student) session.load(Student.class, new Integer(24)); printLog(student3, 8); printLog("--------Step 3--------"); printLog("Session contains student with id=24?" + session.contains(student3)); tx.commit(); System.exit(0); } private static void printLog(Student student, int count) { System.out.println("Get student => Name=" + student.getName() + ", Nationality=" + student.getNationality()); } private static void printLog(String msg) { System.out.println(msg); } } |
Run above main and we get the output like below:
1 2 3 4 5 6 7 8 9 10 11 12 |
--------Step 1-------- Hibernate: select student0_.id as id1_0_0_, student0_.code as code2_0_0_, student0_.ENTERING_DATE as ENTERING3_0_0_, student0_.NAME as NAME4_0_0_, student0_.NATIONALITY as NATIONAL5_0_0_ from STUDENT student0_ where student0_.id=? Get student => Name=David Pham, Nationality=USA Get student => Name=David Pham, Nationality=USA --------Step 2-------- Clear everything from first level cache Hibernate: select student0_.id as id1_0_0_, student0_.code as code2_0_0_, student0_.ENTERING_DATE as ENTERING3_0_0_, student0_.NAME as NAME4_0_0_, student0_.NATIONALITY as NATIONAL5_0_0_ from STUDENT student0_ where student0_.id=? Get student => Name=David Pham, Nationality=USA Hibernate: select student0_.id as id1_0_0_, student0_.code as code2_0_0_, student0_.ENTERING_DATE as ENTERING3_0_0_, student0_.NAME as NAME4_0_0_, student0_.NATIONALITY as NATIONAL5_0_0_ from STUDENT student0_ where student0_.id=? Get student => Name=Bill Murray, Nationality=USA --------Step 3-------- Session contains student with id=24?true |
Now, we can also use session clear() method to clear the cache or delete all the objects from the cache. If you want to check if an object is present in the hibernate cache or not you can use session contains() method.
Important note: While running bulk queries or batch updates, maybe you will get memory problem. The best way is clearing the cache at certain intervals because Hibernate cache all the objects into session first level cache.
That’s it on the Hibernate First Level Cache Example tutorial.
Download complete source code, please click link below
HibernateCacheExample.zip (304 downloads)