2012-02-20 31 views
7

Tôi có nền tảng dựa trên Hibernate, được xây dựng từ các servlet không trạng thái (được sử dụng để đăng ký người dùng và phần còn lại để truy vấn db).Quản lý phiên với Java Hibernate

Tôi đang sử dụng phiên Hibernate như sau:

Session session = HibernateUtil.getSessionFactory().getCurrentSession(); 
if ((null == session) || (session.isOpen() == false)) { 
    session = HibernateUtil.getSessionFactory().openSession(); 
} 

Hiện nay tôi không đóng phiên ở phần cuối của servlet để tránh openSession() gọi (cố gắng sử dụng phiên mở nếu có thể).

Phương pháp hay nhất là gì? khi nào tôi phải đóng các phiên này?

Bạn có thể đưa ra ví dụ không?

Cảm ơn trước!

Trả lời

13

Phương pháp hay nhất là trong hầu hết các trường hợp phiên cho mỗi yêu cầu. Đó là, mở một phiên trong phần đầu của việc xử lý một yêu cầu, và đóng nó vào cuối. Bạn có thể làm điều đó trong một Servlet Filter, ví dụ.

Có một phiên cho toàn bộ ứng dụng là xấu, bởi vì nó sẽ tích lũy rất nhiều thực thể trong bộ nhớ cache cấp 1 của nó, đó là một rò rỉ bộ nhớ. Nó cũng có thể tạo ra kết quả không xác định khi nhiều khách hàng sử dụng nó cùng một lúc.

Mã của bạn, tuy nhiên, không sử dụng một phiên cho toàn bộ ứng dụng - nó đang sử dụng khái niệm "phiên hiện tại", mở phiên và lưu trữ trong ngữ cảnh (ví dụ: ThreadLocal). Nhưng nếu bạn không đóng nó, nó sẽ ở đó mãi mãi. Thêm vào đó, nó sẽ gây ra các vấn đề tương tự như mô tả ở trên, bởi vì các luồng được tái sử dụng trong một ứng dụng web và một yêu cầu mới sẽ nhận được một phiên cũ, không được tiết lộ tại một số điểm.

+0

Tôi đồng ý rằng một phiên cho toàn bộ ứng dụng là một ý tưởng tồi, nhưng làm thế nào về việc phiên hiện tại cho mỗi yêu cầu thay vì phiên gần mở, đặc biệt là khi bạn đang áp dụng mùa xuân và ngủ đông với nhau? – Shilan

3

Bạn nên mở phiên mới cho mọi yêu cầu và đóng phiên khi yêu cầu được xử lý. Giống như

Session session = HibernateUtil.getSessionFactory().openSession(); 

thay vì

Session session = HibernateUtil.getSessionFactory().getCurrentSession(); 

Nếu chúng ta sử dụng phương pháp getCurrentSession(), tansaction.commit()/rollback() đóng kết nối.

+0

"phiên mới cho mọi yêu cầu" là chống mẫu – zond

0

Cách tốt nhất là quản lý phiên ngủ đông là mở phiên mới cho mọi yêu cầu. Tất cả phụ thuộc vào cách bạn có được phiên.

  • nếu bạn sử dụng sessionFactory.getCurrentSession(), bạn sẽ có được một "phiên hiện tại" được ràng buộc với vòng đời của giao dịch và sẽ được tự động đỏ bừng mặt và đóng cửa khi giao dịch đầu (cam kết hoặc rollback)
  • nếu bạn quyết định sử dụng sessionFactory.openSession(), bạn sẽ phải tự mình quản lý phiên và xóa và đóng phiên "thủ công".
if (!session.isOpen()) { 
     session = session.getSessionFactory().openSession(); 
     session.beginTransaction(); 
} 
0

tôi tốt hơn khuyên bạn nên sử dụng khuôn khổ mùa xuân.Nguyên nhân vào mùa xuân, bạn có thể sử dụng @Transactional ở cấp phương thức và phiên sẽ được người quản lý giao dịch tạo và đóng tự động (trừ khi bạn đang sử dụng bất kỳ phiên mở nào trong trình chặn đánh chặn) sử dụng AOP được khung nội bộ xử lý.

@Autowired 
EntityManager em; 

@Transactinal 
void save(User user){ 
    em.persist(user); 
} 

thats all.spring là vui vẻ: D

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