[Spring Data JPA] @ManyToMany (다대다) 관계 설정하기👥

김찬미·2024년 8월 22일
0

Spring Boot

목록 보기
7/7

✅ BackGround

Spring Data JPA에서는 두 엔티티 간의 다대다(Many-to-Many) 관계를 설정할 때 @ManyToMany 어노테이션을 사용한다. 이 관계를 설정할 때는 중간에 연결 테이블을 사용해 두 엔티티를 연결하는데, 이러한 개념은 알아도 실제로 적용하는 법을 모를 때가 종종 있다.

이번 포스트에서는 실제로 @ManyToMany@JoinTable 어노테이션을 사용하여 다대다 관계를 설정하는 방법과 작동 방식에 대해 설명해 보도록 하겠다.

💡 기본 개념

☝️ 한 작가가 여러 책을 쓸 수 있고, 하나의 책에도 여러 작가가 존재할 수 있다.

  • 다대다(Many-to-Many) 관계: 하나의 엔티티 인스턴스가 여러 엔티티 인스턴스와 연관되고, 반대로 여러 엔티티 인스턴스가 또 다른 엔티티 인스턴스와 연관되는 관계이다.

  • 연결 테이블: 두 엔티티 간의 다대다 관계를 관리하기 위해 사용하는 중간 테이블이다.


💻 예제 코드

1. ChatRoom 엔티티

ChatRoom 엔티티는 채팅방을 나타내며, 여러 사용자가 참여할 수 있다.

@Entity
public class ChatRoom {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "chat_room_name", nullable = false, unique = true)
    private String chatRoomName;

    @ManyToMany
    @JoinTable(
            name = "user_chat_room",
            joinColumns = @JoinColumn(name = "chat_room_id"),
            inverseJoinColumns = @JoinColumn(name = "user_id")
    )
    private Set<User> users = new HashSet<>();
}

2. User 엔티티

User 엔티티는 사용자를 나타내며, 여러 채팅방에 참여할 수 있습니다.

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String username;

    @ManyToMany(mappedBy = "users")  // "users"는 ChatRoom 엔티티에서 정의한 필드명
    private Set<ChatRoom> chatRooms = new HashSet<>();
}

여기서는 예시를 위해 ChatRoom이라는 채팅방과 User라는 엔티티를 사용할 것이다. 사용자는 여러 채팅방에 참여할 수 있고, 하나의 채팅방에는 여러 유저가 들어올 수 있다.

다음으로는 여기서 사용된 어노테이션과 주요 속성에 대해 알아보자.

@JoinTable 어노테이션

@JoinTable은 두 엔티티 간의 다대다 관계를 설정할 때 사용되는 연결 테이블 어노테이션이다. 이 어노테이션은 연결 테이블의 이름과 컬럼을 정의한다.

주요 속성

  • name: 연결 테이블의 이름을 지정한다.
  • joinColumns: 현재 엔티티의 기본 키가 연결 테이블에서 어떤 컬럼과 매핑될지를 정의한다.
  • inverseJoinColumns: 연관된 엔티티의 기본 키가 연결 테이블에서 어떤 컬럼과 매핑될지를 정의한다.

코드 설명

@ManyToMany
@JoinTable(
        name = "user_chat_room",  // 연결 테이블의 이름
        // ChatRoom 엔티티의 기본 키
        joinColumns = @JoinColumn(name = "chat_room_id"),
        // User 엔티티의 기본 키
        inverseJoinColumns = @JoinColumn(name = "user_id")
)
private Set<User> users = new HashSet<>();
  • joinColumnsChatRoom 엔티티의 id와 연결 테이블의 chat_room_id를 매핑한다.
  • inverseJoinColumnsUser 엔티티의 id와 연결 테이블의 user_id를 매핑한다.

🔄️ 작동 방식

user_chat_room 연결 테이블

컬럼명데이터 타입설명
chat_room_idBIGINTChatRoom 테이블의 ID (외래키)
user_idBIGINTUser 테이블의 ID (외래키)
  1. 연결 테이블 생성: JPA는 ChatRoomUser 사이에 user_chat_room이라는 연결 테이블을 생성하여, 두 테이블 간의 관계를 관리한다.

  2. 컬럼 매핑: chat_room_id 컬럼은 ChatRoom 엔티티의 기본 키(id)와 연결되며, user_id 컬럼은 User 엔티티의 기본 키(id)와 연결된다.

  3. 양방향 연관: ChatRoom 엔티티는 users 필드를 통해 참여하는 사용자들을 참조하고, User 엔티티는 chatRooms 필드를 통해 참여하는 채팅방을 참조한다.


✈️ 마치며

다대다, 일대다, 일대일 관계 등을 제대로 알긴 했지만 실제로 JPA에서 사용하려고 하면 순간 머뭇거릴 때가 있었다. 이 기회에 제대로 DB의 연결 관계에 대해서 공부하고, 더 익숙해지려고 한다. 특히 실전 경험이 중요한 만큼 열심히 이번 프로젝트에서 써봐야겠다!

profile
백엔드 개발자

0개의 댓글

관련 채용 정보