Hibernate caching (part 1)

Caching là một trong những lợi ích khiến ta chọn Hibernate thay vì JDBC. Bài viết này tôi xin trình bày chi tiết hơn về Hibernate caching. Hibernate cach có hai cấp độ (hai loại) là First levelSecond level.

1. Hibernate caching - First level

First level cache trong Hibernate là chức năng được mặc định có. Ta không cần thiết phải thiết lập gì cho chức năng này, đồng thời ta cũng không thể loại bỏ chức năng này khỏi Hibernate. Để dễ hiểu First level cache trước tiên ta cần hiểu mối liên hệ giữa Session object với Session factory. Trong Hibernate, session object được tạo ra theo yêu cầu từ sesson factory. Khi session factory đóng thì session object cũng mất đi. Tương tự như vậy, First level cache liên kết với session object. First level cache còn khi session object còn. Mỗi First level cached chỉ "phục vụ" cho một session object duy nhất, cách session object khác không truy cập vào được. Những mục quan trọng nhất của First level cache

  • First level cache chỉ liên kết với một session object duy nhất, các session object khác của ứng dụng không thấy, không thể tác động.
  • Phạm vi của First level cache là Session. Một khi session đóng thì first level cache cũng đóng theo.
  • First level cache là mặc định, ta không thể tắt (hủy) nó.
  • Khi ta thực hiện query dữ liệu lần đầu, dữ liệu được lấy ra từ database và lưu trữ vào First level cache được liên kết với Session object này.
  • Nếu ta query cùng một object và cùng một Session như trên thì dữ liệu trả về được lấy từ First level, mà câu truy vấn với database không cần được thực thi.
  • Dữ liệu được lưu ở First level cache có thể bị xóa bằng cách gọi hàm evict() từ session. Sau khi gọi hàm evict(), ta thực hiện lại query cùng object đó thì lúc này query với database được thực thi.
  • Ta có thể xóa dữ liệu trong tất cả các cache của các session bằng cách gọi hàm clear().

Một số ví dụ về First level cache

  • Dữ liệu trả về từ First level cache cho những lần truy vấn sau.
//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

Ta thấy rằng ở lần truy vấn thứ hai session.load() câu truy vấn với database không được thực hiện, dữ liệu được trả về từ cache.

  • Một First level cache chỉ liên kết với một session object (Session còn lại cửa ứng dụng không truy xuất được)
//Open the hibernate session
Session session1 = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
 
Session session2 = HibernateUtil.getSessionFactory().openSession();
sessionTemp.beginTransaction();
try
{
    //fetch the department entity from database first time
    DepartmentEntity department = (DepartmentEntity) session1.load(DepartmentEntity.class, new Integer(1));
    System.out.println(department.getName());
     
    //fetch the department entity again
    department = (DepartmentEntity) session1.load(DepartmentEntity.class, new Integer(1));
    System.out.println(department.getName());
     
    department = (DepartmentEntity) session2.load(DepartmentEntity.class, new Integer(1));
    System.out.println(department.getName());
}
finally
{
    session1.getTransaction().commit();
    HibernateUtil.shutdown();
     
    session2.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

Ví dụ trên có 2 session object là Session session1Session session2 cùng truy vấn 1 object có Id là 1. Với Session session1 ở lần truy vấn thứ 2 (//fetch the department entity again) dữ liệu trả về lấy từ cache. Sau đó Session session2 thực hiện lệnh gọi truy vấn lần nhất, sesion này không truy cập được dữ liệu cache của Session session1 nên nó phải thực hiện query với database để lấy dữ liệu trả về.

  • Xóa dữ liệu từ First level cache Như đã đề cập ở trên, ta không thể hủy bỏ First level cache trong Hibernate, ta chỉ có thể xóa chúng bằng cách gọi hàm evict() để xóa dữ liệu cache của gắn với một session object, gọi hàm clear() để xóa toàn bộ dữ liệu cache gắn với các session object.
//Open the hibernate session
Session session1 = HibernateUtil.getSessionFactory().openSession();
session1.beginTransaction();
Session session2 = HibernateUtil.getSessionFactory().openSession();
session2.beginTransaction();
try
{
    //fetch the department entity from database first time
    DepartmentEntity department = (DepartmentEntity) session1.load(DepartmentEntity.class, new Integer(1));
    System.out.println(department.getName());
    
    department = (DepartmentEntity) session2.load(DepartmentEntity.class, new Integer(1));
    System.out.println(department.getName());
     
    //fetch the department entity again
    department = (DepartmentEntity) session1.load(DepartmentEntity.class, new Integer(1));
    System.out.println(department.getName());
     
    //remove data cache from session1
    session1.evict(department);
     //fetch the department entity again 
    department = (DepartmentEntity) session1.load(DepartmentEntity.class, new Integer(1));
    System.out.println(department.getName());
    department = (DepartmentEntity) session2.load(DepartmentEntity.class, new Integer(1));
    System.out.println(department.getName());
    
    //remove data cache from session1 and session2
    session1.clear();
    
    //fetch the department entity again 
    department = (DepartmentEntity) session1.load(DepartmentEntity.class, new Integer(1));
    System.out.println(department.getName());
    department = (DepartmentEntity) session2.load(DepartmentEntity.class, new Integer(1));
    System.out.println(department.getName());
}
finally
{
    session.getTransaction().commit();
    HibernateUtil.shutdown();
}
         
Output:
 //fetch the department entity from database first time.
Hibernate: select department0_.ID as ID0_0_, department0_.NAME as NAME0_0_ from DEPARTMENT department0_ where department0_.ID=?
Human Resource
Hibernate: select department0_.ID as ID0_0_, department0_.NAME as NAME0_0_ from DEPARTMENT department0_ where department0_.ID=?
Human Resource

//fetch the department entity again from session1.
Human Resource
 
 //fetch the department entity again from session1, session2
 //after remove chache from session1.
Hibernate: select department0_.ID as ID0_0_, department0_.NAME as NAME0_0_ from DEPARTMENT department0_ where department0_.ID=?
Human Resource
Human Resource

//fetch the department entity again from session1, session2
 //after remove chache from all session.
Hibernate: select department0_.ID as ID0_0_, department0_.NAME as NAME0_0_ from DEPARTMENT department0_ where department0_.ID=?
Human Resource
Hibernate: select department0_.ID as ID0_0_, department0_.NAME as NAME0_0_ from DEPARTMENT department0_ where department0_.ID=?
Human Resource

2. Hibernate caching - First level

(In next part) Tài liệu tham khảo