SpringBoot with JPA 프로젝트(M:N) 2.entity 생성,Mapping table 작성 및 데이터 생성

mingki·2022년 3월 6일
0

SpringBoot & JPA

목록 보기
21/26


📚 공부한 책 : 코드로배우는 스프링 부트 웹프로젝트
❤️ github 주소 : https://github.com/qkralswl689/LearnFromCode/tree/main/mreview2022

1.Entity 클래스 설계

1-1.Movie entity 클래스 작성

M:N 관계를 처리할 때는 반드시 맵핑 테이블의 설계는 마지막 단계에서 처리하고 '명사'에 해당하는 클래스를 먼저 설계한다
-> 영화(Movie)와 회원(Member)의 존재가 명사에 해당아므로 먼저 설계한다

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

@Entity
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Getter
@ToString
public class Movie extends BaseEntity{

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

    private String title;
}

1-2.MovieImage entity 클래스 작성

이미지에 대한 정보를 기록한다

  • java.util.UUID를 이용해 고유 번호 생성
  • 이미지의 저장 경로(path)는 년/월/일 폴더 구조를 의미한다
  • 테이블로 생성될 때는 movie 테이블이 PK를 가지고 movie_image 테이블은 FK를 가지게 되므로 @ManyToOne를 적용한다

import lombok.*;
import lombok.extern.java.Log;
import javax.persistence.*;

@Entity
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Getter
@ToString(exclude = "movie")
public class MovieImage {

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

    // java.util.UUID를 이용해 고유 번호 생성
    private String uuid;

    private String imgName;

    private String path;

    // movie 테이블이 PK를 가지고 movie_image 테이블이 FK를 가지므로 movie_image에 @ManyToOne 적용
    @ManyToOne(fetch = FetchType.LAZY)
    private Movie movie;
}

1-3.프로젝트 실행

프로젝트를 실행하여 테이블을 생성한다

Hibernate: 
    
    create table movie_image (
       inum bigint not null auto_increment,
        img_name varchar(255),
        path varchar(255),
        uuid varchar(255),
        movie_mno bigint,
        primary key (inum)
    ) engine=InnoDB
Hibernate: 
    
    alter table movie_image 
       add constraint FKitwj3761d8j8ku189u4qrseih 
       foreign key (movie_mno) 
       references movie (mno)

1-4.Member entity 클래스 작성


import lombok.*;
import javax.persistence.*;

@Entity
@Builder
@AllArgsConstructor
@NoArgsConstructor
@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;

}

2.Mapping table을 위한 Review 클래스 설계

Mapping table은 두 테이블 사이에서 양쪽의 PK를 참조하는 형태로 구성된다

  • Review 클래스는 Movie 와 Member를 양쪽으로 참조하는 구조로 @ManyToOne으로 설계한다

import lombok.*;
import javax.persistence.*;

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

    @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;
}

3.M:N(다대다) Repository 작성, 테스트

3-1.MovieRepository 작성

import com.example.mreview2022.entity.Movie;
import org.springframework.data.jpa.repository.JpaRepository;

public interface MovieRepository extends JpaRepository<Movie,Long> {
}

3-2.MovieImageRepository 작성

import com.example.mreview2022.entity.MovieImage;
import org.springframework.data.jpa.repository.JpaRepository;

public interface MovieImageRepository extends JpaRepository<MovieImage,Long> {
}

3-3.Test

영화와 이미지들은 같은 시점에 insert 처리가 되어야 한다
-> Movie 객체를 우선 저장(save())하고 save()가 실행된 뒤 Movie 객체는 PK에 해당하는 mno 값이 할당 되고, mno를 이용해 영화의 이미지들을 추가한다. 이미지들은 최대 5개까지 임의로 저장된다

import com.example.mreview2022.entity.Movie;
import com.example.mreview2022.entity.MovieImage;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.Commit;

import javax.transaction.Transactional;
import java.util.UUID;
import java.util.stream.IntStream;

@SpringBootTest
public class MovieRepositoryTests {

    @Autowired
    private MovieRepository movieRepository;

    @Autowired
    private MovieImageRepository imageRepository;

    @Commit
    @Transactional
    @Test
    public void insertMovies() {

        IntStream.rangeClosed(1,100).forEach(i ->{

            Movie movie = Movie.builder().title("Movie..." + i).build();

            System.out.println("------------------------");

            movieRepository.save(movie);

            int count = (int)(Math.random() * 5) + 1;

            for (int j = 0; j < count; j++){

                MovieImage movieImage = MovieImage.builder()
                        .uuid(UUID.randomUUID().toString())
                        .movie(movie)
                        .imgName("test" + j +".jpg").build();

                imageRepository.save(movieImage);

            }
            System.out.println("===============================");
        });
    }
}
  • 실행결과

4.Member생성

4-1.MemberRepository 작성

import com.example.mreview2022.entity.Member;
import org.springframework.data.jpa.repository.JpaRepository;

public interface MemberRepository extends JpaRepository<Member,Long> {
}

4-2.Test

import com.example.mreview2022.entity.Member;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.stream.IntStream;

@SpringBootTest
public class MemberRepositoryTests {

    @Autowired
    private MemberRepository memberRepository;

    @Test
    public void insertMembers(){

        IntStream.rangeClosed(1,100).forEach(i -> {
            Member member = Member.builder()
                    .email("r" + i + "@zerock.org")
                    .pw("1111")
                    .nickname("reviewer" + i).build();

            memberRepository.save(member);
        });
    }
}
  • 실행결과

5.Mapping table 데이터 추가

5-1.ReviewRepository 작성

import com.example.mreview2022.entity.Review;
import org.springframework.data.jpa.repository.JpaRepository;

public interface ReviewRepository extends JpaRepository<Review,Long> {
}

5-2.Test

200개의 MovieReview를 저장한다 영화의 번호,회원은 임의의 값으로 현재 DB에 존재하는 값으로 생성하고,
영화의 평점,리뷰 내용을 작성해 MovieReview 객체를 생성해 저장한다

import com.example.mreview2022.entity.Member;
import com.example.mreview2022.entity.Movie;
import com.example.mreview2022.entity.Review;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.stream.IntStream;

@SpringBootTest
public class ReviewRepositoryTests {

    @Autowired
    private ReviewRepository reviewRepository;

    @Test
    public void insertMovieReviews(){

        // 200개의 리뷰 등록
        IntStream.rangeClosed(1,200).forEach(i ->{

            //영화 번호
            Long mno = ((long)(Math.random()*100) + 1);

            //리뷰어 번호
            Long mid = ((long)(Math.random()*100) + 1);

            Member member = Member.builder().mid(mid).build();

            Review movieReview = Review.builder()
                    .member(member)
                    .movie(Movie.builder().mno(mno).build())
                    .grade((int)(Math.random()*5) + 1)
                    .text("이 영화에 대한 느낌 ..." + i)
                    .build();

            reviewRepository.save(movieReview);
        });
    }
}
  • 실행결과
profile
비전공초보개발자

0개의 댓글