class OrderController { ... public String view(Long orderId) { Order order = orderService.findOne(orderId); Member member = order.getMember(); member.getName(); // 지연 로딩시 예외 발생 ... } }

김영한님 JPA 책 내용임 현재 서비스 레이어에서 트랜잭션이 시작해 끝나고 있음 (OSIV는 꺼져있음)

프레젠테이션 레이어에서 서비스 레이어를 통해 Order 엔티티를 받아옴

트랜잭션이 서비스 레이어에서 종료되었으므로 Order는 준영속상태

따라서 Order 안 Member 프록시에 지연로딩을 시도하면 실패




class OrderService { ... @Transactional public Order findOne(Long id) { Order order = orderRepository.findOne(id); order.getMember().getName(); // 프록시를 강제로 초기화 return order; } }

이를 해결하기 위한 방안 중 하나로 트랜잭션 실행중인 서비스 레이어에서 미리 로딩을 해볼수 있지만 레이어간 침투 문제가 생김




class OrderFacade { @Autowired private OrderService orderService public Order findOne(Long id) { Order order = orderService.findOne(id); order.getMember().getName(); // 프록시를 강제로 초기화 return order; } }

따라서 파사드 레이어를 하나 껴놓고 여기서 미리 로딩을 해볼수도 있다...라는 얘기인데 여기서 의문이 생김


파사드 클래스의 findOne를 보면 Transactional 어노테이션이 없음

따라서 트랜잭션은 여전히 서비스 레이어에서 시작해 끝남

그렇다면 파사드쪽 또한 프레젠테이션쪽과 마찬가지로 준영속상태의 Order가지고 레이지 로딩을 시도해 익셉션이 나야하지 않나?


저작권 문제로 올리기는 좀 그렇지만 책의 도식에서는 파사드 레이어까지 트랜잭션을 가지고 가려는 의도가 맞는데 어노테이션 없이 어찌그리되는지...

Transaction 어노테이션이나 EntityManager에서 트랜잭션을 받아오는 것이나 OSIV 외에 암묵적으로 트랜잭션을 생성 및 유지시켜주는 다른 메카니즘이 있는건가?