이 글은 김영한님의 JPA 강의 중 6장을 듣고 정리한 내용입니다 :)
강의 : 자바 ORM 표준 JPA 프로그래밍 - 기본편
교재 : 자바 ORM 표준 JPA 프로그래밍🤷♀️
: 양방향의 경우, 누가 주인(= 외래키 관리하는 쪽)인지 정해주자
다중성 4가지 종류를 알아보자!
여기서는 다대일 양방향 매핑이 중요하고, 다대다는 실무에서 안 쓴다!
만약 '일'쪽에서 외래키를 관리(주인)하겠다면 헷갈리기 때문에 비추함!
⇒ 다대일 관계에서 주인은 항상 '다' 쪽에 있으므로,
⇒ 다대일 양방향을 추천한다. '다'쪽에서 '일'쪽을 조회할 일이 없더라도, '다'를 연관관계의 주인으로 설정하자!
다만, 공식적이지는 않으나 일대다 양방향을 하고 싶으면,
@JoinColumn (insertable=false, updatable=false) 이걸 '다'쪽에 걸어주면 읽기만 할 수 있음
아래는 일대다 단방향으로, 일대다 양방향은 다대일 양방향으로 가자!
@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
@Setter
@Getter
public class Member {
@Id @GeneratedValue
@Column(name = "MEMBER_ID")
private String id;
private String username;
}
아래는 다대일 단방향, 양방향 코드이다
@Entity
@NoArgsConstructor
@ToString(exclude = "team")
@Getter @Setter
public class Member {
@Id
@Column(name = "MEMBER_ID")
private String id;
@ManyToOne
@JoinColumn(name = "TEAM_ID") // 다 쪽에서 걸어주기
private Team team;
}
@Entity
@NoArgsConstructor
@Getter @Setter
public class Team {
@Id
@Column(name = "TEAM_ID")
private String id;
// 이걸 해주면 양방향 성립
@OneToMany(mappedBy = "team")
private List<Member> members = new ArrayList<>();
}
: 주 테이블이나 대상 테이블, 둘 중 어디에나 외래키 넣어도 OK!
: 일대일 양방향일때는 주인이 아닌쪽에 mappedBy 를 걸어주면 된다.
아래는 일대일 단방향, 양방향 코드이다
@Entity
@Getter
@Setter
public class User {
@Id @GeneratedValue
@Column(name = "user_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; // 객체를 참조해주면 양방향임
}
다대다 관계를 매핑할때 @ManyToMany는 사용하지 않는 걸 권장하는데, 아래 그림을 참고해보자
여기서 첫번째 그림처럼 @ManyToMany사용 + 연결 테이블 생성만 하면 실무에서 복잡해진다 (연결 테이블에 다른 컬럼값들을 추가하면, 더 이상 다대다 관계로 매핑하지 못해서..???)
그렇기에 연결 테이블을 엔티티로 승격시켜주어, 다른 컬럼 값들도 추가 가능하게 하자!
따라서 두번째 그림처럼
@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"))
List<Product> products = new ArrayList<Product>();
}
@Entity
public class Product {
@Id
@JoinColumn(name = "PRODUCT_ID")
private String id;
}
아래는 추천하는 @ManyToMany → @OneToMany, @ManyToOne 이렇게 풀어내고 + 연결 테이블용 엔티티(Order) 추가 코드
@Entity
public class Member {
@Id @Column(name = "MEMBER_ID")
private String id;
@OneToMany(mappedBy = "product")
private List<Order> orders;
}
@Entity // 연결 테이블용 엔티티(Order)
public class Order {
@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<Member> members;
}
참고 래퍼런스
https://sa1341.github.io/2019/10/01/다양한-연관관계-매핑/
https://incheol-jung.gitbook.io/docs/study/jpa/6