코드 그라데이션

실전 예제 - 2. 연관관계 매핑 시작 본문

Spring/JPA 공부

실전 예제 - 2. 연관관계 매핑 시작

완벽한 장면 2023. 8. 19. 22:00

이전(예제 1)과 같은 테이블 구조

 

객체 구조

 

 

 

그러면

Order 테이블에서

MEMBER와 ORDER의 관계

//  @Column(name = "MEMBER_ID")
//  private Long memberId;

이게 필요가 없어지고

@ManyToOne
@JoinColumn(name = "MEMBER_ID")
private Member member; // 이렇게 바꿔준다.

이렇게 바꿔준다.

 

getter, setter도 변경해서 알맞게

public Member getMember() {
  return member;
}

public void setMember(Member member) {
  this.member = member;
}

 

 


OrderItem 클래스도 마찬가지

ORDERS와 ORDER_ITEM의 관계

//  @Column(name = "ORDER_ID")
//  private Long orderId;

이거 버리고

@ManyToOne
@JoinColumn(name = "ORDER_ID")
private Order order;

이렇게 되고

 

 

getter, setter도

//  public Long getOrderId() {
//    return orderId;
//  }
//
//  public void setOrderId(Long orderId) {
//    this.orderId = orderId;
//  }

이거 버리고

 

public Order getOrder() {
  return order;
}

public void setOrder(Order order) {
  this.order = order;
}

이게 맞다.

 


역시 OrderItem 클래스에서

ORDER_ITEM과 ITEM의 관계

이거 버리고

//  @Column(name = "ITEM_ID")
//  private Long itemId;

 

 

@ManyToOne
@JoinColumn(name = "ITEM_ID")
private Item item;

이렇게 바꾸면 된다.

 

getter, setter도

//  public Long getItemId() {
//    return itemId;
//  }
//
//  public void setItemId(Long itemId) {
//    this.itemId = itemId;
//  }

이거 버리고

 

public Item getItem() {
  return item;
}

public void setItem(Item item) {
  this.item = item;
}

이렇게 바꾼다.

 

ITEM 은 별달리 세팅한 게 없다.

아이템 입장에서 필요하면 양방향으로 만들 수도 있다.

예를 들면 Item을 보고 이 ITEM의 ORDER_ITEM을 추적하고 싶다든지...

하지만 그럴 일은 거의 없다.

주문 입장에선 상품이 뭐가 들어왔는지가 굉장히 중요하지만

상품 입장에선 어떤 주문에 속해있는지가 그렇게까지 핵심적으로 중요하진 않기 때문.

물론 나중에 리포팅할 때는 중요하겠지만.

 


이제 양방향에 대해서 고민

애플리케이션을 개발 중인 orders(주문 목록)의 중요성이 커졌다.

(여기서 여담. 대부분의 경우 Member에 orders를 넣는 건 별로 좋은 설계가 아니다. 왜? 예를 들어 테이블 입장에서 쿼리를 날려도, ORDERS에 이미 MEMBER_ID(FK) 가 있다. 특정 회원의 주문을 조회하고 싶은 경우겠죠. 그러니까 이미 있으니 쿼리를 시작할 때 ORDER 안에 MEMBER_ID를 기준으로 하지 굳이 Memeber에서 orders를 찾아서 getOrders()... 이렇게 번거롭게 할 필요가 없다는 이야기.)

 

굳이 예제니까 하겠다면,

Member 클래스에

` @OneToMany(mappedBy = "member")
  private List<Order> orders = new ArrayList<>();

이미 연관관계 주인은

@ManyToOne
@JoinColumn(name = "MEMBER_ID")
private Member member; // 이렇게 바꿔준다.

이렇게 있었다.


다음으로 Order 입장에서는

안에 orderItems 가 있는게 충분히 의미가 있는 상황일 가능성이 높다(상식적으로 생각해보아도)

 

그래서 OrderItem 클래스에 만들었던

@ManyToOne
@JoinColumn(name = "ORDER_ID")
private Order order;

이것의 반대매핑을 한다면

Order 클래스에

@OneToMany(mappedBy = "order")
private List<OrderItem> orderItems = new ArrayList<>();

이렇게 추가해서 연관관계를 맺어준다는 것이지.

 


이제 본격적 비즈니스 로직을 만들어보면

JpaShopMain에서

일단

public class JpaShopMain {
  public static void main(String[] args) {
    EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
    EntityManager em = emf.createEntityManager();

    EntityTransaction tx = em.getTransaction();
    tx.begin();

    try {
      Order order = new Order();
      order.addOrderItem(new OrderItem());

      tx.commit();
    } catch (Exception e) {
      tx.rollback();
    } finally {
      em.close();
    }
    emf.close();
  }
}

      Order order = new Order();
      order.addOrderItem(new OrderItem()); 이걸 적고,

Order 클래스에 연관관계 편의 메서드를 만든다.

public void addOrderItem(OrderItem orderItem) {
  orderItems.add(orderItem);
  orderItem.setOrder(this);
}

이렇게...

이러면 주문 객체를 만들어서 원하는 주문 아이템들을 쭉쭉 넣어갈 수 있다.

 

여기까지 하면 실전에제 1에서 연관관계 없이 나열했던 것을 이제 연관관계를 맺어서 적은 게 된다.

 


끝내기 전에

객체 구조 그림에서 orders랑 orderItems는 없어도 아무 문제가 없다. 왜냐하면, 연관관계를 매핑 하는 거 자체가 아무 문제가 없다.

 

왜냐면 굳이 addOrders() 없이

public class JpaShopMain {
  public static void main(String[] args) {
    EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
    EntityManager em = emf.createEntityManager();

    EntityTransaction tx = em.getTransaction();
    tx.begin();

    try {
      Order order = new Order();
      em.persist(order);

       

      OrderItem orderItem = new OrderItem();

      orderItem.setOrder(order); 

       em.persist(orderItem);

 


      tx.commit();
    } catch (Exception e) {
      tx.rollback();
    } finally {
      em.close();
    }
    emf.close();
  }
}

 

이렇게 만들어도 되기 때문이다.

즉, 양방향 연관관계가 아니어도 애플리케이션을 개발할 때 아무 문제가 없다는 것이다.

 

양방향 연관관계를 만드는 이유는 개발상의 편의, 나중에 조회할 때 수월 등.

 

실전에서 JPQL을 짜다보면 단방향 연관관계만 가지고 쓰기에는 약간의 한계가 있어서 양방향을 쓰는 경우가 많다.

728x90

'Spring > JPA 공부' 카테고리의 다른 글

다대일 [N : 1]  (0) 2023.08.20
다양한 연관관계 매핑 도입  (0) 2023.08.20
양방향 연관관계와 연관관계의 주인  (0) 2023.08.19
단방향 연관관계  (0) 2023.08.18
실전 예제 1 - 요구사항 분석과 기본 매핑  (0) 2023.08.17
Comments