Caching is a facility provided by ORM frameworks which help users to get fast running web application, while help framework itself to reduce number of queries made to database in a single transaction. Hibernate achieves the second goal by implementing first level cache.
Fist level cache in hibernate is enabled by default and you do not need to do anything to get this functionality working. In fact, you can not disable it even forcefully.
Its easy to understand the first level cache if we understand the fact that it is associated with Session object. As we know session object is created on demand from session factory and it is lost, once the session is closed. Similarly, first level cache associated with session object is available only till session object is live. It is available to session object only and is not accessible to any other session object in any other part of application.
Hibernate first level cache
Hibernate first level cache

Important facts

  1. First level cache is associated with “session” object and other session objects in application can not see it.
  2. The scope of cache objects is of session. Once session is closed, cached objects are gone forever.
  3. First level cache is enabled by default and you can not disable it.
  4. When we query an entity first time, it is retrieved from database and stored in first level cache associated with hibernate session.
  5. If we query same object again with same session object, it will be loaded from cache and no sql query will be executed.
  6. The loaded entity can be removed from session using evict() method. The next loading of this entity will again make a database call if it has been removed using evict() method.
  7. The whole session cache can be removed using clear() method. It will remove all the entities stored in cache.
Lets verify above facts using examples.

First level cache retrieval example

In this example, I am retrieving DepartmentEntity object from database using hibernate session. I will retrieve it multiple times, and will observe the sql logs to see the differences.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//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
As you can see that second “session.load()” statement does not execute select query again and load the department entity directly.

First level cache retrieval example with new session

With new session, entity is fetched from database again irrespective of it is already present in any other session in application.
?
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
//Open the hibernate session
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
 
Session sessionTemp = HibernateUtil.getSessionFactory().openSession();
sessionTemp.beginTransaction();
try
{
    //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());
     
    department = (DepartmentEntity) sessionTemp.load(DepartmentEntity.class, new Integer(1));
    System.out.println(department.getName());
}
finally
{
    session.getTransaction().commit();
    HibernateUtil.shutdown();
     
    sessionTemp.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
 
Hibernate: select department0_.ID as ID0_0_, department0_.NAME as NAME0_0_ from DEPARTMENT department0_ where department0_.ID=?
Human Resource
You can see that even if the department entity was stored in “session” object, still another database query was executed when we use another session object “sessionTemp”.

Removing cache objects from first level cache example

Though we can not disable the first level cache in hibernate, but we can certainly remove some of objects from it when needed. This is done using two methods :
  • evict()
  • clear()
Here evict() is used to remove a particular object from cache associated with session, and clear() method is used to remove all cached objects associated with session. So they are essentially like remove one and remove all.
?
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
//Open the hibernate session
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
try
{
    //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.evict(department);
    //session.clear();
     
    department = (DepartmentEntity) session.load(DepartmentEntity.class, new Integer(1));
    System.out.println(department.getName());
}
finally
{
    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
 
Hibernate: select department0_.ID as ID0_0_, department0_.NAME as NAME0_0_ from DEPARTMENT department0_ where department0_.ID=?
Human Resource
Clearly, evict() method removed the department object from cache so that it was fetched again from database.
Hope you likes above article. If you got any question or suggestion, drop a comment.
Happy Learning !!