일대일

주 테이블이나 대상 테이블 중에 외래키 선택가능

주 테이블에 외래 키 단방향으로 설정. MEMBER를 주 테이블로 설정.

그림1. 주 테이블에 외래 키 단방향

주 테이블에 외래 키 양방향

그림2.주 테이블에 외래 키 양방향

다대일 양방향 매핑 처럼 외래 키가 있는 곳이 연관관계의 주인 • 반대편은 mappedBy 적용

일대일 : 대상 테이블(주 테이블❌)에 외래키, 단방향으로 있는 경우 단방향 관계는 JPA 지원양방향 관계는 지원🆗⭐️⭐️⭐️⭐️⭐️ 주테이블에 FK가 있어야하는데 대상테이블에 FK가 있으면 안 된다? => 그럼 대상테이블을 주테이블로 하면 안되나?

그림3
그림4. 대상 테이블에 FL 양방향

사실 일대일관계는 어느 쪽에 FK를 두든 상관없지만, 각각의 장단점이 있다!

  1. LOCKER를 주 테이블로 하고, FK를 관리(DBA 입장에서 확장성이 좋음) 생각해봤을 때 한 회원이 여러개의 라커를 사용할 수 있다면?! 위의 테이블 관계도에서 LOCKER 테이블에 FK인 MEMBER_ID에 UNI 조건만 빼면된다!

  2. MEMBER를 주테이블로 하고, FK를 관리(개발자 입장에서 성능적으로 더 유리) =>여러 회원이 한 라커를 사용하는 경우에 적합. 마마찬가지로 MEMBER 테이블의 FK인 LOCKERID에서 UNI 조건만 빼면 된다. =>비즈니스 로직상 Member를 주로 조회해서 Locker의 유무에 따른 로직을 처리하는 경우. 왜냐하면 대부분의 비즈니스의 경우 Member는 기본적으로 다 조회를 한다. Member의 Locker를 조회할 때에도 조인없이 바로 가져올 수 있다.

정리해보면, 명확하게 일대일 관계일 경우 비즈니스 로직을 생각해서 좀더 많이 조회하는 객체를 주테이블로 잡고 FK 관리하도록 한다. 하지만 개인차, 회사의 DBA마다 달라진다.

/*대상 테이블에 외래키

치명적인 단점 : Member의 라커를 조회할 땐 MEMBER 테이블만 조회하는 것이 아니라 LOCKER 테이블도 함께 조회해야 한다. 그림 4 참고. 그러면 LOCKER 테이블 뒤져서에서 WHER문으로 조회해서 LOCKER값이 있다고 떠야 인정된다.

프록시를 넣거나 null을 넣거나 해줘야한다. 있는지 없는지 확인부터 해야한다.

어차피 쿼리가 나가기 때문에 프록시로 만들 필요 없다.

=>일대일 관계이고, 대상 테이블에 외래키 있으면 무조건 지연로딩된다!*/

일대일 정리

  1. 주 테이블에 FK : 객체지향 개발자 선호 주 객체가 대상 객체의 참조를 갖는 것처럼 주 테이블에 외래 키를 두고 대상 테이블을 찾음 JPA 매핑 편리 장점: 주 테이블만 조회해도 대상 테이블에 데이터가 있는지 확인 가능 단점: 값이 없으면 외래 키에 null 허용

  2. 대상 테이블에 FK : 전통적인 데이터베이스 개발자 선호 장점: 주 테이블과 대상 테이블을 일대일에서 일대다 관계로 변경할 때 테이블 구조 유지 단점: 프록시 기능의 한계로 지연 로딩으로 설정해도 항상 즉시 로딩됨(프록시는 뒤에서 설명)

프록시 : 지연 로딩으로 설정했을 때, 연관된 엔티티가 있으면 프록시 객체가 대신 들어가면 되지만 연관된 엔티티가 없으면 null이 들어가야 한다. 주 테이블에 외래 키가 있으면 값이 있는지 없는지 주 테이블을 로딩하는 시점에 외래 키 컬럼을 보고 바로 확인할 수 있다. 그래서 값이 있으면 연관관계...하고, 값이 없으면 null을 설정한다.

프록시와 즉시로딩, 그림4의 대상테이블에 FK가 있는 양방향 관계 참고

하지만 대상테이블에 외래키가 있는 양방향 관계인 경우, 주테이블이 아니라 대상 테이블을 조회해야한다. 그러면 대상 테이블에 쿼리가 들어가야만 Member의 연관된 엔티티 locker에 값이 있는지 없는지 알 수 있다. 그렇기 때문에 (쿼리 없이) 값이 있는 경우 프록시 객체를, 값이 없는 경우 null을 넣는데, 이 값의 유무를 알기 위해서는 어찌 됐든 쿼리를 넣어야하기 때문에 항상 즉시 로딩하는 수 밖에 없다. 잠재된 가정 : 프록시는 쿼리를 하지 않고 만드는 임시 객체.

Last updated