21. 일대일 [1:1]

김성수·2023년 4월 10일
0

⚡ 생각대로 살지 않으면 사는대로 생각한다.

⚡ 나는 어차피 잘 될 놈이다. 이미 잘 되고 있고, 계속해서 잘 되고 있다.


일대일

일대일 관계

  • 일대일 관계는 그 반대도 일대일
  • 주 테이블이나 대상 테이블 중외래 키 선택 가능
    • 주 테이블에 외래 키를 넣거나 대상 테이블에 외래 키를 넣거나 할 수 있음.
  • 외래 키데이터베이스 유니크(UNI) 제약조건 추가되어야 일대일 관계가 된다.
    • DB입장에서 외래 키에 데이터베이스 유니크 제약조건이 추가된 것일대일 관계이다.

일대일 : 주 테이블에 외래 키 단방향

위 그림처럼 MEMBER 테이블에 LOCKER_ID(FK, UNI) 제약조건을 넣어도 되지만, 반대로 LOCKER 테이블에 MEMBER_ID(FK, UNI)로 넣어도 된다.

일대일 : 주 테이블에 외래 키 단방향 정리

  • 다대일(@ManyToOne) 단방향 매핑과 유사

일대일 : 주 테이블에 외래 키 양방향

일대일 : 주 테이블에 외래 키 양방향 정리

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

일대일 : 대상 테이블에 외래 키 단방향

Member(객체)연관관계의 주인으로 하고싶은데, 외래 키LOCKER(테이블)에 있다.

Member(객체)Locker(필드)LOCKER(테이블)MEMBER_ID(외래 키)를 관리할 수 있는가 생각해보면, 할 수 없다. 이는 아예 지원하지도 않고, 방법이 없다.

일대일 : 대상 테이블에 외래 키 단방향 정리

단방향 관계는 JPA에서 지원하지 않는다.

하지만, 양방향 관계는 지원(아래 참고.)

일대일 : 대상 테이블에 외래 키 양방향

일대일 : 대상 테이블에 외래키 양방향

  • 사실 일대일 주 테이블에 외래 키 양방향과 매핑 방법은 같음
  • 일대일 관계에서 양방향으로 만들었는데, Member(객체)에서 Locker(필드)연관관계의 주인으로 하려고 할 때, 대상 테이블인 LOCKER(테이블)외래 키가 있다해도, 상관이 없다. 그냥 Locker(객체)Member(객체)연관관계의 주인으로 하고, LOCKER(테이블)의 **MEMBER_ID(외래 키)와 매핑해주면 된다.
  • 일대일 관계는 내가 내것만 관리하는 것이라고 보면 된다.

Member와 Locker 중 외래키를 어디에 놓는 게 좋을까?

  • 사실 어떤 방법을 쓰더라도 1:1 관계가 유효하다. 정답은 없다.
    • 테이블은 한 번 만들어지면, 변경이 어렵다.
  • 시간이 흘러서 한 명의 MEMBER가 여러개의 LOCKER를 가질 수 있게 되면, 아래의 그림테이블 관계(객체 관계 X)에서 LockerALTER를 써서 유니크 제약조건을 빼면 된다. 이 그림에선 보다 자연스러워진다.

그런데 MEMBER에 외래 키가 있을 때, 하나의 회원이 여러 개의 LOCKER를 사용할 수 있게 될 때, 아래의 그림처럼 관계 설정이 되어있으면, LOCKER에 컬럼을 추가하고, 기능을 변경해야한다. 변경 포인트가 많다.

그런데 비즈니스가 바껴서 하나의 LOCKER를 여러 MEMBER가 사용할 수 있다면, 위에 그림이 더 적합하다.

ORM을 매핑해서 개발해야하는 개발자입장에서는 MEMBER에 LOCKER가 외래 키로 있는 것이 성능도 그렇고, 여러가지로 유리하다.

  • 장점

    • MEMBER가 LOCKER를 가지고 있는지 없는지, 만약 가지고 있지 않으면 Null값을 허용할 수 있다.
    • Null인지 Null이 아닌지에 따라 비즈니스 로직을 돌거나 안 돌게 할 수도 있다.
  • 웬만한 비즈니스로직에서는 MEMBER를 조회해와야 한다.

  • 만약에 SELECT문으로 LOCKER가 있는지 없는지 DB 쿼리 한 번으로 LOCKER의 값이 있는지 없는지에 대한 판단을 아주 쉽게 할 수 있다.

  • 실무에서 객체 매핑을 하려면 아래와 같은 그림이 좀 더 유리하다.

영한좌는 너무 먼일을 생각하지않고, 일대일 관계다!하면 이 그림을 선호한다고 한다.

일대일 정리

주 테이블에 외래 키 장점

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

대상 테이블에 외래 키

  • 대상 테이블에 외래 키가 존재
  • 전통적인 데이터베이스 개발자 선호
  • 잠점 : 주 테이블과 대상 테이블을 일대일에서 일대다 관계로 변경할 때 테이블 구조 유지
  • 단점
    • 어쩔 수 없이 양방향으로 매핑하게 해야 될 수 있다.
    • 프록시 기능의 한계로 지연 로딩으로 설정해도 항상 즉시 로딩됨(프록시는 뒤에서 설명)

지연 로딩으로 설정해도 항상 즉시 로딩됨에 대한 부가설명

  • 테이블과 객체가 이렇게 연관관계가 이 그림처럼 되어있다면, LOCKER에 값이 있는지 없는지, MEMBER 테이블만 조회를 해서 확인 할 수 있을까...?
    어차피 LOCKER를 조회해서 MEMBER_ID가 있는지 없는지, WHERE문에 조건을 넣어서 값이 있는지 없는지 확인을 해야한다.
  • 값이 있어야 Member에 프록시를 넣든 다른 것을 넣거나 혹은, 값이 없을 때 Null을 넣든가 하기 위해선 일단 값이 있는지 없는지를 확인해야하는데, 그 확인하는 과정에서 쿼리를 어차피 날리게 되어있다. 어차피 쿼리가 나가기 때문에, 굳이 프록시를 만들 필요가 없다.
    그래서 지연로딩으로 값을 세팅한다 해도, 일대일 관계에서 대상테이블에 외래 키가 있으면 무조건 즉시 로딩을 하게 되어있다. 그래서 지연로딩으로 세팅하는 것이 의미가 없는 것이다.
  • 치명적인 단점이다.
profile
쌩수 Git >> https://github.com/SsangSoo?tab=repositories

0개의 댓글