연관관계 매핑 시 고려해야 할 사항 3가지가 있다
1. 다중성
2. 단방향, 양방향
외래 키를 매핑할 때 사용한다.
name 속성은 매핑할 외래 키 이름이다.
기본값은 필드명+_+참조하는 테이블의 기본 키 컬럼명
이다.
JPA에서 가장 많이 사용한다.
다 쪽에 외래키가 가야 함.
외래 키가 있는 객체에 참조를 넣어주면 된다.
외래 키가 있는 객체에
@ManyToOne
과 @JoinColumn(name="테이블에 생성될 FK 필드명")
을 넣어준다.
연관관계의 주인 : Member(다)
양방향으로 바꾸더라도 테이블에는 전혀 변경이 없다.
외래 키가 있는 쪽이 연관관계의 주인이다.
양쪽을 서로 참조하도록 개발한다.
일 쪽에서는 양방향이므로
@OneToMany(mappedby="다 쪽의 컬럼명")
애노테이션을 달아준다.
일이 연관관계의 주인이다.
권장하지 않는 모델이다.
DB 입장에서는 무조건 다 쪽에 FK가 있어야 한다.
@Entity
public class Team {
@Id @GeneratedValue
@Column(name="TEAM_ID")
private Long id;
private String name;
@OneToMany(mappedBy = "team")
@JoinColumn(name="TEAM_ID")
private List<Member> members = new ArrayList<>();
@OneToMany
로 매핑한다.
@JoinColumn
을 써줘야 한다. 안쓰면 조인 테이블 방식을 사용한다.
일대다 양방향도 사용하지 말자
일대일 관계는 반대도 일대일이다.
주 테이블이나 대상 테이블 중에 외래 키 선택 가능하다.
외래 키에 데이터베이스 유니크 제약조건 추가된다.
@Entity
public class Locker {
@Id @GeneratedValue
private Long id;
private String name;
}
@Entity
public class Member {
@Id @GeneratedValue
@Column(name="MEMBER_ID")
private Long id;
@Column(name="USERNAME")
private String username;
@OneToOne
@JoinColumn(name="LOCKER_ID")
private Locker locker;
}
@OneToOne
사용 , @JoinColumn
사용
양방향으로 하고 싶다면
@Entity
public class Locker {
@Id @GeneratedValue
private Long id;
private String name;
@OneToOne(mappedBy = "locker")
private Member member;
}
위와 같이 mappedBy
를 걸어주면 된다.
주 테이블에 외래 키가 있는 경우
대상 테이블에 외래 키가 있는 경우
관계형 DB는 정규화된 테이블 2개로 다대다 관계 표현 불가능하다.
연결 테이블을 추가해서 일대다, 다대일 관계로 풀어내야한다.
반면에 객체는 컬렉션을 사용해서 객체 2개로 다대다 관계가 가능하다.
실무에서 사용 X
연결 테이블용 엔티티를 추가해라
@ManyToMany
-> @OneToMany
, @ManyToOne
@Entity
public class Category {
@Id
@GeneratedValue
private Long id;
private String name;
@ManyToOne
@JoinColumn(name="PARENT_ID")
private Category parent;
@OneToMany(mappedBy = "parent")
private List<Category> child = new ArrayList<>();
}
Category에서 스스로 연관관계를 ManyToOne이랑 OneToMany로 양방향으로 걸었다.
@Entity
@Table(name = "ORDERS")
public class Order {
@Id
@GeneratedValue
@Column(name="ORDER_ID")
private Long id;
@ManyToOne
@JoinColumn(name="MEMBER_ID")
private Member member;
@OneToOne
@JoinColumn(name="DELIVERY_ID")
private Delivery delivery;
...
Order에서 FK를 갖고 있어서 @OneToOne
으로 매핑하고 @JoinColumn
으로 연관관계의 주인으로 지정한다.
@Entity
public class Delivery {
@Id
@GeneratedValue
private Long id;
private String city;
private String street;
private String zipcode;
private DeliveryStatus status;
@OneToOne(mappedBy = "delivery")
private Order order;
}
Delivery에서는 @OneToOne
에 mappedBy
로 Order에서 Delivery의 필드명을 지정해준다.
@ManyToMany
@JoinTable( name="CATEGORY_ITEM",
joinColumns = @JoinColumn(name="CATEGORY_ID"),
inverseJoinColumns = @JoinColumn(name="ITEM_ID")
)
private List<Item> items = new ArrayList<>();
Category 엔티티에 다음과 같이 추가해준다. 매핑을 위한 중간 테이블인 CATEGORY_ITEM
을 만든 것이다. 내 쪽의 JoinCOlumn은 CATEGORY_ID
이고 상대 쪽의 inverseJoinColumn은 ITEM_ID
이다.
@ManyToMany(mappedBy = "items")
private List<Category> category = new ArrayList<>();
양방향으로 매핑하고 싶으면 Item 엔티티에 다음과 같이 추가해준다. 연관관계의 주인이 아니기 때문에 mappedBy를 써준다.
@ManyToMany
사용하지 말 것