반응형

OneToOne

양쪽이 서로 하나의 관계만 가진다. 예를 들어 사용자와 해당 사용자의 프로필 이미지를 저장하는 두 엔티티가 있다고 예를 들어보면 이 경우 OneToOne 관계를 사용하여 각 사용자는 하나의 프로필 이미지를 가지고 있고, 각 프로필 이미지는 특정 사용자와 연결됩니다.

주의사항 - OneToOne 기본형이 EAGER이기 때문에 LAZY 사용해야 함!

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String username;

    @OneToOne(mappedBy = "user", cascade = CascadeType.ALL)
    private ProfileImage profileImage;
}

@Entity
public class ProfileImage {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String imageUrl;

    @OneToOne
    @JoinColumn(name = "user_id")
    private User user;
}

일대일 관계는 일대다, 다대일처럼 다 쪽에 외래키를 가지는 게 아니라 주 테이블이나 대상 테이블 어느 곳이든지 외래키를 가질 수 있습니다.

주테이블에 외래키 장점

  • 일관성 관리가 용이해집니다. 주 테이블에 외래키를 두면 데이터의 일관성 관리가 쉽습니다. 일반적으로 주 테이블이 관계를 소유하고 있으며, 데이터를 관리하고 유지하기 편리합니다.
  • 효율적인 쿼리 작성으로 주 테이블에 외래키를 두면 관련 데이터를 쉽게 검색하고 관리할 수 있으며 쿼리 작성이 간단해지며 필요한 정보를 빠르게 가져올 수 있습니다.

대상 테이블에 외래키 장점

  • 양방향 관계 설정으로 대상 테이블에 외래키를 둠으로써 주 테이블과 대상 테이블 간 양방향 관계를 쉽게 설정할 수 있습니다. 양쪽 엔티티에서 서로를 참조할 수 있어 객체 간의 관계를 보다 자연스럽게 표현할 수 있습니다.
  • 대상 테이블에 외래키를 두면 주로 조회되거나 관리되어야 할 데이터를 중심으로 관리할 수 있습니다. 데이터를 주로 조회하고 업데이트하는 쪽에 외래키를 두어 관리하가 편해집니다.

ManyToMany

두 엔티티 간의 다대다 관계를 매핑하는 데 사용하며 이러한 관계는 중간 테이블을 통해 구현됩니다. 양쪽 엔티티가 서로 많은 수의 다른 엔티티와 연결될 수 있는 상황에서 유용합니다. 또한 관계형 데이터 베이스에서는 정규화된 테이블 2개로 다대다 관계 표현이 불가능합니다.

@Entity
public class Student {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    @ManyToMany
    @JoinTable(
        name = "student_course",
        joinColumns = @JoinColumn(name = "student_id"),
        inverseJoinColumns = @JoinColumn(name = "course_id")
    )
    private Set<Course> courses = new HashSet<>();
}

@Entity
public class Course {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    @ManyToMany(mappedBy = "courses")
    private Set<Student> students = new HashSet<>();
}

ManyToMany 기본키 생성 전략

  • 다대다 관계에서의 중간 테이블은 주로 두 엔티티 사이의 관계를 나타내며 추가적인 정보를 담을 수 있습니다.
  • 다대다 관계의 중간 테이블에서는 보통 복합 기본키가 사용되며 이 키는 두 엔티티의 외래키를 조합하여 생성합니다. 쉽게 예를 들어보면 Student와 Course 엔티티 관계를 나타내는 중간 테이블에서 Student_id와 Course_id를 복합하여 기본키로 사용할 수 있습니다.
  • 자동 생성 ID를 사용해 중간 테이블에서도 별도의 ID를 생성하여 기본키를 사용하는 경우가 있으며 이 경우에는 중간 테이블에 대한 별도의 ID필드를 가질 수 있고, 이 필드에 대해 일반적인 ID 생성 전략을 사용할 수 있습니다.

ManyToMany한계 (실무 사용 거의 XXX)

다대다 관계에서 관계를 추가로 확장하거나 추가적인 속성을 추가하려면 중간 테이블을 수정해야 합니다. 이는 관계의 변경이나 확장하는 데에 제한을 가집니다.

대규모 시스템에서는 많은 데이터가 중간 테이블에 저장될 수 있으며, 성능 이슈를 유발할 수 있습니다. 특히 쿼리 사용이 조인이 복잡해질 수 있습니다.

극복 방법

  • 다대다 관계를 갖는 두 엔티티 사이에 새로운 엔티티를 도입하여 관계를 분해하는 방법이며 이 새로운 엔티티는 두 엔티티 간의 관계를 매핑하면서 추가 정보를 저장할 수 있습니다. 이를 통해 중간 테이블에서 발생하는 한계를 극복 가능합니다.
  • 다대다 관계를 추가 정보로 포함하는 일대다 또는 다대일 관계로 변환할 수 있으며 중간 테이블에 추가 정보를 담을 수 있는 엔티티를 만들고 각각의 다른 엔티티와 일대다 또는 다대일 관계를 형성하여 정보를 저장할 수 있습니다.
  • 다대다 관계를 양방향 관계로 분해하여 일대다 또는 다대일 관계로 변경할 수 있습니다. 이렇게 함으로 중간 테이블을 제거하고 하나의 엔티티에서 다른 엔티티를 직접 참조하는 형태로 관계를 설정할 수 있습니다.
728x90

'Spring(Boot & FrameWork)' 카테고리의 다른 글

Proxy  (0) 2023.12.22
@ManyToOne / @OneToMany  (0) 2023.12.20
JUnit5 Basic  (0) 2023.12.18