해결된 질문
작성
·
567
5
안녕하세요 강사님 오랜만에 또 돌려보네요.!
다름이 아니라 OneToOne 연관 관계에서
Member입장에서는 Lokcer가 있는지 알려면 Locker 테이블을 찾아야 하기 떄문에, 프록시로 설정할 이유가 없다고 하셨습니다. (여기 까진 이해 했습니다)
그런데 그럼
public class Team {
@ManyToOne
List<Member> members = new ArrayList<>();
}
Team도 마찬가지로 member_id 컬럼이 실제 DB에 없기 떄문에 Member테이블을 조회해야하는 하는데, 여기서는 프록시가 동작하는 이유에 대해서 궁금합니다.
@ManyToOne에서는 지연로딩이 동작하고,
@OneToOne에서만 동작하지 않는 이유가 궁금합니다. (둘 다 값이 없어서 상대 테이블을 조회해야 하는데도 불구하고)
답변 1
9
안녕하세요. 참치캔님^^
좋은 질문입니다.
우선 예시로 남겨주신 내용 중에 정정할 부분이 있습니다.
컬렉션에 @ManyToOne을 사용할 수는 없으므로 @OneToMany로 변경해야 합니다.
이 내용을 이해하려면 값이 없을 때 어떻게 되는가를 이해해야 합니다.
예를 들어서 A,B 엔티티가 다음과 같이 설정이 되어 있습니다.
외래키는 B에 있고, B가 연관관계의 주인입니다.
A {
@OneToOne B b
}
만약 b의 결과가 없다면 어떻게 노출되어야 할까요?
바로 결과는 null이 되어야 합니다.
그런데 만약 A -> B가 지연로딩 관계라면 b는 프록시 객체가 되어야 합니다.
여기에서 문제가 발생합니다.
만약 이 상황에서 프록시를 적용하기 위해서 b가 프록시 객체가 된다면 b는 null이 아니라 프록시 객체를 가지게 됩니다.
이런 상황에서 a.b를 호출한다면 우리가 기대하는 결과는 null이어야 하는데, 프록시가 되겠지요?
결국 프록시를 미리 넣게되면 null이라는 것을 넣을 수 없는 문제가 발생합니다.
@OneToOne에서 외래키가 A에 있으면 A를 조회하는 순간 B의 데이터가 있는지 확인할 수 있습니다. 그래서 null을 입력해야 할지, 아니면 프록시를 입력해야 할지 명확한 판단이 가능하지요.
그런데 지금 처럼 @OneToOne에서 외래키가 B에 있으면 A를 조회할 때 B가 데이터가 있는지 없는지 판단이 불가능합니다. 그래서 null을 입력할지 아니면 프록시를 입력해야 할지 판단히 불가능합니다. 따라서 이 경우 강제로 즉시 로딩을 해서 데이터가 있으면 해당 데이터를 넣고, 없으면 null을 입력하게 됩니다.
자 그러면 컬렉션의 경우에는 어떻게 될까요?
컬렉션은 재미있게도 null일 필요가 없습니다. 컬렉션 자체가 데이터가 없는 Empty를 표현할 수 있습니다.
따라서 컬렉션은 항상 지연로딩으로 동작할 수 있습니다.
도움이 되셨길 바래요^^
안녕하세요. chlwnsdud121님
이 문제는 @OneToOne 연관관계에서만 발생하는 특별한 문제입니다.
다음 내용을 참고해주세요^^
https://www.inflearn.com/questions/40670
https://www.inflearn.com/questions/179434
감사합니다.
명쾌한 답변 감사합니다!!
이런 현상이 발생한 근본적인 이유는 mappedBy된 대상이 실제 테이블에 반영이 되지 않기 때문이라고 이해한 것이 맞을까요??