////
Search
Duplicate
🥌

6장. 다양한 연관관계 매핑

엔티티의 연관관계를 매핑할 때는 다음 3가지를 고려해야 한다.
다중성
다중성을 판단하기 어려울 때는 반대방향을 생각해보면 된다. 참고로 일대다의 반대방향은 항상 다대일이고 일대일의 반대방향은 항상 일대일이다.
보통 다대일과 일대다 관계를 가장 많이 사용하고 다대다 돤계는 실무에서 거의 사용하지 않는다.
단방향, 양방향
테이블은 외래 키 하나로 조인을 사용해 사실 상 방향이라는 개념이 없으나. 객체는 참조용 필드를 가지고 있는 연관된 객체만 조회할 수 있다.
연관관계의 주인
데이터베이스는 외래 키 하나로 두 테이블이 연관관계를 맺는데, 외래 키를 관리하는 객체의 속성을 연관관계의 주인이라 한다.
외래 키를 가진 테이블과 매핑한 엔티티가 외래 키를 관리하는게 효율적이므로 보통 이곳을 연관관계의 주인으로 선택한다.
연관관계의 주인은 mappedBy 속성을 사용하지 않는다.

1. 다대일

다대일 관계의 반대 방향은 항상 일대다 관계고 일대다 관계의 반대 방향은 항상 다대일 관계다.
데이터베이스 테이블의 , 관계에서 외래 키는 항상 쪽에 있다. 따라서 연관관계의 주인도 항상 다쪽이다.

1. 다대일 단방향 [N:1]

2. 다대일 양방향 [N:1, 1:N]

양방향 연관관계는 항상 서로를 참조해야 한다. 어느 한 쪽만 참조하면 양방향이 성립하지 않는다. 이때 연관관계 편의 메소드를 작성하는 것이 좋다.

2. 일대다

일대다 관계는 객체를 하나 이상 참조할 수 있으므로 자바 컬렉션인 Collection, List, Set, Map 중 하나를 사용해야 한다.

1. 일대다 단방향 [1:N]

하나의 팀은 여러 회원을 참조할 수 있고 회원은 팀을 참조하지 않으면 이를 일대다 단방향 관계라 한다.
매핑한 객체가 관리하는 외래 키가 다른 테이블에 있다는 단점을 가지고 있다. 이때문에 연관관계 처리를 위한 수정 SQL이 추가로 요구된다.
일대다 단방향 매핑보다는 다대일 양방향 매핑을 사용하는 것이 좋다.

2. 일대다 양방향 [1:N, N:1]

일대다 양방향 매핑 대신 가급적 다대일 양방향 매핑을 사용해야 한다.
양방향 매핑에서 @OneToMany는 연관관계의 주인이 될 수 없기 때문인데, 관계형 데이터베이스의 특성상 일대다, 다대일 관계는 항상 다 쪽에 외래 키가 있다.
임의로 매핑을 추가하고 적용하면 성능상 이슈가 발생할 수 있기 때문에 가급적 피하는 것이 좋다.

3. 일대일 [1:1]

일대일 관계는 그 반대도 일대일 관계다.
테이블 관계에서 일대일 관계는 주 테이블이나 대상 테이블 둘 중 어느 곳이나 외래 키를 가질 수 있다.
주 테이블에 외래 키
주 객체가 대상 객체를 참조하는 것처럼 참조하는 방법으로 외래 키를 객체 참조와 비슷하게 사용할 수 있어 객체지향 개발자들이 선호한다고 한다.
이 방법의 장점은 주 테이블이 외래 키를 가지고 있으므로 주 테이블만으로도 연관관계를 확인할 수 있다.
대상 테이블에 외래 키
전통적인 데이터베이스 개발자들이 선호하는 방법이다.
이 방법의 장점은 테이블 관계를 일대일에서 일대다로 변경할 때 테이블 구조를 그대로 유지할 수 없다.

4. 다대다 [N:N]

관계형 데이터베이스는 정규화된 테이블 2개로 다대다 관계를 풀어낼 수 없다. 그래서 보통 다대다 관계를 일대다, 다대일 관계로 풀어내는 연결 테이블을 사용한다.
객체는 테이블과 다르게 객체 2개로 다대다 관계를 만들 수 있다. @ManyToMany를 사용하면 다대다 관계를 편리하게 매핑할 수 있다.

1. 다대다: 단방향

연결 테이블을 지정해주어야 하는데, 이때 @JoinTable 어노테이션을 사용한다.

2. 다대다: 양방향

역방향도 @ManyToMany를 지정하고 원하는 곳에 mappedBy 작성해 연관관계의 주인을 지정한다.

3. 다대다: 매핑의 한계와 극복, 연결 엔티티 사용

@ManyToMany만으로는 비즈니스 로직을 완전히 표현하는 것이 힘들다. 따라서 연결 엔티티를 만들고 이곳에 연결 테이블의 키를 제외한 칼럼들을 매핑해야 한다.
그리고 엔티티 간의 관계도 테이블 관계처럼 다대다에서 일대다, 다대일 관계로 풀어야 한다.
이 테이블은 기본 키가 연결의 대상이 되는 두 테이블의 키를 복합 기본 키로 가진다. JPA에서 복합 키를 사용하려면 별도의 식별자 클래스를 만들고 엔티티에 @IdClass를 사용해 지정해주어야 한다.
복합 키를 위한 식별자 클래스는 다음과 같은 특징을 가진다.
Serializable을 구현한다.
equalshashsCode 메소드를 구현한다.
기본 생성자가 있어야 한다.
public이어야 한다.
@IdClass 외에도 @EmbeddedId를 사용하는 방법도 있다.
부모 테이블의 기본 키를 받아서 자신의 기본 키 + 외래 키로 사용하는 것을 데이터베이스 용어로 식별관계라 한다.

4. 다대다: 새로운 기본 키 사용

연결 테이블에 새로운 기본 키를 적용하기 위해 ORDER라는 이름을 붙여준다. 연관관계를 정의한 것이다.
식별자 클래스를 사용하지 않아 코드가 단순해지며 이도 좋은 방법이다.

5. 다대다 연관관계 정리

다대다 관계를 일대다, 다대일 관계로 풀어내기 위해 연결 테이블을 만들 때는 식별자를 어떻게 구성할지 선택해야 한다.
식별 관계: 받아온 식별자를 기본 키 + 외래 키로 사용
비식별 관계: 받아온 식별자를 외래 키로만 사용하고 새로운 식별자를 추가한다.
객체 입장에서 보면 비식별 관계를 사용하는 것이 복합 키를 위한 식별자 클래스를 만들지 않아도 되므로 단순하고 편리하게 ORM 매핑을 할 수 있다. 이런 이유로 비식별 관계를 추천하신다.

5. 정리

다대일, 일대다, 일대일, 다대다 연관관계를 단방향, 양방향으로 매핑하는 방법에 대해 알아보았다.
마지막에는 다대다 연관관계를 일대다, 다대일로 풀어보았다.