작성
·
282
0
답변 3
1
안녕하세요. 최태훈님
단순하게 생각해보면 간단합니다.
member -> locker 라는 참조가 있습니다.
그런데 만약에 locker라는 데이터가 없다고 가정해보겠습니다.
그러면 member -> null(locker의 참조)이 되어야 합니다.
null은 객체가 아니기 때문에 프록시로 감싸거나 하는것이 불가능합니다.
member -> locker(프록시, null 데이터) null인데 이렇게 하면 이미 locker는 null이 아니라 객체(프록시)가 되어버립니다.
감사합니다.
0
안녕하세요. 최태훈님
많이 고민하시는 모습이 좋네요^^ 사실 저도 이전에 이 문제 때문에 고민을 많이 했습니다.
답을 말씀드리면,
JPA 스펙에서 값이 없는 경우에는 null이어야 하는 규약이 있습니다.
그런데 프록시를 두게 되면 이미 null이 아니라 프록시 객체가 됩니다. 이것 자체가 문제가 되는 것이지요.
예를 들어서 값이 없는 경우 member.locker == null 이라는 공식 자체가 실패하게 되는 것입니다. 값이 없는 경우에도 프록시 객체가 들어있게 되니까요.
대안으로는 프록시 대신에 바이트 코드를 직접 조작하는 로드 타임 위빙이라는 기술을 사용하면 가능하기는 하지만 설정이 너무 복잡하고, 다른 문제들이 추가로 발생할 수 있어서 잘 사용하지는 않습니다.
감사합니다.
0
영한님 답변주셔서 감사합니다.
말씀하신 예제를 구현해보았습니다.
실행결과는 당연히 아래와 같습니다.
첫번째 lock메소드에서 한번 real object가 로드되고 나머지 lock메소드 호출에서는 로드된 real object를 재사용합니다.
만약 여기서 하이버네이트 팀이 nullable proxy가 가능하도록 구현하였으면 애초에 저희가 FK가 없는쪽에서 lazy loading이 발생하지 않는 사태를 만들지 않을수있지 않았을까라는 의문이 자꾸 듭니다.
코드는 아래와 같습니다.
위 코드는 비록 client가 NPE에 노출되는 점은 있지만,
위의 흐름이 일반적인 관점에서 봤을때 사용자가 설정한 lazy메커니즘을 깨지않으면서 더 자연스러워 보일수도 있을것같습니다.
왜냐하면 클라이언트가 위코드처럼 lazy동작이 아니라 eager로 동작하게끔 설정해놔도
(현재 하이브네이트가 선택한 방식처럼..) fetch이후 null일거기 때문에 NPE에 노출 되는거는 똑같은거 같아보이거든요.
둘다 결국 member가 locker가 null인지 널체크를 하면서 lock()을 호출해야하는건 동일해보입니다.
제가 뭔가 잘못이해하고있는 것인지 고견을 주시면 감사하겠습니다.
좋은 하루되세요.