- 참조: 자바 ORM 표준 JPA 프로그래밍
- 외래키에서 참조로의 변환
지난번 요구사항을 Entity 로 변환하는 과정에서 아래 다이어그램과 같이 속성으로 외래키를 그대로 냅두었었다.
연관관계 맵핑을 배웠으니 이 외래키들을 참조로 변환할 수 있다. 연관관계를 더 명확히 보기 위해서 해당 필드에도 다중성을 표시하였다.
아래 설명은 위의 다이어그램에서 클래스간의 관계를 파악한것이다.
- Member - Order: 멤버는 주문을 1건도 하지 않을 수도, 여러건을 할 수도 있다. 1 : N 의 관계이다. Member 와 Order 는 서로간을 참조하는 양방향 연관관계이다. 외래키는 Order 에서 MEMBER_ID 를 가져야 한다. 앞에서 설명했듯이 Member : Order = 1 : N 이므로 N 쪽에서 외래키를 가져야 한다고 생각해도 된다. 이게 헷갈린다면 DB 의 레코드 구조를 생각해보면 직관적으로 알 수 있다. Member 에서 여러 건의 Order 를 가질 수 있다는것을 표현하려면 Member#1, Order#1 인 행과 Member#1, Order#2 의 행이 있어야 한다. Order 가 여러 건인걸 표현하기 위해 User#1 의 정보가 중복되므로 Order에서 Member의 Id 외래키를 관리하는것이 합당하다.
- Order - OrderItem: 주문은 주문 아이템을 여러건 가질 수 있다. 단 주문 아이템은 주문 자체가 생성되어야 생성될 수 있는 개념이므로 다중성의 하한이 1 이라고 생각하였다. 1 : N 의 관계이다. 주문 아이템에서 주문을 참조할 수 있어서 양방향 연관관계이다. 외래키의 주인은 주문 아이템이다. Member - Order 처럼 레코드 구조를 생각해보면 왜 OrderItem 에서 Order 의 Id 를 외래키로 참조하고 있어야 하는지 알 수 있다.
- OrderItem - Item: 주문 아이템은 아이템을 1 건만 참조하고 있다. 아이템은 재고수량이 충분하다면 다른 여러 주문에서 참조될 수 있다. 따라서 주문아이템과 아이템은 N : 1 의 관계이다. OrderItem 의 다중성 하한은 0 이라고 생각했는데, 아이템을 주문하지 않을수도 있기 때문이다.
- JPA 코드로의 변환
Member 엔티티는 아래와 같이 작성한다.
@Entity
public class Member {
@Id @GeneratedValue
@Column(name = "MEMBER_ID")
private Long id;
private String name;
private String city;
private String street;
private String zipcode;
@OneToMany(mappedBy = "member")
private List<Order> orders = new ArrayList<>();
Member 는 주문을 여러 건 할 수 있어서 1 : N 관계이다. 따라서 외래키는 Order 에서 관리한다. 연관관계의 주인은 Order 라서 @OneToMany 어노테이션을 사용하고 mappedBy 속성의 값은 Order 의 Member 필드인 member 가 된다.
Member 의 반대편인 Order 는 아래와 같다. @Table 의 이름속성으로 ORDERS 를 설정한것은 Order 가 예약어라서 테이블이름으로 사용할 수 없기 때문이다.
@Entity
@Table(name = "ORDERS")
public class Order {
@Id
@GeneratedValue
@Column(name = "ORDER_ID")
private Long id;
@ManyToOne
@JoinColumn(name = "MEMBER_ID")
private Member member;
@OneToMany(mappedBy = "order")
private List<OrderItem> orderItems = new ArrayList<>();
@Temporal(TemporalType.TIMESTAMP)
private Date orderDate;
@Enumerated(EnumType.STRING)
private OrderStatus status;
Order 는 Member 와 N : 1 관계이다. 따라서 @ManyToOne 어노테이션을 사용하며, @JoinColumn 을 이용하여 Member의 Key인 MEMBER_ID 값을 설정한다. Order 는 OrderItem 과도 관계를 갖는다. 1 : N 관계라서 @OneToMany 어노테이션을 사용하며 mappedBy 에는 OrderItem 에서 Order를 참조하는 필드명인 order 값을 설정한다.
OrderItem 과 Order 는 N : 1 의 관계이기 때문에 @ManyToOne 어노테이션을 설정한다. @JoinColumn 으로 Order의 Key 컬럼인 ORDER_ID 를 할당한다. 그리고 Item 과도 관계를 갖는다. N : 1 이므로 역시 @ManyToOne 이며, @JoinColumn 은 Item 의 Key 컬럼인 ITEM_ID 이다.
@Entity
public class OrderItem {
@Id
@GeneratedValue
@Column(name = "ORDER_ITEM_ID")
private Long id;
@ManyToOne
@JoinColumn(name = "ORDER_ID")
private Order order;
@ManyToOne
@JoinColumn(name = "ITEM_ID")
private Item item;
private int orderPrices;
private int count;
반면 OrderItem 에서 Item 단방향 참조이기 때문에 Item 은 연관관계가 없다.
@Entity
public class Item {
@Id
@GeneratedValue
@Column(name = "ITEM_ID")
private Long id;
private String name;
private int price;
private int stockQuantity;
'Framework and Tool > JPA' 카테고리의 다른 글
JPA - 다양한 연관관계 - 1 : 1 (0) | 2021.07.06 |
---|---|
JPA - 다양한 연관관계 - N : 1 과 1 : N (0) | 2021.07.03 |
JPA - 연관관계 맵핑 - 양방향 연관 (0) | 2021.07.01 |
JPA - 연관관계 맵핑 - 단방향 연관 (0) | 2021.06.30 |
JPA - 엔티티 맵핑 - 요구사항 분석과 맵핑 (0) | 2021.06.27 |
댓글