2012-05-19 23 views
11

Tôi đang sử dụng Hibernate với Spring trên Tomcat. Tôi đã đọc và đọc lại oft chỉ đến JBoss wiki page về chủ đề, và điều đó rất hữu ích. Nhưng nó để lại cho tôi một số câu hỏi.Phiên mở cửa Hibernate trong Chế độ xem: Giao dịch cho mỗi yêu cầu?

  1. Ý tưởng bắt đầu giao dịch cho mọi yêu cầu làm phiền tôi. Tôi đoán tôi có thể giới hạn các bộ lọc để điều khiển nhất định - có thể đặt tất cả các bộ điều khiển của tôi cần một giao dịch dưới một pseudo "tx" đường dẫn hoặc một cái gì đó. Nhưng nó không phải là một ý tưởng tồi để sử dụng các giao dịch nếu bạn không biết nếu bạn sẽ cần một giao dịch? Và nếu tôi chỉ đang đọc trong một số yêu cầu - đọc rất có thể đến từ một bộ nhớ cache - không phải là tôi tốt hơn mà không có một giao dịch?

  2. Tôi đã đọc các bài đăng đề cập đến cách họ xử lý giao dịch ở lớp dịch vụ và tôi muốn làm điều này với Spring. Nhưng sau đó mã bộ lọc trông như thế nào? Tôi vẫn muốn các phiên có sẵn trong quan điểm của tôi cho một số tải lười biếng.

  3. Nếu tất cả những gì tôi phải làm là gọi sessionFactory.getCurrentSession() trong bộ lọc của tôi, làm cách nào để "giải phóng" trở lại nhà máy phiên để sử dụng lại? (Tôi dự kiến ​​sẽ thấy session.close() hoặc một cái gì đó, ngay cả khi sử dụng giao dịch.) Ai đang nói cho nhà máy phiên rằng phiên đó có thể được sử dụng lại?

  4. Có lẽ đó là cuộc gọi beginTransaction() liên kết kết nối cơ sở dữ liệu đã cho với một phiên nhất định trong thời gian yêu cầu? Nếu không, phiên sẽ kéo các kết nối db từ nhóm nếu cần, phải không?

Cảm ơn sự kiên nhẫn của bạn với tất cả các câu hỏi của tôi.

(Và nếu câu trả lời của bạn sẽ là một liên kết đến tài liệu Spring, bạn sẽ khiến tôi khóc. Bạn không muốn điều đó, phải không? Tôi sẽ trả tiền thật nếu mọi người ngừng trả lời Spring các câu hỏi liên quan theo cách đó.)

Trả lời

20

Mối quan tâm của bạn hợp lệ, giải pháp được cung cấp trên trang wiki quá đơn giản. Giao dịch không nên được quản lý ở lớp web - nó phải được xử lý ở lớp dịch vụ.

Việc triển khai chính xác sẽ mở một phiên và liên kết nó với một chuỗi trong bộ lọc. Không có giao dịch nào được bắt đầu. Phiên này được đặt ở chế độ tuôn ra không bao giờ - chế độ chỉ đọc. Cuộc gọi dịch vụ sẽ đặt phiên thành chế độ tự động tuôn ra & bắt đầu/cam kết giao dịch. Khi phương thức dịch vụ kết thúc chế độ xả phiên được hoàn nguyên về không bao giờ.

Ngoài ra còn có một tùy chọn để không mở phiên trong bộ lọc. Mỗi cuộc gọi lớp dịch vụ sẽ mở một phiên riêng biệt & giao dịch - sau khi cuộc gọi dịch vụ được thực hiện, phiên này không được đóng, nhưng đã đăng ký để hoãn trả chậm. Phiên sẽ bị đóng sau khi quá trình xử lý yêu cầu web hoàn tất.

