연관 관계란 객체의 참조와 테이블의 외래 키를 매핑시키는 것이라고 보면 편하다. 연관 관계는 크게 3가지로 나누어 볼 수 있다.
자세히 알아보도록 하자
연관 관계에서 객체사이의 방향은 단방향과 양방향으로 이루어져있다. 단방향은 말 그대로 한 방향으로 흐르는것이다. 양방향은 한번에 흐르는 참조가 있는 것 같지만 실은 단방향 2개가 모여서 만들어진 것이 양방향이다.
2가지 방향성이 있지만 양방향은 단방향으로도 흐를수 있으므로 양방향만 쓰면 되지 않는가? 라는 생각이 들 수도 있다.
하지만 무조건 양방향으로 설계하는것은 좋지 않다.
그 이유는 객체 입장에서 양방향 매핑을 했을때 사용자의 입장에서는 엔티티들과 매우 복잡한 관계를 가질수 밖에 없기 때문이다. 이렇게 연관 관계에서 양방향을 남발한다면, 나중에 다시 자신이 설계한 관계형 데이터베이스를 봐도 이해할 수 없는 아이러니한 상황이 발생할 수 있다.
2개의 객체가 양방향 연관 관계를 가질 때 연관 관계에서의 주인을 정해줘야 한다.
연관 관계에서의 주인이라 하면, 연관 관계의 주인을 지정 하는 것은 두 단방향 관계(A→B, B→A)중, 제어의 권한(CRUD)을 갖는 객체가 어느 객체인지 JPA에게 알려주는 것이라고 보면된다.
연관 관계에의 주인을 정해주어야 하는 이유는 정해져 있다. A의 데이터를 수정한다고 가정하였을 때 A의 데이터를 수정하는 방식도 있지만, B의 데이터를 수정하는 방식도 틀리지 않았기에 JPA의 입장에서는 매우 혼란스러울 것이다. 따라서 연관 관계에서의 주인은 명확하게 정의 해주어야 한다.
연관 관계는 대칭성을 가진다.
다대일 양방향으로 만드려면 @OneToMany를 추가해서 양방향 매핑이 되었으므로 연관 관계의 주인을 mappedBy를 사용해서 Member로 지정해준다.
package jpabook.jpashop.domain;
import lombok.Getter;
import lombok.Setter;
import org.apache.tomcat.jni.Address;
import javax.persistence.*;
import javax.persistence.criteria.Order;
import java.util.ArrayList;
import java.util.List;
@Entity
@Getter
@Setter
public class Member {
@Id @GeneratedValue
@Column(name = "member_id")
public Long id;
private String name;
@Embedded
private Address address;
@OneToMany(mappedBy = "member") // 연관 관계의 주인 정하기
private List<Order> orders = new ArrayList<>();
}
나머지 일대일(1:1), 일대다(1:N), 다대다(N:M)는 사용하지 않는것을 권장한다.
일대일(1:1) : JPA에서는 아예 지원자체를 않으며, 논란의 여지가 많음(A에게 포린키를 줄 것인가, B에게 포린키를 줄 것인가)
일대다(1:N) : 일대다(1:N) 단방향 연관 관계 매핑보다 다대일(N:1) 양방향 연관 관계를 매핑이 유지보수에 더 좋은 모습을 보여줌
다대다(N:M) : 다대다 관계에서는 객체 사이에 조인 중간 테이블이 숨겨져 있기 때문에 복잡한 조인의 쿼리가 발생하는 경우가 생길 수 있음