Spring Boot의 spring.jpa.open-in-view = true 속성은 무엇입니까?


121

spring.jpa.open-in-view=trueJPA 구성에 대한 Spring Boot 문서에서 속성을 보았습니다 .

  • true이 속성이 전혀 제공되지 않은 경우 기본값 입니까 ?;
  • 이것이 실제로 무엇을합니까? 나는 그것에 대해 좋은 설명을 찾지 못했습니다.
  • SessionFactory대신 사용 EntityManagerFactory합니까? 그렇다면 EntityManagerFactory대신 사용하도록 허용하려면 어떻게해야합니까?

감사!

답변:


52

이 속성은 현재 스레드에 OpenEntityManagerInViewInterceptor를 등록하는를 등록 EntityManager하므로 EntityManager웹 요청이 완료 될 때까지 동일한 속성을 갖게됩니다 . Hibernate SessionFactory등과 는 관련이 없습니다 .


현재 웹 요청이 완료 될 때까지 EntityManager를 제어하는 ​​필터 OpenEntityManagerInViewFilter가 있습니다. 이 인터셉터는 "OpenEntityManagerInViewInterceptor"가 "OpenEntityManagerInViewFilter"와 동일합니까? 그들 사이의 차이점은 무엇입니까? 그래서 Spring Boot에 대한 서블릿 컨텍스트에이 필터가 더 없을까요?
Carlos Alberto

1
인터셉터는 Spring에서 DispatcherServlet을 사용할 때만 작동합니다 (인터셉터는 Spring 메커니즘이기 때문에). 필터는 구성된 모든 서블릿에 매핑 될 수 있습니다 (애플리케이션 중 하나의 FacesServlet에 사용됨). 따라서 DispatcherServlet 만 사용하는 경우 속성을 추가하고 필터를 제거 할 수 있습니다. 그렇지 않으면 필터를 사용할 수 있습니다.
dunni

299

OSIV 안티 패턴

비즈니스 계층이 View 계층에 필요한 모든 연결을 가져 오는 것이 가장 좋은 방법을 결정하도록하는 대신 OSIV (Open Session in View)는 그림과 같이 View 계층이 프록시 초기화를 트리거 할 수 있도록 Persistence Context를 강제로 열어 둡니다. 다음 다이어그램으로.

여기에 이미지 설명 입력

  • OpenSessionInViewFilter부르는 openSession기본 방법을 SessionFactory새로운를 가져옵니다 Session.
  • Session에 바인딩됩니다 TransactionSynchronizationManager.
  • OpenSessionInViewFilter부르는 doFilterjavax.servlet.FilterChain오브젝트 레퍼런스 및 요청이 더 처리
  • DispatcherServlet라고하며 기본에이를 라우팅 HTTP 요청한다 PostController.
  • PostController통화량은 PostService목록을 얻을 수 Post개체를.
  • PostService새 트랜잭션을 열고,이 HibernateTransactionManager같은 재사용 Session에 의해 열린이 OpenSessionInViewFilter.
  • PostDAO목록 가져 오는 Post어떤 게으른 관계를 초기화하지 않고 개체를.
  • PostService기본 트랜잭션을 커밋하지만은 Session그것이 외부에서 열렸다 때문에 닫히지 않았습니다.
  • DispatcherServlet차례로, lazy 연관을 탐색하고 자신의 초기화를 트리거 UI를 렌더링이 시작됩니다.
  • OpenSessionInViewFilter을 닫을 수 Session및 기본 데이터베이스 연결이 잘으로 해제됩니다.

언뜻보기에 이것은 끔찍한 일처럼 보이지 않을 수도 있지만 데이터베이스 관점에서 보면 일련의 결함이 더 분명해지기 시작합니다.

서비스 계층은 데이터베이스 트랜잭션을 열고 닫지 만 이후에는 명시적인 트랜잭션이 진행되지 않습니다. 이러한 이유로 UI 렌더링 단계에서 발행 된 모든 추가 문은 자동 커밋 모드에서 실행됩니다. 자동 커밋은 각 문이 트랜잭션 로그를 디스크로 플러시해야하므로 데이터베이스 측에서 많은 I / O 트래픽을 유발하므로 데이터베이스 서버에 부담을줍니다. 한 가지 최적화는를 Connection읽기 전용으로 표시 하여 데이터베이스 서버가 트랜잭션 로그에 쓰지 않도록하는 것입니다.