Mùa xuân cung cấp OpensessionInViewFilter hoạt động như mô tả ở trên. Vì vậy, bỏ qua bài viết wiki jboss và chỉ cần cấu hình OpensessionInViewFilter - mọi thứ sẽ ổn.

SessionFactory.getCurrentSession() - tạo nội bộ và gán phiên cho một chuỗi cục bộ. Mỗi yêu cầu/chủ đề sẽ có phiên riêng của nó. Khi xử lý yêu cầu web hoàn tất, phiên sẽ bị đóng. Từ bên trong mã của bạn, bạn chỉ cần sử dụng SessionFactory.getCurrentSession() và không phải đóng nó lại. Mẫu mã trên trang wiki jboss là sai - nó phải có một SessionFactory.getCurrentSession(). Close() trong khối cuối cùng.Hoặc họ có thể đang sử dụng giao dịch JTA và cấu hình ngủ đông để mở/đóng phiên kết hợp với giao dịch JTA.

+0

Tôi đã đi từ đây đến đó và sau đó đến đó, bỏ qua web về chủ đề này trong một tuần ... và đó là lần đầu tiên tôi đọc rằng Spring có bộ lọc OpenSessionInView. Cảm ơn bạn. – Marvo

+0

Con người, điều đó hoạt động rất đẹp. Cảm ơn! – Marvo

+0

Tôi luôn nghĩ rằng nó sẽ hoạt động như một giao dịch. Nhưng thực sự giao dịch được giới hạn bởi @Transactional của mùa xuân. Cảm ơn lời giải thích. –

0

Nó không phải là một vấn đề nếu bộ lọc tạo ra một phiên cho mỗi yêu cầu, bởi vì các phiên đến từ một nhóm phiên, và chúng sẽ được tái sử dụng. Từ quan điểm của hệ điều hành, không có gì xảy ra.

Một phiên ngủ đông là, bởi thực tế, kết nối tcp (hoặc ổ cắm/ống) với máy chủ cơ sở dữ liệu. Chi phí của việc tạo ra conn conn là rất phụ thuộc vào loại sql (postgresql đáng chú ý là xấu trong này, nó rất tốt trong mọi thứ). Nhưng nó không có nghĩa là thực sự bất cứ điều gì, bởi vì hibernate reuses các kết nối cơ sở dữ liệu.

Giải pháp bộ lọc hibernate đơn giản cũng bắt đầu một giao dịch mới trên phiên cho mọi yêu cầu. Nó là giao dịch từ khung nhìn của SQL: đó là truy vấn "BEGIN" và "COMMIT". Nó luôn luôn tốn kém, và điều này nên được giảm.

IMHO một giải pháp có thể là, nếu các giao dịch chỉ được bắt đầu tại truy vấn đầu tiên của yêu cầu hiện tại. Có lẽ mùa xuân có cái gì đó có thể sử dụng cho việc này.

+1

Những gì chúng tôi đến là sử dụng bộ lọc OpenSessionInView (xem ở trên) kết hợp với chú thích Spring @Transactional. Cho đến nay nó hoạt động tuyệt vời. – Marvo

+0

@Marvo Tôi không có trải nghiệm tuyệt vời như vậy. Bạn không có quyền kiểm soát, những gì chính xác xảy ra và tại sao. Trong dự án cuối cùng của tôi, tôi đã có nhiều kết nối cơ sở dữ liệu (một số thực thể kết nối đầu tiên, một số đến thứ hai) với các lớp mùa xuân chỉ đạo chéo và một số quy trình từ Quartz bắt đầu, một số từ web. Tình hình rất phức tạp và vấn đề chính là trong một điều chú thích- hoặc/và dựa trên AOP bạn có rất rất kiểm soát để kiểm tra, những gì không thành công hoặc đâu là vấn đề. Nó chỉ đơn giản là hoạt động hay không, nhưng bạn không thể nhìn thấy chúng. Trong một môi trường thủ tục rõ ràng nó là tầm thường. – peterh

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