일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- JPQL
- CHECK OPTION
- 연결리스트
- fetch
- 지연로딩
- 이진탐색
- shared lock
- 스프링 폼
- 스토어드 프로시저
- dfs
- 동적sql
- 힙
- 유니크제약조건
- 연관관계
- BOJ
- 백트래킹
- 다대다
- execute
- 데코레이터
- SQL프로그래밍
- FetchType
- 낙관적락
- querydsl
- 비관적락
- 일대다
- exclusive lock
- PS
- 즉시로딩
- eager
- 다대일
- Today
- Total
흰 스타렉스에서 내가 내리지
[JPA] 연관관계 - 다대다 @ManyToMany, 복합 키, 식별자 클래스, @IdClass 본문
@ManyToMany 이용
@Entity
@Getter @Setter
public class Member{
@Id @GeneratedValue
@Column(name = "MEMBER_ID")
private Long id;
private String username;
@ManyToMany
@JoinTable(name = "MEMBER_PRODUCT",
joinColumns = @JoinColumn(name = "MEMBER_ID"),
inverseJoinColumns = @JoinColumn(name = "PRODUCT_ID"))
private List<Product> products = new ArrayList<Product>();
}
@Entity
public class Product {
@Id @GeneratedValue
@Column(name = "PRODUCT_ID")
private Long id;
@ManyToMany(mappedBy = "products")
private List<Member> members;
}
@ManyToMany를 사용하면 MEMBER_PRODUCT 연결 테이블을 자동으로 처리해준다.
도메인 모델이 단순해지고 편리해진다.
하지만, 연결 테이블에 보통 단순히 양쪽의 아이디만 담고 끝나지 않는다.
주문 수량컬럼이나 주문 날짜 컬럼이 더 필요하다.
이렇게 컬럼을 더 추가하려면 @ManyToMany는 사용할 수 없다.
따라서 연결 테이블을 매핑하는 연결 엔티티를 만들고 이곳에 추가한 컬럼들을 매핑해야 한다.
그리고 엔티티 간의 관계도 테이블 관계처럼 다대다에서 일대다, 다대일 관계로 풀어야 한다.
복합키 사용
@Entity
@Getter @Setter
public class Member{
@Id @GeneratedValue
@Column(name = "MEMBER_ID")
private Long id;
// 역방향
@OneToMany(mappedBy = "member")
private List<MemberProduct> memberProducts;
}
@Entity
public class Product {
@Id @GeneratedValue
@Column(name = "PRODUCT_ID")
private Long id;
private String name;
}
public class MemberProductId implements Serializable {
private Long member; // MemberProduct.member와 연결
private Long product; // MemberProduct.product와 연결
// equals()와 hashCode()는 IDE에서 자동생성 해주는 기능이 있음
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof MemberProductId)) return false;
MemberProductId that = (MemberProductId) o;
return Objects.equals(member, that.member) && Objects.equals(product, that.product);
}
@Override
public int hashCode() {
return Objects.hash(member, product);
}
}
@Entity
@IdClass(MemberProductId.class)
public class MemberProduct {
@Id
@ManyToOne
@JoinColumn(name = "MEMBER_ID")
private Member member; //MemberProductId.member와 연결
@Id
@ManyToOne
@JoinColumn(name = "PRODUCT_ID")
private Product product; //MemberProductId.product와 연결
private int orderAmount;
}
MemberProduct 클래스를 보면, 기본 키를 매핑하는 @Id와 외래 키를 매핑하는 JoinColumn을 동시에 사용해서 기본 키 + 외래 키를 한 번에 매핑했다. 그리고 @IdClass를 사용해서 복합 기본 키를 매핑했다.
회원 상품 엔티티는 기본 키가 MEMBER_ID와 PRODUCT_ID로 이루어진 복합 기본키다.
JPA에서 복합 키를 사용하려면 별도의 식별자 클래스를 만들어야 한다.
그리고 엔티티에 @IdClass를 사용해서 식별자 클래스를 지정하면 된다.
여기서는 MemberProductId 클래스를 복합 키를 위한 식별자 클래스로 사용한다.
식별자 클래스
- 복합 키는 별도의 식별자 클래스로 만들어야 한다.
- Serializable을 구현해야 한다.
- equals와 hashCode 메소드를 구현해야 한다.
- 기본 생성자가 있어야 한다.
- 식별자 클래스는 public 이어야 한다.
- @IdClass 를 사용하는 방법 외에 @EmbeddedId를 사용하는 방법도 있다.
다대다 : 새로운 기본 키 사용
@Entity
@Getter @Setter
public class Member{
@Id @GeneratedValue
@Column(name = "MEMBER_ID")
private Long id;
@OneToMany(mappedBy = "member")
private List<Order> orders = new ArrayList<Order>();
private String username;
}
@Entity
public class Product {
@Id @GeneratedValue
@Column(name = "PRODUCT_ID")
private Long id;
private String name;
}
@Entity
@Table(name = "Orders")
@Getter @Setter
public class Order {
@Id @GeneratedValue
private Long id;
@ManyToOne
@JoinColumn(name = "MEMBER_ID")
private Member member;
@ManyToOne
@JoinColumn(name = "PRODUCT_ID")
private Product product;
private int orderAmount;
}
식별자 클래스를 사용하지 않아서 코드가 한결 단순해졌다. 추천방식
'Spring' 카테고리의 다른 글
[JPA] 식별 관계와 비식별 관계 (0) | 2023.02.11 |
---|---|
[JPA] 상속 관계 매핑 (0) | 2023.02.11 |
[JPA] 연관관계 - 다대일,일대다,일대일,@ManyToOne,@OneToMany,@OneToOne (0) | 2023.02.10 |
[JPA] 연관관계의 주인 , mappedBy, 연관관계 (0) | 2023.02.10 |
[JPA]@Access(AccessType.PROPERTY) (0) | 2023.02.10 |