Thuộc tính spring.jpa.open-in-view = true này trong Spring Boot là gì?


121

Tôi đã thấy spring.jpa.open-in-view=truethuộc tính trong tài liệu Spring Boot cho cấu hình JPA.

  • Có phải truegiá trị mặc định cho thuộc tính này không nếu nó không được cung cấp ?;
  • Điều này thực sự làm gì? Tôi đã không tìm thấy bất kỳ giải thích tốt cho nó;
  • Nó có làm cho bạn sử dụng SessionFactorythay vì EntityManagerFactory? Nếu có, làm thế nào tôi có thể thông báo nó cho phép tôi sử dụng EntityManagerFactorythay thế?

Cảm ơn!

Câu trả lời:


52

Thuộc tính này sẽ đăng ký một OpenEntityManagerInViewInterceptor, đăng ký một EntityManagerchuỗi hiện tại, vì vậy bạn sẽ có như vậy EntityManagercho đến khi yêu cầu web kết thúc. Nó không liên quan gì đến Hibernate, SessionFactoryv.v.


Hiện tại, tôi có bộ lọc OpenEntityManagerInViewFilter để kiểm soát EntityManager cho đến khi yêu cầu web hoàn tất. Bộ chặn này mà bạn muốn nói là "OpenEntityManagerInViewInterceptor" có giống với "OpenEntityManagerInViewFilter" không? Sự khác biệt giữa chúng là gì? Vì vậy, tôi sẽ không có thêm bộ lọc này trong ngữ cảnh servlet của tôi cho Spring Boot?
Carlos Alberto

1
Bộ chặn chỉ hoạt động khi bạn sử dụng DispatcherServlet trong Spring (vì bộ chặn là một cơ chế Spring). Bộ lọc có thể được ánh xạ tới tất cả các servlet đã định cấu hình (chúng tôi sử dụng nó cho FacesServlet trong một trong các ứng dụng của chúng tôi). Vì vậy, nếu bạn chỉ sử dụng DispatcherServlet, bạn có thể thêm thuộc tính và xóa bộ lọc, nếu không hãy sử dụng bộ lọc.
dunni

298

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.

nhập mô tả hình ảnh ở đây

  • 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
  • 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.
  • 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 .


14
Có một CẢNH BÁO đang được ghi ngày nay.
Vlad Mihalcea

Điều này có áp dụng cho Spring nói chung hay chỉ Spring Boot? Có thể tắt tính năng này thông qua lớp chú thích @ Cấu hình thay vì đặt thuộc tính không?
Gordon

2
Nó chỉ áp dụng cho Spring Boot. Trong Spring tiêu chuẩn, bạn chọn rõ ràng loại đậu nào sẽ sử dụng hoặc bạn muốn một Bộ lọc web, như OSIV. Tôi không biết liệu bạn có thể tắt nó thông qua một số chú thích hay không. Tôi chỉ biết về cài đặt cấu hình.
Vlad Mihalcea

Nó không phải là một kiểu chống đối. Nó có tác động đến hiệu suất, đôi khi tiêu cực, nhiều khi khá trung lập và theo hướng tích cực trong nhiều trường hợp: nếu bạn thực sự muốn bắt đầu một quan hệ lười biếng, bạn không cần phải thực hiện truy vấn trong mọi trường hợp và có thể tránh nó khi cần bằng cách sử dụng chế độ xem mở.
ymajoros

5
Theo Wikipedia, "Phản ứng kiểu là một phản ứng phổ biến đối với một vấn đề lặp lại thường không hiệu quả và có nguy cơ phản tác dụng cao". Đó chính xác là những gì Phiên mở trong Chế độ xem.
Vlad Mihalcea
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.