JPA에서는 M:N 관계일 때 어떻게 하지??

myminimin·2023년 9월 22일
0

Spring/Springboot

목록 보기
18/21
post-custom-banner

JPA를 배우면서 entity 클래스가 정말 편하다는 것은 알겠는데 M:N, 다대다의 관계에서 '매핑 테이블'을 어떻게 처리해야 하는가? 에 대한 의문이 들었다.

책에서는 Movie - Review - Member 라는 테이블로 예를 들었는데 이 테이블들은 각각 서로 다른 목적이 있는 테이블인데

내가 전에 Spring을 배울 때 (JPA를 모르던 시절) 이렇게 다대다 관계를 생각해서 설계를 했던 적이 있는데... 한 영화에 영화 배우가 여러 명이 있을 수 있고 영화배우는 여러 영화에 출연할 수 있다.. 처럼!

이때는 Movie - movie_actor(매핑테이블) - Actor 이렇게 3개의 테이블을 수동으로 모두 만들어준 후에 연관 관계를 설정했는데...

Spring boot-JPA를 사용하는 이번 교재에서는 movie - review - member 같은 경우 review 클래스에서 @ManyToOne을 사용해 movie와 member를 연결을 했다.

JPA에서 내가 위에 설계해둔 movie_actor와 같은 매핑 테이블을 어떻게 처리해야하는가? 에 대한 궁금증이 생겼다...
(왜냐하면 movie, review, member는 서로 다른 목적이 있지만 movie와 actor은 movie라는 하나의 목적으로 만들어졌으니까...??)

movie_actor도 클래스를 하나 새로 만들어서 @entity를 해준 뒤에 @ManyToOne을 사용해서 movie와 actor를 연결하는 식으로 사용해야 하는가???


그래서 생각해본 3가지의 방법이 있다...

  1. movie - movie_actor - actor 3개의 엔티티 클래스를 모두 만든 뒤에 movie_actor 클래스에서 @ManyToOne으로 movie와 actor를 연결한다! (내가 spring에서 써본 방식!)

  2. movie - actor 엔티티 클래스를 만든 뒤 @ManyToMany로 각자의 엔티티 클래스를 연결한다!? (M:N의 관계는 실제 테이블로 설계할 수가 없다는데 가능할까..........? 실무에서도 가능하면 '단방향 참조' 위주로 프로젝트를 진행한다는데... 문제가 발생할 것 같다)

  3. movie와 actor 엔티티 클래스를 만든 뒤 @ManyToMany를 사용하는데!

    Movie에서
    @ManyToMany
    @JoinTable(name = movie_actor.....) Set<Genre> genres;
    Genre에서도
    @ManyToMany(mappedBy = "genres")
    Set<Movie> movies;

    이런 식으로 다대다의 관계를 만드는 것이다........ 🤔🤔


추가로 공부를 해보니 3번과 같은 @ManyToMany 어노테이션을 사용해 다대다 매핑이 가능은 하지만 컬럼을 추가할 수도 없고 엔티티를 조회할 때 어떤 쿼리문이 실행될지 예측하기가 쉽지 않아서 사용하지 않는다고 한다.

1번 방식처럼 연결 테이블용 엔티티를 하나 생성한 후 일대다 다대일 관계로 매핑을 하는 게 맞는 것 같다.


다만 여기에서 내가 또 마음에 안드는 점이 생기는데... 바로 연결 테이블용 엔티티를 하나하나 다 만들어야 한다는 점이다...

내가 이전에 Spring에서 이렇게 굳이 ArrayList<Hash Map<....>> 을 사용하면서 다중 데이터를 가지고 왔던 이유는 깔끔했기 때문이다.

보통 다중 테이블에서 데이터를 추출 방법에 대해서 검색을 해보면 거의 VO를 필요한 테이블마다 생성하는 방식을 많이 추천해주는데..

나는 이 방식이 번거롭고 불필요한 VO 클래스가 많이 생성된다고 생각했다.

그래서 VO는 movie 하나만 사용하고 MyBatis의 Mapper MXl 파일에서 테이블 간의 매핑을 설정하고 HashMap 타입으로 받아와서 ArrayList에 담아 JSP로 보내는 방식을 사용했는데...

JPA에서는 다대다를 해소하기 위해서는 결국 Entity 클래스를 테이블마다 생성하는 방법밖에는 없는 건가? 하는 생각이 든다... 원래 이렇게 하는 건가... 😒

프로젝트를 진행해보고 공부를 좀 더 해보면 해결 방법이 나오겠지?

post-custom-banner

0개의 댓글