본문 바로가기
프론트엔드/Vue.js

N대1 연관관계

by step 1 2021. 8. 8.
반응형

N대1의 연관관계를 설정하기 위해서는 아래와 같은 코드로 작성한다.

@ManyToOne
@ToString.Exclude
private Publisher publisher;

위 코드를 작성하면 아래화면과 같이 해당 테이블에 외래키가 자동으로 작성된다.

 

N대1 연관관계를 맺으면 연관된 테이블에 데이터를 가져올때 get 메소드를 통해서 가져온다.

System.out.println("Publisher: " + user.getReviews().get(0).getBook().getPublisher());

 

예제코드

Review 클래스 생성

package com.example.bookmanager.domain;

import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;

import javax.persistence.*;
import java.util.Calendar;

@Entity
@NoArgsConstructor
@Data
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
public class Review extends BaseEntity{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String title;

    private String content;

    private float score;

    @ManyToOne
    private User user;

    @ManyToOne
    private Book book;
}

Jpa 사용을 위해 repository 구현

package com.example.bookmanager.repository;

import com.example.bookmanager.domain.Review;
import org.springframework.data.jpa.repository.JpaRepository;

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

테이블 생성 확인

Review 와 마찬가지로 Publisher 클래스 생성

package com.example.bookmanager.domain;

import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;

import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;

@Entity
@NoArgsConstructor
@Data
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
public class Publisher extends BaseEntity{

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

    private String name;

    @OneToMany(fetch = FetchType.EAGER)
    //  new ArrayList<>(): null 예외처리 방지
    @JoinColumn(name = "publisher_id")
    private List<Book> books = new ArrayList<>();


}

repository 생성

package com.example.bookmanager.repository;

import com.example.bookmanager.domain.Publisher;
import org.springframework.data.jpa.repository.JpaRepository;

public interface PublisherRepository extends JpaRepository<Publisher, Long> {
}

테이블 생성 확인

 

 

User 클래스 코드 추가 (review 테이블과 연관관계를 맺는다. 1대N관계)

@OneToMany(fetch = FetchType.EAGER)
@JoinColumn(name = "user_id")
@ToString.Exclude
private List<Review> reviews = new ArrayList<>();

1대 N관계는 외래키가 생성되지 않는다.

Book 클래스 코드 추가

    @OneToMany
    @JoinColumn
    @ToString.Exclude
    private List<Review> reviews = new ArrayList<>();

    @ManyToOne
    @ToString.Exclude
    private Publisher publisher;

 

테스트 코드

package com.example.bookmanager.repository;

import com.example.bookmanager.domain.Book;
import com.example.bookmanager.domain.Publisher;
import com.example.bookmanager.domain.Review;
import com.example.bookmanager.domain.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import javax.transaction.Transactional;
import java.time.LocalDateTime;

import static org.junit.jupiter.api.Assertions.*;

@SpringBootTest
class BookRepositoryTest {

    @Autowired
    private BookRepository bookRepository;
    @Autowired
    private PublisherRepository publisherRepository;
    @Autowired
    private ReviewRepository reviewRepository;
    @Autowired
    private UserRepository userRepository;

    // 테스트를 진행하기 전에 데이터를 입려하는 부분
    public void Dto(){
        // 기본 데이터 생성 jpa를 이용하여 insert 된다.
        userRepository.save(new User("martin", "martin@naver.com", LocalDateTime.now(), LocalDateTime.now()));
        userRepository.save(new User("dennis", "dennis@fastcampus.com", LocalDateTime.now(), LocalDateTime.now()));
        userRepository.save(new User("sophia", "sophia@fastcampus.com", LocalDateTime.now(), LocalDateTime.now()));
        userRepository.save(new User("james", "james@fastcampus.com", LocalDateTime.now(), LocalDateTime.now()));
        userRepository.save(new User("martin2", "martin2@fastcampus.com", LocalDateTime.now(), LocalDateTime.now()));
        userRepository.save(new User("martin", "martin555@fastcampus.com", LocalDateTime.now(), LocalDateTime.now()));
    }

