스프링 공부/JPA

[JPA] 13. 다대다 매핑(이걸 매핑이라 부를까....?)

장아장 2022. 11. 3. 21:39

데이터베이스와 JPA에서 사용되는 방식이 정말 비슷하다고 생각되는, 몇 안되는 녀석 중 하나다. 

 

데이터베이스의 다대다 매핑은, 이 매핑을 위한 테이블을 하나 구현한다. 

이 테이블에 외래키 두개를 만들어 사용했다. 

 

JPA에서도 마찬가지다. 다대다로 매핑할 두 객체 사이에 끼어들어갈 객체를 하나 만든다. 

이 객체에 양쪽에서 가운데로 다대일 매핑을 하는 것이다. 

예를 들어보자면, 

@Entity
@Table(name = "ORDER_ITEM")
public class OrderItem {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "ORDER_ITEM_ID")
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "ITEM_ID")
    private Item item;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "ORDER_ID")
    @OnDelete(action = OnDeleteAction.CASCADE)
    private Order order;

이 녀석을 예로 들 수 있다. 

기본적으로 주문은 여러 상품을 할 수 있고, 한 상품을 여러 사람들이 주문할 수 있다. 즉, 다대다 관계가 되어야 한다. 

하지만, OrderItem으로 주문상품이라는 객체를 만든다. 주문상품은 상품과 다대일, 주문과 다대일로 매핑해 상품과 주문이 다대다 매핑을 하는 것과 비슷한 효과를 낼 수 있다. 

실제로 프로젝트를 해 볼 때에도, 공부를 할 때에도 이렇게만 있었다. 

 

번듯이 '@' 를 눌러보면 ManyToMany가 존재하는데, 쓰질 않는다. 

이유를 찾아보았다. 

 

우리가 다대다 매핑을 해서 데이터를 가져올 때, 결국 외래키를 가지는 한 객체를 가져온다. 이 객체를 이용해 외래키로 불러진 객체도 탐색할 수 있게 하는게 결국 테이블의 데이터를 가져와 조작하고 쓰기 수월하다. 

 

하지만 다대다 매핑의 제일 큰 문제는, JPA가 쿼리문을 조인 테이블로 보낸다. 즉, 하나의 테이블로 합쳐서 공통적인 값들은 반복시키지 않고 리턴한다. 

(쉽게 보자면 상품 테이블, 주문 테이블이 와야 되는데 상주품문이 온다는 뜻)

 

쿼리문이 불필요하게 많이 나가고, 이상하게 나가고, 번잡하기도 하다. 

그래서 잘 안쓴다고도 한다. 

 

이렇게 기본적인 연관관계 매핑을 공부했다. 

공부하면서 느낀점

  1. 일단 다대일 일대일로 만든다. 
  2. 다대다가 필요하다면 그 테이블을 더 쪼개보자
  3. 다대일로 다 만들고, 후에 필요하다면 그 때 양방향 매핑을 해서 사용하자. 

이정도 인 것 같다. 사실, 아직 이 정도로 복잡한 테이블 구조를 사용해본 적은 없는 것 같기도 하다. 

조금 더 지식을 가다듬고, 몸으로도 체화시켜서 더 많은 경험을 쌓아야 겠다.