Trang chủHướng dẫnHibernate Caching là gì? Tìm hiểu bộ nhớ đệm cấp một trong Hibernate

Hibernate Caching là gì? Tìm hiểu bộ nhớ đệm cấp một trong Hibernate

CyStack blog 4 phút để đọc
CyStack blog24/07/2025
Locker Avatar

Chris Pham

Technical Writer

Locker logo social
Reading Time: 4 minutes

Chào mừng bạn đến với hướng dẫn về Hibernate Caching – ví dụ minh họa cách sử dụng bộ nhớ đệm cấp một (First Level Cache). Trước đó, chúng ta đã tìm hiểu về kiến trúc Hibernate, cách ánh xạ đối tượng và sử dụng HQL để truy vấn dữ liệu theo hướng đối tượng. Trong bài viết này, chúng ta sẽ tiếp tục khám phá một khía cạnh quan trọng khác của Hibernate: cơ chế bộ nhớ đệm (Hibernate Cache)

hibernate caching là gì

Hibernate Caching là gì?

Hibernate Cache có thể mang lại hiệu năng tốt hơn cho ứng dụng nếu được sử dụng đúng cách. Mục tiêu của cache là giảm số lần truy vấn đến cơ sở dữ liệu, từ đó rút ngắn thời gian xử lý ứng dụng. Hibernate hỗ trợ nhiều loại Cache khác nhau:

  1. First Level Cache: Cache này gắn với đối tượng Session. Nó được bật mặc định và không thể tắt. Tuy nhiên, Hibernate cung cấp các phương thức cho phép loại bỏ từng đối tượng cụ thể ra khỏi cache hoặc xóa toàn bộ cache. Các đối tượng được lưu trong session này sẽ không hiển thị với các session khác và khi session đóng lại, tất cả các đối tượng trong cache cũng sẽ mất.
  2. Second Level Cache (Bộ nhớ đệm cấp hai): Cache này không được bật mặc định nhưng có thể cấu hình để sử dụng. Hiện tại, EHCache và Infinispan cung cấp giải pháp triển khai cho cache cấp hai trong Hibernate. Nội dung này sẽ được trình bày trong bài viết tiếp theo.
  3. Query Cache (Bộ nhớ đệm truy vấn): Hibernate cũng có thể lưu vào bộ nhớ đệm kết quả của một truy vấn. Tuy nhiên, Hibernate Query Cache không lưu trạng thái thực của các entity mà chỉ lưu giá trị định danh (identifier) và các kết quả có kiểu dữ liệu giá trị. Vì vậy, khi sử dụng Query Cache, bạn nên kết hợp với bộ nhớ đệm cấp hai để đạt hiệu quả tốt nhất.

Hibernate Caching – Ví dụ về First Level Cache

Trong ví dụ này, sử dụng cấu hình giống như trong bài HQL trước. Bạn có thể tham khảo bài đó để cấu hình bảng và thêm dữ liệu mẫu. Trước tiên, chúng ta cùng xem qua chương trình, kết quả đầu ra và sau đó phân tích các điểm quan trọng liên quan đến First Level Cache của Hibernate.

HibernateCacheExample.java

package com.journaldev.hibernate.main;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;

import com.journaldev.hibernate.model.Employee;
import com.journaldev.hibernate.util.HibernateUtil;

public class HibernateCacheExample {

	public static void main(String[] args) throws InterruptedException {
		
		SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
		Session session = sessionFactory.getCurrentSession();
		Transaction tx = session.beginTransaction();
		
		//Get employee with id=1
		Employee emp = (Employee) session.load(Employee.class, new Long(1));
		printData(emp,1);
		
		//waiting for sometime to change the data in backend
		Thread.sleep(10000);
		
		//Fetch same data again, check logs that no query fired
		Employee emp1 = (Employee) session.load(Employee.class, new Long(1));
		printData(emp1,2);
		
		//Create new session
		Session newSession = sessionFactory.openSession();
		//Get employee with id=1, notice the logs for query
		Employee emp2 = (Employee) newSession.load(Employee.class, new Long(1));
		printData(emp2,3);
		
		//START: evict example to remove specific object from hibernate first level cache
		//Get employee with id=2, first time hence query in logs
		Employee emp3 = (Employee) session.load(Employee.class, new Long(2));
		printData(emp3,4);
		
		//evict the employee object with id=1
		session.evict(emp);
		System.out.println("Session Contains Employee with id=1?"+session.contains(emp));

		//since object is removed from first level cache, you will see query in logs
		Employee emp4 = (Employee) session.load(Employee.class, new Long(1));
		printData(emp4,5);
		
		//this object is still present, so you won't see query in logs
		Employee emp5 = (Employee) session.load(Employee.class, new Long(2));
		printData(emp5,6);
		//END: evict example
		
		//START: clear example to remove everything from first level cache
		session.clear();
		Employee emp6 = (Employee) session.load(Employee.class, new Long(1));
		printData(emp6,7);
		Employee emp7 = (Employee) session.load(Employee.class, new Long(2));
		printData(emp7,8);
		
		System.out.println("Session Contains Employee with id=2?"+session.contains(emp7));
		
		tx.commit();
		sessionFactory.close();
	}

