•
엔티티의 연관관계를 매핑할 때는 다음 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을 구현한다.
▪
equals와 hashsCode 메소드를 구현한다.
▪
기본 생성자가 있어야 한다.
▪
public이어야 한다.
▪
@IdClass 외에도 @EmbeddedId를 사용하는 방법도 있다.
•
부모 테이블의 기본 키를 받아서 자신의 기본 키 + 외래 키로 사용하는 것을 데이터베이스 용어로 식별관계라 한다.
4. 다대다: 새로운 기본 키 사용
•
연결 테이블에 새로운 기본 키를 적용하기 위해 ORDER라는 이름을 붙여준다. 연관관계를 정의한 것이다.
•
식별자 클래스를 사용하지 않아 코드가 단순해지며 이도 좋은 방법이다.
5. 다대다 연관관계 정리
•
다대다 관계를 일대다, 다대일 관계로 풀어내기 위해 연결 테이블을 만들 때는 식별자를 어떻게 구성할지 선택해야 한다.
◦
식별 관계: 받아온 식별자를 기본 키 + 외래 키로 사용
◦
비식별 관계: 받아온 식별자를 외래 키로만 사용하고 새로운 식별자를 추가한다.
•
객체 입장에서 보면 비식별 관계를 사용하는 것이 복합 키를 위한 식별자 클래스를 만들지 않아도 되므로 단순하고 편리하게 ORM 매핑을 할 수 있다. 이런 이유로 비식별 관계를 추천하신다.
5. 정리
•
다대일, 일대다, 일대일, 다대다 연관관계를 단방향, 양방향으로 매핑하는 방법에 대해 알아보았다.
•
마지막에는 다대다 연관관계를 일대다, 다대일로 풀어보았다.