[코드로 배우는 스프링부트 웹 프로젝트] - M:N 관계

Jongwon·2023년 1월 11일
0

관계 데이터베이스 수업을 들었었다면 M:N관계에 있는 테이블의 설계방법을 다들 알고 계실 것입니다. 바로 새로운 테이블을 만들고, 두 엔티티의 기본키를 외래키로 참조하는 방법입니다.

JPA에서는 M:N관계를 설정해줄 수 있는 방법으로는 2가지가 있습니다.

  • @ManyToMany 어노테이션을 사용
    M:N 관계를 자동적으로 설정해줍니다. 하지만 두 테이블의 매핑 정보 이외에는 추가적인 애트리뷰트 지정이 불가능합니다. 또한 양방향 참조를 진행해야 하기 때문에, 컨텍스트 상의 엔티티 객체들의 상태를 동기화하는 작업이 복잡합니다.
  • 매핑 테이블을 엔티티로 설계하고 @ManyToOne어노테이션 사용
    이 방법의 사용을 권장합니다. 연관관계를 사용하여 조회를 해야하는 경우에도 Join을 통해 원하는 데이터를 추출할 수 있습니다.


M:N 관계를 처리하는 법을 배우기 위해 영화 게시판 프로젝트를 생성하겠습니다.

그리고 build.gradleapplication.properties에 이전 예제에서 사용한 MariaDB 관련 설정을 넣어줍니다.

build.gradle

dependencies에 추가
	// https://mvnrepository.com/artifact/org.mariadb.jdbc/mariadb-java-client
	implementation group: 'org.mariadb.jdbc', name: 'mariadb-java-client', version: '3.1.0'

application.properties

spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
spring.datasource.url=jdbc:mariadb://localhost:3308/bootex
spring.datasource.username=bootuser
spring.datasource.password=bootuser

spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.show-sql=true


spring.thymeleaf.cache=false

그리고 이전 예제에서 사용한 BaseEntity를 추가합니다. 이때 메인 클래스에 @EnableJpaAuditing를 추가하여 Auditing 기능을 할 수 있도록 합니다.


다음으로는 엔티티를 생성합니다. BaseEntity를 상속받는 Movie엔티티와, Movie와 1:N의 연관관계를 가질 MovieImage엔티티를 생성합니다.

Movie

package org.zerock.mreview.entity;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.*;

@Entity
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Getter
@ToString
public class Movie extends BaseEntity {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long mno;
    
    private String title;
    
}

MovieImage

package org.zerock.mreview.entity;

import jakarta.persistence.*;
import lombok.*;

@Entity
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Getter
@ToString(exclude = "movie")
public class MovieImage {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long inum;
    
    private String uuid;
    
    private String imgName;
    
    private String path;
    
    @ManyToOne(fetch = FetchType.LAZY)
    private Movie movie;
    
}

그리고 Member 엔티티도 생성해줍니다.

Member

package org.zerock.mreview.entity;

import jakarta.persistence.*;
import lombok.*;

@Entity
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Getter
@ToString
@Table(name = "m_member")
public class Member extends BaseEntity{
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long mid;
    
    private String email;
    
    private String pw;
    
    private String nickname;
}


앞에서 언급한 Movie와 Member는 M:N 연관관계입니다. 하나의 Movie에 여러 사용자가 댓글을 입력할 수 있고, 사용자는 여러 Movie에 입력한 댓글이 존재합니다.

별도의 엔티티 Review를 만들고, Member, Movie와 1:N 연관관계를 설정해 M:N 관계를 해소하겠습니다.

Review

package org.zerock.mreview.entity;

import jakarta.persistence.*;
import lombok.*;

@Entity
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Getter
@ToString(exclude = {"movie", "member"})
public class Review {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long reviewnum;

    @ManyToOne(fetch = FetchType.LAZY)
    private Movie movie;

    @ManyToOne(fetch = FetchType.LAZY)
    private Member member;

    private int grade;

    private String text;
}
profile
Backend Engineer

0개의 댓글