• 트랜잭션 범위의 영속성 컨텍스트 전략이 기본이다

  • 트랜잭션범위(=영속성 컨텍스트 범)에 있지않는 뷰 레벨(컨트롤러 등)에서 엔티티에 접근을 하다가 LazyInitailize Exception 이 발생!

  • 원인 사례 : 

    • " 어 나는 뷰에는 이 엔티티의 필드를 좀 암호화해서 넘기구싶어" 것을 원할수가 있음

    • " 뷰 레벨에서 나중에 (Lazy) 꺼내 써야지~ 지금은 당장 필요없으니깐~"

  • Lazy InitializeException을 해결하는 방법이 뭐가 있을까?

    • 뷰 레벨전에 엔티티를 미리 초기화하는 방법이 있겠네

      • 그럼 뷰 레벨전에 엔티티를 초기화하는 방법엔 뭐가있을까?

        • 글로벌 페치 전략 수정

          • Entity에 fetchType Eager로 지정

          • 사용하지 않을수도있는 엔티티 까지도 로딩해서 메모리 문제.. 여기까진 OK

          • 일반 JPA 메소드로 조회했을떄는 이너조인해서 잘 가져온다 문제가없다.. 근데? JPQL을 사용하게 되면 N+1 문제가 발생한다

        • JPQL 페치 조인

          • 위의 N+1문제를 해결하기 위해 JPQL을 쓸때는 페치 조인을 쓴다. 

        • 강제로 초기화(Facade)

          • 이것도 아니면 Lazy 로딩인걸 무조건 initialize하는 계층인 facade 계층을 하나 만든다.(Controller <-> facade <-> service)

    • 뷰 레벨전에 엔티티를 미리 초기화의 문제점

      • 누가 뷰 만들때 이 엔티티가 초기화 잘됐는지까지 확인해.. 그냥 뷰만 딱 만들지..너무 모델뷰간의 의존성이 높아진다..

    • 그러면 Lazy InitializeException 가장 좋은방법은 OSIV 적용!

      • 스프링의 예전 OSIV

        • 요청당 트랜잭션 방식의 OSIV , 즉 요청이 들어오는 즉시(필터/인터셉터부터) 트랜잭션 시작!  영속성컨텍스트도 똑같이 시작!

          • 문제점 : 뷰레벨에서 모델에 셋을할수있음. 즉 데이터가 바뀔수있음 뷰레벨에서.

      • 지금의 스프링 OSIV

        • 서비스단에서 트랜잭션 시작!  영속성컨텍스트는 필터/인터셉터부터 시작

+ Recent posts