JPA 연관관계 매핑 정리
Intro
안녕하세요. 최혜정 사원입니다. 다양한 연관관계 매핑에 대해서 정리한 내용을 공유하겠습니다.
1. 연관 관계 매핑 할 때 고려사항
1. 다중성 결정하기
- 다대일
- 일대다
- 일대일
- 다대다
2. 단방향, 양방향 정하기
- 테이블의 경우 : ‘방향’이라는 개념이 없고 그냥 외래키로 조인하면 두 테이블이 연관관계를 맺음
- 객체의 경우 : 연관관계 매핑을 객체 참조하는 방식으로 하여, 참조가 2군데 있어야함 (A>B, B>A)
===> 왜리키를 뭐로 할지, 누가 외래키를 관리할 지 정해줘야 함
===> 연관관계의 주인을 만들어야 함
3. 연관관계의 주인 정해주기
양방향의 경우, 누가 주인(=외래키 관리하는 쪽)인지 정해준다.
2. 일대다 @OneToMany
- 일대다 단방향 [1:N] : ‘일’이 연관관계 주인임, @JoinColumn을 넣어줘야함
- 일대다 양방향 [1:N, N:1] : 이보다는 다대일 양방향(‘다’쪽이 주인)을 추천
- 일대다 관계는 항상 ‘다’ 쪽에 외래키가 있음
만약 ‘일’쪽에서 외래키를 관리(주인)하겠다면 헷갈리기 때문에 비추!
- 다대일 관계에서 주인은 항상 ‘다’쪽에 있으므로, 다대일 양방향을 추천
- ‘다’쪽에서 ‘일’쪽을 조회할 일이 없더라도, ‘다를’ 연관관계의 주인으로 설정하자
@Entity
@Getter @Setter
public class Team {
@Id @GeneratedValue
@Column(name = "TEAM_ID")
private String id;
private String name;
@OneToMany
@JoinColumn(name = "TEAM_ID")
private List<Member> members = new ArrayList<>();
}
@Entity
@Getter @Setter
public class Member {
@Id @GeneratedValue
@Column(name = "MEMBER_ID")
private String id;
private String username;
}
3. 다대일 @ManyToOne
- 다대일 단방향 [N:1] : 주인인 ‘다’쪽에서는 ‘일’쪽 참조 가능하나, 반대는 조회도 불가능
- 다대일 양방향 [N:1, 1:N] : 서로 참조하면 주인아닌 쪽에서는 조회 가능해짐, 연관관계 편의 메소드를 만들어주면 좋음
- 객체 양방향 관계에서 연관관계의 주인은 항상 다 쪽이다.
@Entity
@Getter @Setter
public class Member {
@Id
@Column(name = "MEMBER_ID")
private String id;
@ManyToOne
@JoinColumn(name = "TEAM_ID")
private Team team;
}
@Entity
@Getter @Setter
public class Team {
@Id
@Column(name = "TEAM_ID")
private String id;
@OneToMany(mappedBy = "team") // 양방향
private List<Member> members = new ArrayList<>();
}
4. 일대일 @OneToOne
- 주 테이블이나 대상 테이블, 둘 중 어디에나 외래키 넣어도 가능하다.
- 일대일 양방향일때는 주인이 아닌쪽에 mappedBy 를 걸어주면 된다.
-
일대일 양방향일때 다대일 양방향 매핑처럼 외래키가 있는 곳이 연관관계 주인
- 주 테이블에 외래키 : 객체지향 개발자들이 선호하는 방식으로, 주 객체가 대상 객체의 참조를 가지는 것 처럼 주 테이블에 외래 키를 두고 대상 테이블을 찾는다.
- 대상 테이블에 외래키
@Entity
@Getter @Setter
public class Member {
@Id @GeneratedValue
@Column(name = "member_id")
private String id;
@OneToOne
@JoinColumn(name = "locker_id")
private Locker locker;
}
@Entity
@Getter @Setter
public class Locker {
@Id @GeneratedValue
@Column(name = "locker_id")
private Long id;
// 양방향
@OneToOne(mappedBy = "locker")
private Member member;
}
5. 다대다 @ManyToMany
- 객체: 다대다 관계가 가능함
- 테이블: 기존 테이블 두개만으로 다대다 관계를 만들수 없음
- @JoinTable로 연결 테이블 지정
보통은 연결 테이블을 추가하여 일대다, 다대일로 풀어냄 @ManyToMany → @OneToMany, @ManyToOne 이렇게 풀어내어 만들자
비추하는 코드
- 연결 테이블이 단순히 연결만 하는게 아니다.
- 주문시간, 수량 같은 다른 데이터가 필요할 수 있다.
@Entity
public class Member {
@Id @GeneratedValue
@Column(name = "MEMBER_ID")
private String id;
@ManyToMany
@JoinTable(name = "MEMBER_PRODUCT", //연결테이블 지정
joinColumns = @JoinColumn(name = "MEMBER_ID"), //외래키
inverseJoinColumns = @JoinColumn(name = "PRODUCT_ID")) //반대 엔티티의 외래키
private List<Product> products = new ArrayLit<>();
}
@Entity
public class Product {
@Id
@JoinColumn(name = "PRODUCT_ID")
private String id;
private String name;
}
추천하는 코드
@ManyToMany → @OneToMany, @ManyToOne 로 만들고 + 연결 테이블용 엔티티(Order) 추가
@Entity
public class Member {
@Id @Column(name = "MEMBER_ID")
private String id;
@OneToMany(mappedBy = "member")
private List<Order> orders = new ArrayList<>();
}
@Entity // 연결 테이블용 엔티티(Order)
public class Order {
@Id @GeneratedValue
@Column(name = "ORDER_ID")
private Long Id;
@Id
@ManyToOne
@JoinColumn(name = "MEMBER_ID")
private Member member;
@Id
@ManyToOne
@JoinColumn(name = "PRODUCT_ID")
private Product product;
}
@Entity
public class Product {
@Id @Column(name = "PRODUCT_ID")
private String id;
@OneToMany(mappedBy = "product")
private List<Order> orders = new ArrayList<>();
}
Leave a comment