관계 데이터베이스 수업을 들었었다면 M:N관계에 있는 테이블의 설계방법을 다들 알고 계실 것입니다. 바로 새로운 테이블을 만들고, 두 엔티티의 기본키를 외래키로 참조하는 방법입니다.
JPA에서는 M:N관계를 설정해줄 수 있는 방법으로는 2가지가 있습니다.
@ManyToMany
어노테이션을 사용@ManyToOne
어노테이션 사용M:N 관계를 처리하는 법을 배우기 위해 영화 게시판 프로젝트를 생성하겠습니다.
그리고 build.gradle
과 application.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;
}