spring.jpa.open-in-view=trueJPA 구성에 대한 Spring Boot 문서에서 속성을 보았습니다 .
true이 속성이 전혀 제공되지 않은 경우 기본값 입니까 ?;- 이것이 실제로 무엇을합니까? 나는 그것에 대해 좋은 설명을 찾지 못했습니다.
SessionFactory대신 사용EntityManagerFactory합니까? 그렇다면EntityManagerFactory대신 사용하도록 허용하려면 어떻게해야합니까?
감사!
답변
이 속성은 현재 스레드에 OpenEntityManagerInViewInterceptor를 등록하는를 등록 EntityManager하므로 EntityManager웹 요청이 완료 될 때까지 동일한 속성을 갖게됩니다 . Hibernate SessionFactory등과 는 관련이 없습니다 .
답변
OSIV 안티 패턴
비즈니스 계층이 View 계층에 필요한 모든 연결을 가져 오는 것이 가장 좋은 방법을 결정하도록하는 대신 OSIV (Open Session in View)는 그림과 같이 View 계층이 프록시 초기화를 트리거 할 수 있도록 Persistence Context를 강제로 열어 둡니다. 다음 다이어그램으로.
- 가
OpenSessionInViewFilter부르는openSession기본 방법을SessionFactory새로운를 가져옵니다Session. - 는
Session에 바인딩됩니다TransactionSynchronizationManager. - 는
OpenSessionInViewFilter부르는doFilter의javax.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 가 경고를 발행 하므로 프로덕션 시스템에 영향을 미치기 훨씬 전에이 문제를 발견 할 수 있습니다.

