Tại sao bạn cần một bộ đệm truy vấn

Hãy viết lại ví dụ của chúng tôi với việc nhận nhân viên trong HQL:

Employee director1 = session.createQuery("from Employee where id = 4").uniqueResult();
Employee director2 = session.createQuery("from Employee where id = 4").uniqueResult();

assertTrue(director1 != director2);

Kết quả của các truy vấn như vậy không được lưu trữ bởi bộ nhớ cache cấp một hoặc cấp hai.

Đây chính xác là nơi có thể sử dụng bộ đệm truy vấn . Nó cũng bị tắt theo mặc định. Để kích hoạt nó, hãy thêm dòng sau vào tệp cấu hình:

<property name="hibernate.cache.use_query_cache" value="true"/>

Nhưng đây chỉ là một nửa giải pháp. Chúng tôi đã bật bộ đệm truy vấn, nhưng chúng tôi cũng cần chỉ định kết quả truy vấn nào chúng tôi muốn lưu vào bộ đệm. Điều này phải được viết trong Truy vấn:

Query query = session.createQuery("from Employee where id = 4");
query.setCacheable(true);
Employee director1 = query.uniqueResult();

Bộ đệm truy vấn tương tự như bộ đệm cấp hai. Nhưng, không giống như nó, ở đây chìa khóa của dữ liệu bộ đệm không phải là mã định danh đối tượng, mà là tập hợp các tham số truy vấn. Và bản thân dữ liệu là các định danh của các đối tượng phù hợp với tiêu chí truy vấn. Do đó, việc sử dụng bộ đệm này với bộ đệm cấp hai là hợp lý.

Xóa bộ nhớ cache

Một trong những nhiệm vụ quan trọng khi làm việc với bộ đệm là đảm bảo rằng các đối tượng được lưu trong bộ đệm thay đổi và xóa chúng khỏi bộ đệm (hoặc cập nhật chúng). Hibernate làm điều này rất tốt. Đôi khi, có vẻ như anh ta được hướng dẫn bởi quy tắc "xóa bộ nhớ cache trong bất kỳ tình huống khó hiểu nào".

Giả sử bạn muốn cập nhật dữ liệu người dùng qua HQL:

Query query = session.createQuery("update Employee set name=’Alex’ where id = 4")
query. executeUpdate();

Hibernate không thể biết chính xác những gì đã thay đổi trong cơ sở dữ liệu, nhưng nó biết rằng bạn đang thay đổi một đối tượng Nhân viên. Do đó, sau khi thực hiện truy vấn này, Hibernate sẽ xóa tất cả các đối tượng thuộc loại Nhân viên khỏi bộ đệm của nó.

Nhưng NativeQuery hoạt động thậm chí còn thú vị hơn:

Query nativeQuery = session.createNativeQuery("update employee set name=’Alex’ where id = 4")
nativeQuery.executeUpdate();

Một truy vấn SQL gốc tới cơ sở dữ liệu đã được thực thi. Điều này có nghĩa là có gì đó đã thay đổi trong cơ sở dữ liệu - yêu cầu đã được gọi trong phương thức execUpdate() . Do đó, trong trường hợp này, Hibernate sẽ chơi an toàn và xóa tất cả các đối tượng thuộc mọi loại khỏi bộ đệm của nó .

Làm thế nào để bạn thích điều đó? Bạn gọi một yêu cầu vô hại và Hibernate đáp lại sẽ xóa tất cả dữ liệu khỏi bộ đệm! Điều này chắc chắn sẽ tốt hơn so với việc anh ấy giữ những đồ vật khác với đế, nhưng chỉ có thế!

Do đó, những người tạo ra Hibernate đã nhanh chóng tìm ra cách giúp Hibernate trong trường hợp này. Bạn có thể cho nó biết loại thực thể nào cần xóa khỏi bộ đệm:

Query nativeQuery = session.createNativeQuery("update employee set name=’Alex’ where id = 4");
nativeQuery.unwrap(org.hibernate.SQLQuery.class).addSynchronizedEntityClass(Employee.class);
nativeQuery.executeUpdate();
Nhận xét . Các truy vấn chọn gốc không xóa bộ đệm , chỉ chèn, cập nhật, xóa, gọi thủ tục, v.v.

Xóa cache thủ công

Vì một số lý do nhất định, bạn có thể muốn tự mình xóa một đối tượng khỏi bộ đệm ẩn. Điều này có thể được thực hiện theo những cách khác nhau.

lưu ý . Các đối tượng trong bộ đệm được lưu trữ trong các nhóm được gọi là vùng . Theo mặc định, tên khu vực giống như tên lớp. Do đó, nếu bạn có các đối tượng thuộc loại com.codegym.Employee thì tất cả chúng sẽ được lưu trữ trong một nhóm (vùng) có tên “ com.codegym.employee ”.

Nếu bạn muốn truy cập bộ đệm và làm điều gì đó với nó, bạn có thể làm điều đó với đối tượng SessionFactory và phương thức getCache() :

session.getSessionFactory().getCache().evictQueryRegion("com.codegym.employee”);

Nếu bạn muốn xóa dữ liệu khỏi tất cả các nhóm (khu vực), thì bạn cần chạy truy vấn sau:

session.getSessionFactory().getCache().evictAllRegions();

Để xóa một đối tượng khỏi bộ đệm, bạn cần chuyển tên (loại) và id của nó. Bạn có thể làm điều này theo hai cách:

session.getSessionFactory().getCache().evictEntityData("Employee, 4);

session.getSessionFactory().getCache().evictEntityData(com.codegym.Employee.class, 4);

Bạn cũng có thể kiểm tra xem một đối tượng cụ thể có trong bộ đệm hay không:

session.getSessionFactory().getCache().containsEntity("Employee, 4);
session.getSessionFactory().getCache().containsEntity(com.codegym.Employee.class, 4);