	private static void printData(Employee emp, int count) {
		System.out.println(count+":: Name="+emp.getName()+", Zipcode="+emp.getAddress().getZipcode());
	}

}

Khi chạy chương trình trên, đầu ra sẽ chứa nhiều thông tin liên quan đến Hibernate. Tuy nhiên, phần đáng chú ý là kết quả của đoạn mã và các câu truy vấn được Hibernate sinh ra để lấy dữ liệu. Dưới đây là trích đoạn đầu ra liên quan:

Hibernate Configuration loaded
Hibernate serviceRegistry created
Hibernate: select employee0_.emp_id as emp_id... where employee0_.emp_id=?
1:: Name=Pankaj, Zipcode=95129
2:: Name=Pankaj, Zipcode=95129
Hibernate: select employee0_.emp_id as emp_id... where employee0_.emp_id=?
3:: Name=PankajK, Zipcode=95129
Hibernate: select employee0_.emp_id as emp_id... where employee0_.emp_id=?
4:: Name=David, Zipcode=95051
Session Contains Employee with id=1?false
Hibernate: select employee0_.emp_id as emp_id... where employee0_.emp_id=?
5:: Name=Pankaj, Zipcode=95129
6:: Name=David, Zipcode=95051
Hibernate: select employee0_.emp_id as emp_id... where employee0_.emp_id=?
7:: Name=Pankaj, Zipcode=95129
Hibernate: select employee0_.emp_id as emp_id... where employee0_.emp_id=?
8:: Name=David, Zipcode=95051
Session Contains Employee with id=2?true

Các điểm quan trọng về First Level Cache trong Hibernate

Các điểm quan trọng về First Level Cache trong Hibernate có thể rút ra từ ví dụ trên gồm:

  1. First Level Cache được bật mặc định và không cần cấu hình.
  2. Cache này chỉ áp dụng trong phạm vi của một session, do đó khi lấy lại cùng một dữ liệu trong cùng một session thì không có truy vấn nào được gửi đến cơ sở dữ liệu. Ngược lại, nếu sử dụng session khác thì sẽ thấy Hibernate phát sinh truy vấn.
  3. Cache có thể chứa dữ liệu cũ. Như trong ví dụ trên, chương trình được cho dừng trong 10 giây và dữ liệu ở cơ sở dữ liệu đã được cập nhật (tên từ Pankaj đổi thành PankajK), nhưng do cache vẫn giữ bản cũ nên không thấy thay đổi trong session hiện tại. Tuy nhiên, session mới thì nhận được giá trị đã cập nhật.
  4. Có thể sử dụng session.evict() để xóa một đối tượng cụ thể khỏi cache.
  5. session.clear() cho phép xóa toàn bộ các đối tượng trong cache.
  6. Để kiểm tra một đối tượng có tồn tại trong cache hay không, dùng session.contains(), nếu tìm thấy sẽ trả về true, ngược lại là false.
  7. Do Hibernate đưa tất cả các đối tượng vào First Level Cache nên khi thực hiện các truy vấn khối lượng lớn hoặc cập nhật theo batch, chúng ta cần xóa cache định kỳ để tránh gặp sự cố về bộ nhớ.

Phần trình bày về Hibernate caching và ví dụ First Level Cache kết thúc tại đây. Trong các bài viết sau sẽ tiếp tục với Second Level Cache và triển khai EHCache.

0 Bình luận

Đăng nhập để thảo luận

Chuyên mục Hướng dẫn

Tổng hợp các bài viết hướng dẫn, nghiên cứu và phân tích chi tiết về kỹ thuật, các xu hướng công nghệ mới nhất dành cho lập trình viên.

Đăng ký nhận bản tin của chúng tôi

Hãy trở thành người nhận được các nội dung hữu ích của CyStack sớm nhất

Xem chính sách của chúng tôi Chính sách bảo mật.

Đăng ký nhận Newsletter

Nhận các nội dung hữu ích mới nhất