엔티티들은 대부분 다른 엔티티와 연관 관계를 맺고 있는데,
JPA에서는 엔티티에 연관 관계를 매핑해 두고 필요할 때 해당 엔티티와 연관된 엔티티를 사용하여 조금 더 객체지향적으로 프로그래밍할 수 있도록 도와줌
연관 관계 매핑의 종류
일대일 매핑의 예: 각 회원들의 장바구니
일대다 매핑의 예: 하나의 장바구니에 여러 개의 상품
일대일(1:1): @OneToOne
일대다(1:N): @OneToMany
다대일(N:1): @ManyToOne
다대다(N:M): @ManyToMany
* 다대일과 일대다는 반대 관계
엔티티 매핑시의 방향성
단방향
양방향
* 양방향 매핑에서는 '연관 관계 주인'을 설정해야 함
ㄴ 연관 관계의 주인은 외래키가 있는 곳으로 설정
ㄴ 연관 관계의 주인이 외래키를 관리(등록, 수정, 삭제)
ㄴ 주인이 아닌 쪽은 연관 관계 매핑 시 mappedBy 속성의 값으로 연관 관계의 주인을 설정
ㄴ 주인이 아닌 쪽은 읽기만 가능
일대일 단방향 매핑하기
회원 엔티티와 장바구니 엔티티 매핑 설정
import lombok.ToString;
import javax.persistence.*;
@Entity
@Table(name = "cart")
@Getter @Setter
@ToString
public class Cart {
@Id
@Column(name = "cart_id")
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@OneToOne //일대일 매핑
@JoinColumn(name="member_id") //매핑할 외래키를 지정
private Member member;
}
회원(Member) 엔티티에는 장바구니(Cart) 엔티티와 관련된 소스가 없음
장바구니 엔티티가 일방적으로 회원 엔티티를 참조
= 일대일 단방향 매핑
다대일 단방향 매핑하기
하나의 장바구니에는 여러 개의 상품들이 들어갈 수도 있고 같은 상품을 여러 개 주문할 수도 있으므로 몇 개를 담아줄 것인지도 설정이 필요
package com.shop.entity;
import lombok.Generated;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.*;
@Entity
@Getter @Setter
@Table(name="cart_item")
public class CartItem {
@Id
@Generated
@Column(name = "cart_item_id")
private Long id;
@ManyToOne // 다대일 관계로 매핑
@JoinColumn(name="cart_id")
private Cart cart;
@ManyToOne
@JoinColumn(name = "item_id")
private Item item; // 장바구니에 담을 상품의 정보
private int count; // 같은 상품을 장바구니에 몇 개 담을지 저장
}
다대일/일대다 양방향 매핑하기
장바구니 엔티티에 장바구니 상품 엔티티를 일대다 관계로 매핑을 해준다면 양방향 매핑이 됨
주문 - 주문 상품의 양방향 매핑
package com.shop.entity;
import com.shop.constant.OrderStatus;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.*;
import java.time.LocalDateTime;
@Entity
@Table(name = "orders") //정렬할 때 사용하는 "order" 키워트가 있기 때문에 테이블로 orders를 지정
@Getter @Setter
public class Order {
@Id @GeneratedValue
@JoinColumn(name = "order_id")
private Long id;
@ManyToOne
@JoinColumn(name = "member_id")
private Member member; //한 명의 회원은 여러번 주문할 수 있음 -> 주문 엔티티 기준에서 다대일 단방향 매핑
private LocalDateTime orderDate; //주문일
@Enumerated(EnumType.STRING)
private OrderStatus orderStatus; //주문 상태
private LocalDateTime regTime;
private LocalDateTime updateTime;
}
주문 상품 엔티티와 주문 엔티티의 단방향 매핑
package com.shop.entity;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.*;
import java.time.LocalDateTime;
@Entity
@Getter @Setter
public class OrderItem {
@Id @GeneratedValue
@Column(name = "order_item_id")
private Long id;
@ManyToOne
@JoinColumn(name = "item_id")
private Item item; //하나의 상품은 여러 주문 상품으로 들어갈 수 있으므로 주문 상품 기준 다대일 단방향 매핑
@ManyToOne
@JoinColumn(name = "order_id")
private Order order; // 한번의 주문에 여러 개의 상품을 주문할 수 있으므로 주문 상품 엔티티와 주문 엔티티를 다대일 단방향 매핑을 먼저 설정
private int orderPrice; //주문가격
private int count; //수량
private LocalDateTime regTime;
private LocalDateTime updateTime;
}
다대다 매핑을 사용하지 않는 이유
연결 테이블에는 컬럼을 추가할 수 없기 때문
조인 컬럼뿐 아니라 추가 컬럼들이 필요한 경우가 많고, 엔티티를 조회할 때 member 엔티티에서 item을 조회하면 중간 테이블이 있기 때문에 어떤 쿼리문이 실행될지 예측하기도 쉽지 않음
연결 테이블용 엔티티를 하나 생성한 후 일대다 다대일 관계로 매핑하면 됨