본문 바로가기
Spring/JPA

N 대 N 연관관계 설정

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

현업에서는 거의 사용되지 않는다.

 

예제

Author 클래스 생성

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.Collections;
import java.util.List;

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

    private String name;

    private String country;

    // N대N 관계 설정
    // stack 오버 플로우 처리
    // null 예외처리 방지 설정
    @ManyToMany
    @ToString.Exclude
    private List<Book> books = new ArrayList<>();

    // ... => 배열로 받는다는 의미
    // Book 정보가 여러개 존재하면 모두 처리
    public void addBook(Book... book){
        Collections.addAll(this.books, book);
//        if (book != null){
//            for (Book book1 : book){
//                this.books.add(book1);
//            }
//        }
    }
}

 

Book 클래스 수정 (아래 코드 추가)

    // N대N 관계 설정
    // stack 오버 플로우 처리
    // null 예외처리 방지 설정
    @ManyToMany
    @ToString.Exclude
    private List<Author> authors = new ArrayList<>();

    // ... => 배열로 받는다는 의미
    // Author 정보가 여러개 존재하면 모두 처리
    public void addAuthor(Author... author) {
        Collections.addAll(this.authors, author);
    }

 

AuthorRepository 인터페이스 생성 (JPA 사용을 위해서)

package com.example.bookmanager.repository;

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

public interface AuthorRepository extends JpaRepository<Author, Long> {

}

 

Test 코드 작성

package com.example.bookmanager.repository;

import com.example.bookmanager.domain.Author;
import com.example.bookmanager.domain.Book;
import org.assertj.core.util.Lists;
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 static org.junit.jupiter.api.Assertions.*;

@SpringBootTest
class AuthorRepositoryTest {

    @Autowired
    private AuthorRepository authorRepository;
    @Autowired
    private BookRepository bookRepository;

    @Test
    @Transactional
        // LazyInitializationException 에러 처리를 위해서 설정
    void manyToManyTest(){
        Book book1 = givenBook("책 1");
        Book book2 = givenBook("책 2");
        Book book3 = givenBook("개발책1");
        Book book4 = givenBook("개발책2");

        Author author1 = givenAuthor("martin");
        Author author2 = givenAuthor("steve");

        book1.addAuthor(author1);
        book2.addAuthor(author2);

        // 공동저자로 설정
        book3.addAuthor(author1,author2);
        book4.addAuthor(author1,author2);
//        book3.setAuthors(Lists.newArrayList(author1, author2));
//        book4.setAuthors(Lists.newArrayList(author1, author2));

        author1.addBook(book1, book3, book4);
        author2.addBook(book2, book3, book4);
//        author1.setBooks(Lists.newArrayList(book1, book3, book4));
//        author2.setBooks(Lists.newArrayList(book2, book3, book4));
        // 연관 관계 설정 종료

        bookRepository.saveAll(Lists.newArrayList(book1,book2,book3,book4));
        authorRepository.saveAll(Lists.newArrayList(author1, author2));

        System.out.println("3번째 책 가져오기: " + bookRepository.findAll().get(2).getAuthors());
        System.out.println("martin이 쓴 책 출력: " + authorRepository.findAll().get(0).getBooks());
    }

    private Book givenBook(String name) {
        Book book = new Book();
        book.setName(name);

        return bookRepository.save(book);
    }

    private Author givenAuthor(String name){
        Author author = new Author();
        author.setName(name);

        return authorRepository.save(author);
    }
}

 

콘솔 창 결과

3번째 책 가져오기: [Author(super=BaseEntity(createdAt=2021-08-29T14:47:15.186, updatedAt=2021-08-29T14:47:15.186), id=1, name=martin, country=null), Author(super=BaseEntity(createdAt=2021-08-29T14:47:15.202, updatedAt=2021-08-29T14:47:15.202), id=2, name=steve, country=null)]
martin이 쓴 책 출력: [Book(super=BaseEntity(createdAt=2021-08-29T14:47:15.154, updatedAt=2021-08-29T14:47:15.154), id=1, name=책 1, category=null, authorId=null), Book(super=BaseEntity(createdAt=2021-08-29T14:47:15.186, updatedAt=2021-08-29T14:47:15.186), id=3, name=개발책1, category=null, authorId=null), Book(super=BaseEntity(createdAt=2021-08-29T14:47:15.186, updatedAt=2021-08-29T14:47:15.186), id=4, name=개발책2, category=null, authorId=null)]

 

 

반응형