테이블은 외래 키 하나로 양쪽 조인 가능. 방향이라는 개념이 없다
객체는 참조용 필드가 있는 쪽으로만 참조 가능 한쪽만 참조하면 단방향. 양쪽이 서로 참조하면 양방향
테이블은 외래 키 하나로 두 테이블이 연관관계를 맺음
객체 양방향 관계는 참조가 2군데. 둘중 테이블의 외래 키를 관리할 곳을 지정해야 함
연관관계의 주인은 외래키를 관리하는 참조이고 반대편은 외래 키에 영향을 주지 않으며 단순 조회만 가능하다.
가장 많이 사용하는 연관관계
양방향의 경우 외래 키가 있는 쪽이 연관관계의 주인
일대다 단반향은 일이 연관관계의 주인
테이블에서는 항상 다쪽에 외래키가 있다.
객체와 테이블의 차이 때문에 반대편 테이블의 외래 키를 관리하는 특이한 구조
연관관계 관리를 위해 추가로 UPDATE SQL을 실행한다. 그러니 일대다 단방향 매핑보다는 다대일 양방향 매핑을 사용하자
일대다 양방향 사용 X
일대일 관계 이므로 주 테이블이나 대상 테이블 중에 외래키 선택
단방향의 경우 다대일 단방향 매핑과 유사하다.
양방향의 경우 외래 키가 있는 곳이 연관관계의 주인이다. 반대편은 mappedBy 적용한다.
주 객체가 대상 객체의 참조를 가지는 것처럼 주 테이블에 외래 키를 두고 대상 테이블을 찾는다.
JPA 매핑이 편리하고 주 테이블만 조회해도 대상 테이블 조회 가능
값이 없으면 외래키에 null을 허용하는 단점이 있다.
대상 테이블에 외래 키가 존재하는 경우인데, 주 테이블과 대상 테이블을 일대일에서 일대다 관계로 변경할 때 테이블 구조를 유지할 수 있다.
프록시 기능의 한계로 항상 즉시 로딩되는 단점이 있다.
관계형 데이터베이스는 정규화된 테이블 2개로 다대다 관계를 표현할 수 없으므로 연결 테이블을 추가해야한다.
연결 테이블이 단순 연결만 하는게 아니라 다른 데이터도 들어올 수 있다.
예시
@Entity
public class Member {
@Id @GeneratedValue
private Long id;
// 멤버 오더 일대다이므로 오더가 주 테이블이고 외래키를 관리한다. 오더 쪽에 조인 컬럼으로 외래키 지정하고 그리고 양방향으로 매핑하기로 결정했으므로 멤버 쪽에서는 mappedBy로 반대 변수명 적어준다.
// 리스트 선언시 초기화 필수
@OneToMany(mappedBy = "member")
private List<Order> orders = new ArrayList<>();
}
@Entity
public class Order {
@Id @GeneratedValue
private Long id;
// 연관관계의 주인. DB에 오더 테이블에 외래키 들어감.
@ManyToOne
@JoinColumn(name = "member_id")
private Member member;
}
@Entity
public class Order {
@Id @GeneratedValue
private Long id;
//1:1임
//아무쪽에서나 외래키 가질 수 있음. 설계상 딜리버리쪽에서 외래키 가지고 있음. 그러면 딜리버리가 주 테이블임. 양방향 매핑 하기로 다짐했으므로 오더 클래스에 딜리버리 추가
@OneToOne(mappedBy = "order")
private Delivery delivery;
}
@Entity
public class Delivery {
@Id @GeneratedValue
private Long id;
@OneToOne
@JoinColumn(name = "order_id")
private Order order;
}
@Entity
public class Order {
@Id @GeneratedValue
private Long id;
// 오더와 아이템을 다대다 매핑하기로 마음먹음. 그러면 연결 테이블을 만들어아 함. 오더아이템 클래스를 만들어서 양방향 매핑해야겠다. 그러면 오더 오더아이템 일대다 이므로 오더아이템이 다쪽이라 다쪽에 외래키가 있고 연관관계의 주인이다. 오더아이템과 양방향 매핑을 할 것이므로 오더에 오더아이템 변수를 만들고 mappedBy로 매핑
@OneToMany(mappedBy = "order")
private List<OrderItem> orderItems;
}
@Entity
public class Item {
@Id @GeneratedValue
private Long id;
// 아이템에서 오더를 참조하지 않기로 설계했다. 그러면 아무것도 안적어도 된다.
}
@Entity
public class OrderItem {
@Id @GeneratedValue
private Long id;
// 오더아이템은 중간 테이블. 오더아이템이 N쪽이므로 외래키를 여기서 관리한다. 조인컬럼으로 외래키 이름 지정한다. 이때 오더와 아이템 둘다 연결한다.
@ManyToOne
@JoinColumn(name = "item_id")
private Item item;
@ManyToOne
@JoinColumn(name = "order_id")
private Order order;
}
출처 : 인프런 자바 ORM 표준 JPA 프로그래밍 - 기본편