2012-05-10 45 views
7

Tôi đang gặp một số sự cố khi biết truy vấn HQL nhận thông tin từ đó. Dự án của tôi đang sử dụng các luồng khác nhau và mỗi luồng đọc/ghi vào cơ sở dữ liệu. Chủ đề không chia sẻ đối tượng Phiên, thay vào đó tôi đang sử dụng lớp học HibernateUtil tạo phiên cho tôi.Hibernate HQL chỉ truy cập bộ nhớ cache phiên

Cho đến gần đây, tôi sẽ chỉ đóng một phiên sau khi viết chứ không phải sau khi đọc. Thay đổi đối tượng sẽ được nhìn thấy ngay lập tức trong cơ sở dữ liệu nhưng khi đọc trên các chủ đề khác (đối tượng phiên khác với đối tượng được sử dụng để viết), tôi sẽ nhận được thông tin cũ. Đọc và viết xảy ra luôn luôn trên các chủ đề khác nhau có nghĩa là các đối tượng Session khác nhau và các bộ đệm phiên khác nhau. Tôi luôn luôn nghĩ rằng bằng cách sử dụng HQL thay vì Criteria, tôi sẽ luôn nhắm mục tiêu cơ sở dữ liệu (hoặc bộ nhớ cache cấp thứ hai) và không phải là bộ nhớ cache phiên nhưng trong khi gỡ lỗi mã của tôi, nó đã được làm rõ với tôi rằng HQL đang tìm kiếm đối tượng trong bộ nhớ cache phiên và truy lục đối tượng cũ đã lỗi thời.

Tôi có sai khi giả định rằng HQL luôn nhắm mục tiêu cơ sở dữ liệu không? Hoặc ít nhất là bộ nhớ cache cấp thứ hai?

PS: Tôi chỉ đang sử dụng một đối tượng SessionFactory.

Trả lời

7

Hibernate có các khái niệm khác nhau về bộ đệm ẩn - bộ nhớ cache đối tượng và bộ đệm truy vấn. Entity caching là bộ nhớ cache phiên (và cache cấp 2, nếu được kích hoạt).

Giả sử bộ nhớ đệm truy vấn không được bật (mặc định không theo mặc định), sau đó HQL của bạn sẽ được thực thi đối với cơ sở dữ liệu. Điều này sẽ trả về các ID của các thực thể phù hợp với truy vấn. Nếu những thực thể đó đã có trong bộ nhớ cache phiên, thì Hibernate sẽ trả lại những thứ đó, thay vì xây dựng lại chúng từ cơ sở dữ liệu. Nếu phiên của bạn có các bản sao cũ của chúng (vì một phiên khác đã cập nhật cơ sở dữ liệu), thì đó là vấn đề bạn có.

Tôi khuyên bạn không nên sử dụng các phiên có thời gian tồn tại lâu dài, chủ yếu vì lý do đó. Bạn nên hạn chế tuổi thọ của phiên làm việc với đơn vị công việc cụ thể mà bạn đang cố gắng làm, và sau đó đóng nó lại. Có rất ít hoặc không có hình phạt hiệu suất để làm điều này (giả sử bạn sử dụng một hồ bơi kết nối cơ sở dữ liệu). Ngoài ra, để đảm bảo bạn không có được thực thể cũ, bạn có thể gọi Session.clear(), nhưng bạn có thể kết thúc với các hiệu ứng phụ không mong muốn.

+0

vì vậy lần đầu tiên đối tượng phiên của tôi thực hiện truy vấn HQL nó nhắm mục tiêu đến db. kết quả sau đó được lưu trữ trong bộ nhớ cache phiên. sau đó lần thứ hai tôi thực hiện cùng một truy vấn HQL, nó đọc bộ nhớ cache thay vì nhắm mục tiêu cơ sở dữ liệu. Đây là hành vi mặc định. tôi đã hiểu điều này một cách chính xác chưa? ** ps: ** thực sự, các phiên kết thúc sau mỗi lần đọc và ghi (các đối tượng 'Session' ngắn ngủi) giải quyết được vấn đề của tôi. – alegen

+4

@alegen: HQL sẽ được chạy dựa vào cơ sở dữ liệu * mỗi lần *, nhưng các đối tượng Java là kết quả cuối cùng của truy vấn đó có thể đến từ bộ nhớ cache phiên. Đây là hành vi mặc định. – skaffman

+1

bạn có một ngày tuyệt vời! Cảm ơn bạn cho câu trả lời của bạn :) – alegen

Các vấn đề liên quan