    @Test
//    @Transactional
 //   @Transactional
    void bookRelationTest(){
        Dto();
        givenBookAndReview();

        User user = userRepository.findByEmail("martin@naver.com");
        System.out.println("확인5: " + user.toString());
        System.out.println("Review: " + user.getReviews().toString());
        System.out.println("Book: " + user.getReviews().get(0).getBook());
        System.out.println("Publisher: " + user.getReviews().get(0).getBook().getPublisher());

    }

    private void givenBookAndReview(){
        givenReview(givenUser(), givenBook(givenPublisher()));
    }

    private User givenUser(){
        System.out.println("확인: " + userRepository.findByEmail("martin@naver.com").toString());
        return userRepository.findByEmail("martin@naver.com");
    }
    private Book givenBook(Publisher publisher){
        Book book = new Book();
        book.setName("jpa 패키지");
        book.setPublisher(publisher);
        System.out.println("확인: " + publisher.toString());
        return bookRepository.save(book);
    }
    private Publisher givenPublisher() {
        Publisher publisher = new Publisher();
        publisher.setName("공부하자");
        return publisherRepository.save(publisher);
    }
    private void givenReview(User user, Book book){
        Review review = new Review();
//        review.setId(1L);
        review.setTitle("리뷰 제목");
        review.setContent("리뷰 내용");
        review.setScore(5.0f);
        review.setUser(user);
        review.setBook(book);
        System.out.println("확인2: " + user.toString());
        System.out.println("확인3: " + book.toString());
        System.out.println("확인4: " + review.toString());
        reviewRepository.save(review);
    }
}

 

콘솔 쿼리

select
        books0_.publisher_id as publishe7_1_0_,
        books0_.id as id1_1_0_,
        books0_.id as id1_1_1_,
        books0_.created_at as created_2_1_1_,
        books0_.updated_at as updated_3_1_1_,
        books0_.author_id as author_i4_1_1_,
        books0_.category as category5_1_1_,
        books0_.name as name6_1_1_,
        books0_.publisher_id as publishe7_1_1_,
        bookreview1_.id as id1_2_2_,
        bookreview1_.created_at as created_2_2_2_,
        bookreview1_.updated_at as updated_3_2_2_,
        bookreview1_.average_review_score as average_4_2_2_,
        bookreview1_.book_id as book_id6_2_2_,
        bookreview1_.review_count as review_c5_2_2_ 
    from
        book books0_ 
    left outer join
        book_review_info bookreview1_ 
            on books0_.id=bookreview1_.book_id 
    where
        books0_.publisher_id=?

결과 확인

확인5: User(id=1, name=martin, email=martin@naver.com, createdAt=2021-08-08T17:18:17.309, updatedAt=2021-08-08T17:18:17.309, gender=null)
Review: [Review(super=BaseEntity(createdAt=2021-08-08T17:18:17.538, updatedAt=2021-08-08T17:18:17.538), id=1, title=리뷰 제목, content=리뷰 내용, score=5.0, user=User(id=1, name=martin, email=martin@naver.com, createdAt=2021-08-08T17:18:17.309, updatedAt=2021-08-08T17:18:17.309, gender=null), book=Book(super=BaseEntity(createdAt=2021-08-08T17:18:17.538, updatedAt=2021-08-08T17:18:17.538), id=1, name=jpa 패키지, category=null, authorId=null))]
Book: Book(super=BaseEntity(createdAt=2021-08-08T17:18:17.538, updatedAt=2021-08-08T17:18:17.538), id=1, name=jpa 패키지, category=null, authorId=null)
Publisher: Publisher(super=BaseEntity(createdAt=2021-08-08T17:18:17.522, updatedAt=2021-08-08T17:18:17.522), id=1, name=공부하자, books=[Book(super=BaseEntity(createdAt=2021-08-08T17:18:17.538, updatedAt=2021-08-08T17:18:17.538), id=1, name=jpa 패키지, category=null, authorId=null)])
반응형