Để có mô tả dài hơn, bạn có thể đọc bài viết Chống mô hình phiên mở trong chế độ xem của tôi . Nếu không, đây là bản tóm tắt lý do tại sao bạn không nên sử dụng Open Session In View.
Mở phiên trong chế độ xem có một cách tiếp cận xấu để tìm nạp dữ liệu. 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, nó 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.

- 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.
- Tìm
PostDAOnạp danh sách các Postthực thể mà không cần khởi tạo bất kỳ liên kết lười biếng nào.
- 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ỗ hổng 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, điều này 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 ứng dụng được triển khai 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ế nhạo 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ó thể được giữ trong suốt giai đoạn kết xuất giao diện người dùng (tùy thuộc vào chế độ phát hành kết nối của bạn), đ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. Càng giữ nhiều kết nối, thì càng có nhiều yêu cầu đồng thời khác sẽ phải đợi để nhận được kết nối từ nhóm.
Vì vậy, hoặc bạn bị giữ kết nối quá lâu, hoặc bạn có được / giải phóng nhiều kết nối cho một yêu cầu HTTP duy nhất, do đó gây áp lực lên nhóm kết nối cơ bản và hạn chế khả năng mở rộng.
Khởi động mùa xuân
Rất tiếc, Open Session in View được bật theo mặc định trong Spring Boot .
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 .