OSIV Anti-Pattern
Thay vì để lớp nghiệp vụ quyết định cách tốt nhất để tìm nạp tất cả các liên kết mà lớp Chế độ xem cần, OSIV (Phiên mở trong Chế độ xem) buộc Ngữ cảnh bền vững luôn mở để lớp Chế độ xem có thể kích hoạt khởi tạo Proxy, như minh họa bằng sơ đồ sau.

- Các
OpenSessionInViewFiltercuộc gọi openSessionphương thức của cơ sở SessionFactoryvà nhận được một mới Session.
- Các
Sessionràng buộc với TransactionSynchronizationManager.
- Các
OpenSessionInViewFiltergọi doFiltercủa javax.servlet.FilterChaintham chiếu đối tượng và yêu cầu được tiếp tục chế biến
- Nó
DispatcherServletđược gọi và nó định tuyến yêu cầu HTTP đến bên dưới PostController.
- Các
PostControllerlệnh gọi PostServiceđể lấy danh sách các Postthực thể.
- Giao dịch
PostServicemở ra một giao dịch mới và HibernateTransactionManagersử dụng lại giao dịch Sessionđã được mở bởi OpenSessionInViewFilter.
- Các
PostDAOfetches các danh sách các Postthực thể mà không cần khởi tạo bất cứ tổ chức lười biếng.
- Giao dịch
PostServicecam kết giao dịch cơ bản, nhưng Sessionkhông bị đóng vì nó được mở bên ngoài.
- Các
DispatcherServletrender giao diện người dùng, trong đó, đến lượt nó, điều hướng các hiệp hội lười biếng và gây nên khởi tạo của họ bắt đầu.
- Có
OpenSessionInViewFilterthể đóng Session, và kết nối cơ sở dữ liệu cơ bản cũng được phát hành.
Thoạt nhìn, điều này có vẻ không phải là một việc tồi tệ để làm, nhưng một khi bạn xem nó từ góc độ cơ sở dữ liệu, một loạt lỗi bắt đầu trở nên rõ ràng hơn.
Lớp dịch vụ mở và đóng một giao dịch cơ sở dữ liệu, nhưng sau đó, không có giao dịch rõ ràng nào diễn ra. Vì lý do này, mọi câu lệnh bổ sung được đưa ra từ giai đoạn kết xuất giao diện người dùng được thực thi ở chế độ cam kết tự động. Tự động cam kết gây áp lực lên máy chủ cơ sở dữ liệu vì mỗi câu lệnh phải chuyển nhật ký giao dịch vào đĩa, do đó gây ra nhiều lưu lượng I / O trên phía cơ sở dữ liệu. Một tối ưu hóa sẽ là đánh dấu Connectionlà chỉ đọc sẽ cho phép máy chủ cơ sở dữ liệu tránh ghi vào nhật ký giao dịch.
Không có sự tách biệt của các mối quan tâm nữa vì các câu lệnh được tạo ra bởi cả lớp dịch vụ và quá trình kết xuất giao diện người dùng. Viết các bài kiểm tra tích hợp xác nhận số lượng câu lệnh được tạo yêu cầu phải đi qua tất cả các lớp (web, dịch vụ, DAO) trong khi triển khai ứng dụng trên vùng chứa web. Ngay cả khi sử dụng cơ sở dữ liệu trong bộ nhớ (ví dụ: HSQLDB) và máy chủ web nhẹ (ví dụ: Jetty), các thử nghiệm tích hợp này sẽ thực thi chậm hơn so với nếu các lớp được tách biệt và các thử nghiệm tích hợp phía sau sử dụng cơ sở dữ liệu, trong khi các bài kiểm tra tích hợp front-end đang chế giễu hoàn toàn lớp dịch vụ.
Lớp giao diện người dùng được giới hạn trong việc điều hướng các liên kết có thể kích hoạt N + 1 sự cố truy vấn . Mặc dù Hibernate cung cấp @BatchSizecác liên kết tìm nạp theo lô và FetchMode.SUBSELECTđể đối phó với trường hợp này, các chú thích đang ảnh hưởng đến kế hoạch tìm nạp mặc định, vì vậy chúng được áp dụng cho mọi trường hợp sử dụng kinh doanh. Vì lý do này, truy vấn lớp truy cập dữ liệu phù hợp hơn nhiều vì nó có thể được điều chỉnh cho phù hợp với các yêu cầu tìm nạp dữ liệu ca sử dụng hiện tại.
Cuối cùng nhưng không kém phần quan trọng, kết nối cơ sở dữ liệu được tổ chức trong suốt giai đoạn kết xuất giao diện người dùng, điều này làm tăng thời gian thuê kết nối và hạn chế thông lượng giao dịch tổng thể do tắc nghẽn trên nhóm kết nối cơ sở dữ liệu. Kết nối càng được giữ, thì càng có nhiều yêu cầu đồng thời khác sẽ phải chờ để nhận được kết nối từ nhóm.
Spring Boot và OSIV
Thật không may, OSIV (Open Session in View) được bật theo mặc định trong Spring Boot và OSIV thực sự là một ý tưởng tồi từ góc độ hiệu suất và khả năng mở rộng .
Vì vậy, hãy đảm bảo rằng trong application.propertiestệp cấu hình, bạn có mục nhập sau:
spring.jpa.open-in-view=false
Thao tác này sẽ vô hiệu hóa OSIV để bạn có thể xử lý LazyInitializationExceptionđúng cách .
Bắt đầu với phiên bản 2.0, Spring Boot đưa ra cảnh báo khi OSIV được bật theo mặc định, vì vậy bạn có thể phát hiện ra sự cố này rất lâu trước khi nó ảnh hưởng đến hệ thống sản xuất.
Để biết thêm chi tiết về OSIV, hãy xem bài viết này .