반응형
💡구현 목표
- 영화(Movie)와 회원(Member)이 있고 회원이 영화에 대한 리뷰(Review)를 기록하는 시나리오를 기반으로 프로젝트를 구성함.
- 한 편의 영화는 여러 회원의 평가가 행해질 수 있다.
- 한 명의 회원은 여러 영화에 대해 평점을 줄 수 있다.
💡다대다 관계의 특징
다대다 관계(M:N)는 논리적 설계와 실제 테이블 설계가 다르게 됨.
- 영화 엔티티와 회원 엔티티는 양쪽 모두 독립적인 엔티티로 설계가 가능함.(대부분 명사인 경우)
- 사람에 해당하는 회원 입장에서는 여러 편의 영화를 평가한다는 구조가 됨.
- 영화 입장에서는 한 편의 영화는 여러 회원이 존재한다는 관계가 성립하게 됨.
다대다(M:N)를 해결하기 위해서는 실제 테이블 설계에 매핑(mapping) 테이블을 사용함. (=연결 테이블)
- 여기에서는 리뷰 테이블을 중간에 추가하기로 함.
매핑 테이블의 특징은
- 매핑 테이블의 작성 이전에 다른 테이블들이 먼저 존재해야함.
- 매핑 테이블은 주로 '명사'가 아닌 '동사', '히스토리'에 대한 데이터를 보관하는 용도.
- 매핑 테이블은 중간에서 양쪽 PK를 참조하는 형태로 사용됨.
결론 : JPA에서 다대다(M:N)을 처리하는 방식 중 별도 엔티티를 설계하고 @ManyToOne을 이용해서 처리하는 방식으로 구현할 예정.
🤍영화 리뷰 프로젝트
1. 엔티티 클래스 설계
- 매핑 테이블은 주로 동사나 히스토리를 의미 -> 여기에서는 '회원이 영화에 대해 평점을 준다'는 행위로 매핑 테이블이 필요함.
- 회원(Member)이라는 주어와 영화(Movie)라는 목적어가 있지만 이에 대한 '평점을 준다'는 부분이 없기 때문에 연결 매핑 테이블로 리뷰(Review) 테이블을 설계함.
- Review 엔티티는 @ManyToOne을 이용해서 양쪽을 참조하는 구조가 됨.
2. 완성된 테이블 ERD
3. 각각 Repository를 생성 후 더미 데이터를 넣는 작업
- MemberRepository
public interface MemberRepository extends JpaRepository<Member, Long> {
}
@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);
});
}
총 100명의 회원을 추가함.
- MovieImageRepository, MovieRepository
public interface MovieImageRepository extends JpaRepository<MovieImage,Long> {
}
public interface MovieRepository extends JpaRepository<Movie, Long> {
}
//영화 및 영화 이미지를 추가하는 테스트
@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; //1,2,3,4
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("=================================");
}
});
}
- 영화와 영화 이미지는 같은 시점에 insert처리가 되어야하므로 Movie 객체를 우선 save해줌.
- save 실행 이후 Movie 객체는 PK에 해당하는 mno값이 할당되므로 이를 이용해서 영화 이미지를 추가함.
- ReviewRepository
public interface ReviewRepository extends JpaRepository<Review,Long> {
}
@Test
public void insertMoviewReviews(){
//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);
});
}
- 200개의 리뷰를 저장함.
- 영화 번호와 회원은 임의의 값으로 DB에 존재하는 값으로 생성해서 처리, 영화 평점과 리뷰의 내용을 작성해서 MovieReview 객체를 생성해서 저장함.
- 임의로 만들어졌기 때문에 중간에 리뷰가 없는 영화도 있음.
반응형
'💻 my code archive > 🏷️JAVA & Spring(Boot)' 카테고리의 다른 글
스프링부트 공부기록(28) - 영화 리뷰 프로젝트 :: 영화 등록 구현하기 (0) | 2022.03.20 |
---|---|
스프링부트 공부기록(27) - 영화 리뷰 프로젝트 :: 파일 업로드 처리, 영화 포스터 업로드 구현하기 (0) | 2022.03.20 |
[스프링부트 블로그 만들기] 글 상세보기, 글 삭제하기, 글 수정하기 구현하기 (0) | 2022.03.19 |
[스프링부트 블로그 만들기] 글쓰기, 글 목록보기, 페이징 구현하기 (0) | 2022.03.19 |
[스프링부트 블로그 만들기] 비밀번호 해쉬화(암호화), 스프링 시큐리티 로그인 구현하기 (0) | 2022.03.19 |