문은 서비스 계층과 UI 렌더링 프로세스 모두에서 생성되기 때문에 더 이상 문제가 분리되지 않습니다. 생성되는 문 수를 확인하는 통합 테스트를 작성 하려면 애플리케이션이 웹 컨테이너에 배포되는 동안 모든 계층 (웹, 서비스, DAO)을 거쳐야합니다. 인 메모리 데이터베이스 (예 : HSQLDB) 및 경량 웹 서버 (예 : Jetty)를 사용하는 경우에도 이러한 통합 테스트는 계층이 분리되고 백엔드 통합 테스트에서 데이터베이스를 사용하는 경우보다 실행 속도가 느립니다. 프런트 엔드 통합 테스트는 서비스 계층을 모두 조롱했습니다.

UI 레이어는 N + 1 쿼리 문제를 유발할 수있는 연결 탐색으로 제한됩니다 . Hibernate는 @BatchSize일괄 적으로 연관을 가져오고이 FetchMode.SUBSELECT시나리오에 대처하기 위해 제공하지만 주석은 기본 가져 오기 계획에 영향을 미치므로 모든 비즈니스 사용 사례에 적용됩니다. 이러한 이유로 데이터 액세스 계층 쿼리는 현재 사용 사례 데이터 가져 오기 요구 사항에 맞게 조정할 수 있기 때문에 훨씬 더 적합합니다.

마지막으로 데이터베이스 연결은 UI 렌더링 단계 내내 유지되므로 연결 임대 시간이 늘어나고 데이터베이스 연결 풀의 정체로 인해 전체 트랜잭션 처리량이 제한됩니다. 연결이 더 많이 유지 될수록 풀에서 연결을 얻기 위해 더 많은 다른 동시 요청이 대기하게됩니다.

스프링 부트와 OSIV

불행히도 OSIV (Open Session in View)는 Spring Boot에서 기본적으로 활성화되어 있으며 OSIV는 성능 및 확장 성 관점에서 볼 때 실제로 나쁜 생각입니다 .

따라서 application.properties구성 파일에 다음 항목이 있는지 확인하십시오 .

spring.jpa.open-in-view=false

이렇게하면 OSIV가 비활성화 되어 올바른 방법으로 처리LazyInitializationException 할 수 있습니다 .

버전 2.0부터는 OSIV 가 기본적으로 활성화 되면 Spring Boot 가 경고를 발행 하므로 프로덕션 시스템에 영향을 미치기 훨씬 전에이 문제를 발견 할 수 있습니다.

OSIV에 대한 자세한 내용은 이 기사를 확인 하십시오 .


14
현재 경고가 기록되고 있습니다.
Vlad Mihalcea

이것은 일반적으로 Spring에 적용됩니까, 아니면 Spring Boot에만 적용됩니까? 속성을 설정하는 대신 @Configuration 주석이 달린 클래스를 통해 비활성화 할 수 있습니까?
Gordon

2
Spring Boot에만 적용됩니다. 표준 Spring에서는 사용할 빈이나 OSIV와 같은 웹 필터를 원하는지 명시 적으로 선택합니다. 주석을 통해 비활성화 할 수 있는지 모르겠습니다. 구성 설정 만 알고 있습니다.
Vlad Mihalcea

안티 패턴이 아닙니다. 성능에 영향을 미치고 때로는 부정적이며 많은 경우 매우 중립적이며 많은 경우 긍정적 인 방식으로 영향을 미칩니다. 실제로 지연 관계를 시작하려면 모든 경우에 쿼리를 수행 할 필요가 없습니다. Open-in-View를 사용하여 필요할 때 피할 수 있습니다.
ymajoros

5
Wikipedia에 따르면, "반 패턴은 일반적으로 비효율적이고 매우 비생산적인 위험이있는 반복되는 문제에 대한 일반적인 반응입니다." 이것이 바로 Open Session in View의 의미입니다.
Vlad Mihalcea
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.