-
Jpa 연관관계 살펴보기 (N:N)백엔드 2023. 8. 23. 14:39728x90반응형SMALL
다대다 관계에 있는 Entity의 설정 과정을 살펴보도록 하겠습니다. 중간 테이블을 자동으로 생성하는 @ManyToMany 방식보다는 매핑 테이블을 별도로 만들어서 각각의 엔티티와 1:N N:1 관계를 맺도록 해보도록 하겠습니다.
ERD
ERD 이전 시간에 살펴본 ERD에서 다대다 연결 관계를 가지고 있는 book과 author를 통해 살펴보도록 하겠습니다.
우선 book과 author 중간 매핑 테이블을 만들어줄 Entity를 선언해줍니다.
BookAndAuthor
@Entity @NoArgsConstructor @Data public class BookAndAuthor { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @ManyToOne private Book book; @ManyToOne private Author author; }
BookAndAuthor Entity의 경우 Book, Author Entity와 1:N 관계를 맺고 있으므로 @ManyToOne 어노테이션을 선언해줍니다.
이에 따라 Book과 Author Entity에도 BookAndAuthor Entity 관련 컬럼을 선언해줍니다.
Book
@Data @NoArgsConstructor @Entity public class Book { ... @OneToMany @JoinColumn(name = "book_id") @ToString.Exclude private List<BookAndAuthor> bookAndAuthors = new ArrayList<>(); public void addBookAndAuthor(BookAndAuthor... bookAndAuthors){ Collections.addAll(this.bookAndAuthors,bookAndAuthors); } }
Book과 BookAndAuthor의 관계는 1:N이므로 @OneToMany 어노테이션을 선언해주고, List로 선언해줍니다.
이미 매핑 테이블을 선언해두었기 때문에 새로운 테이블이 필요하지 않으므로 @JoinColumn을 join될 Entity의 어떤 컬럼에 매핑된다는 것을 지정해줍니다.
아래 addBookAndAuthor는 bookAndAuthor 값을 세팅해주는 메서드입니다.
Author
@Entity @NoArgsConstructor @Data public class Author { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; private String country; @OneToMany @JoinColumn(name = "author_id") @ToString.Exclude private List<BookAndAuthor> bookAndAuthors = new ArrayList<>(); public void addBookAndAuthor(BookAndAuthor... bookAndAuthors){ Collections.addAll(this.bookAndAuthors,bookAndAuthors); } }
Author와 BookAndAuthor의 관계도 1:N이므로 @OneToMany 어노테이션을 선언해주고, List로 선언해줍니다. 또한 @JoinColumn도 선언해주었습니다.
아래 addBookAndAuthor는 bookAndAuthor 값을 세팅해주는 메서드입니다.
위와 같이 Entity를 선언할 경우 나오는 ddl은 다음과 같습니다.
Hibernate: create table author ( id bigint generated by default as identity, country varchar(255), name varchar(255), primary key (id) ) Hibernate: create table book ( id bigint generated by default as identity, category varchar(255), name varchar(255), primary key (id) ) Hibernate: create table book_and_author ( id bigint generated by default as identity, author_id bigint, book_id bigint, primary key (id) )
book과 author에서는 book_and_author에 대한 FK가 존재하지 않고 book_and_author에만 book, author에 대한 FK가 생성된 것을 알 수 있습니다.
예제 )
public BookAndAuthor givenBookAndAuthor(Book book, Author author){ BookAndAuthor bookAndAuthor = new BookAndAuthor(); bookAndAuthor.setBook(book); bookAndAuthor.setAuthor(author); return bookAndAuthorRepository.save(bookAndAuthor); } @Transactional @Test public void test3(){ // Book 생성 Book book1 = new Book(); book1.setName("book1"); book1.setCategory("category1"); Book book2 = new Book(); book2.setName("book2"); book2.setCategory("category2"); bookRepository.save(book1); bookRepository.save(book2); // Author 생성 Author author1 = new Author(); author1.setName("author1"); author1.setCountry("country1"); Author author2 = new Author(); author2.setName("author1"); author2.setCountry("country1"); authorRepository.save(author1); authorRepository.save(author2); // BookAndAuthor 생성 BookAndAuthor bookAndAuthor1 = givenBookAndAuthor(book1,author1); BookAndAuthor bookAndAuthor2 = givenBookAndAuthor(book1,author2); BookAndAuthor bookAndAuthor3 = givenBookAndAuthor(book2,author1); BookAndAuthor bookAndAuthor4 = givenBookAndAuthor(book2,author2); // book, author에도 연관 관계 추가 book1.addBookAndAuthor(bookAndAuthor1,bookAndAuthor2); book2.addBookAndAuthor(bookAndAuthor3,bookAndAuthor4); author1.addBookAndAuthor(bookAndAuthor1,bookAndAuthor2); author2.addBookAndAuthor(bookAndAuthor3,bookAndAuthor4); bookRepository.saveAll(Lists.newArrayList(book1,book2)); authorRepository.saveAll(Lists.newArrayList(author1,author2)); bookRepository.findAll().get(1).getBookAndAuthors().forEach(System.out::println); }
출력
Hibernate: select book0_.id as id1_1_, book0_.category as category2_1_, book0_.name as name3_1_ from book book0_ BookAndAuthor(id=3, book=Book(id=2, name=book2, category=category2), author=Author(id=1, name=author1, country=country1)) BookAndAuthor(id=4, book=Book(id=2, name=book2, category=category2), author=Author(id=2, name=author1, country=country1))
연관된 모든 값들을 출력해주는 것을 알 수 있습니다.
이번 포스팅까지 Entity relation에 대해 알아보았습니다. 의도하지 않은 중간 테이블이 생기거나, 추가적인 쿼리가 발생하는 것을 막기 위해 많이 시도해보는 것이 좋을 것 같습니다.
반응형LIST'백엔드' 카테고리의 다른 글
JPA Transaction (0) 2023.08.25 영속성 컨텍스트, Entity Cache, Entity Lifecycle (2) 2023.08.24 JPA 연관관계 살펴보기 (1:1, 1:N, N:1) (4) 2023.08.21 Entity annotation, Listener (1) 2023.08.19 JPA 쿼리메서드 (0) 2023.08.18