minlog
article thumbnail

 

연관관계(relation) 및  ERD

ERD(앤티티 릴레이션십 다이어그램의 줄임말)

 


 

1 . 1 : 1연관관계 - @OneToOn

@OneToOn 어노테이션 옵션
optional default 값은 true 이다.   >  outer join 
false 설정 시 not null로 설정 된다. >  inner join 
mappedBy 연관 키를 해당 테이블에서 가지지 않게 만들어준다.

 

🍫 책과 책 리뷰와의 관계

1) 객체 생성

Book , BookReviewInfo 객체 생성

 

-  필드에 bookId 대신 Book 객체를 넣어줄 수 잇다. 

@OneToOn :  1 : 1 연관관계라는 선언.

jpa에서는 entity로 set,get을 하면 릴레이션을 자동으로 맺을 수 있도록 처리해준다.

 

📑BookReviewInfo

@Entity
@NoArgsConstructor
@Data
public class BookReviewInfo extends BaseEntity{
    @Id
    @GeneratedValue
    private Long id;
    // private Long bookId;
    @OneToOne        
    private Book book; 
    private float averageReviewScore; 
    private int reviewCount;
}

 

 

2) Repository JPA 인터페이스 생성

BookRepository , BookReviewInfoRepository 인터페이스 생성

 

📑 BookReviewInfoRepository

public interface BookReviewInfoRepository extends JpaRepository<BookReviewInfo,Long>{
}

 

3) Join 테스트

@Autowired
private BookReviewInfoRepository bookReviewInfoRepository;

@Autowired
private BookRepository bookRepository;

@Test
void crudTest(){
    givenBookReviewInfo();
    Book result = BookRepository.findById(1L)
                                .orElseThrow(RuntimeException::new)
                                .getBook();
    System.out.println(result);
}

private Book givenBook(){
    Book book = new Book();
    book.setName("jap");
    book.setAuthorId(1L);
    book.setPublisherId(1L);
}

private void givenBookReviewInfo(){
    BookReviewInfo bookReviewInfo = new BookReviewInfo();
    bookReviewInfo.SetBook(givenBook());
    bookReviewInfo.setAverageReviewScore(4.5f);
    bookReviewInfo.setReviewCount(2);

    bookReviewInfoRepository.save(bookReviewInfo);
    System.out.println(bookReviewInfoRepository.findAll());
       
}

 

 


 

2 .  1 : N 연관관계 - @OneToMany

@OneToMany 어노테이션 옵션
fetch fetchType.EAGER

 

🍫 고객정보와 고객이 변경한 정보 리스트와의 관계

 

1) 객체 생성

User , UserHistory 객체 생성

 

- @JoinColumn  : entity가 어떤 컬럼으로 조인이 될지 정해주는 어노테이션 

@JoinColumn(name="user_id",insertable=false,updatable=false)  :  user 객체에서 디비 명 설정(설정 하지 않을시 필요 없는 중간   테이블이 생성될 수 있다.) 및 객체 내에서는 해당 필드를 저장 및 수정이 불가능하도록 설정 

 

- user 는 하나이지만 변경 기록은 여러개 일 수 있기 때문에 userHistory 객채를 List로 받는다.

 

📑User

public class User extends BaseEntity{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY) //자동으로 증가
    private Long id;
    @NonNull
    private String name;
    @NonNull
    private String email;
    @Enumerated(value = EnumType.STRING)
    private Gender gender;
  
    @OneToMany
    @JoinColumn(name="user_id",insertable=false,updatable=false) 
    private List<UserHistory> userHistories = new ArrayList<>();
}

📑UserHistory

public class UserHistory extends BaseEntity{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY) //자동으로 증가
    private Long id;
    
    @Column(name="user_id")
    private Long userId;
    
    private String name;
    private String email;
    private Gender gender;
  
}

 

2) Join 테스트

- 적용 전 코드 

userHistoryRepository.findAll().forEach(System.out::println);
List<UserHistory> result = userHistoryRepository.findByUserId(
	userRepository.findByEmail("d@naver.com").getId());

- jpa 어노테이션을 활용시 코드

 

List<UserHistory> result = userHistoryRepository.findByEmail("d@naver.com").userHistories();
result.forEach(System.out::println);

 


3 .  N : 1 연관관계 -  @ManyToOne


4 .  M : N 연관관계 -  @ManyToMany

( ※ 실제 실무에서는 거이 사용되지 않음 )

ex) 상품 주문 > 상품 , 고객은 ManyToMany 이지만, 주문(Order)라는 중간 테이블을 생성하여 1 : N 형식으로 변경해줄수 있다.

 

 

🍫 책과 작가와의 관계

1) 객체 생성

Author , Book 객체 생성

 

📑author

@Entity
@NOArgsConstructor
@Data
@ToString(callSupper =ture)
@EqualsAndHashCode(callSupper =ture)
public class Author extends BaseEntity{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String country;
    @ManyToMany
    @ToString.Exclude
    private List<Book> books = new ArrayList<>();
    
    //리스트 생성을 위한 메서드 
	    // ... 배열로 받겠다는 의미
    public void addBook(Book... book){
    	Collections.addAll(this.books, book);
    }
}

📑 book ( authores 정보 추가 )

@ManyToMany
@ToString.Exclude
private List<Author> authors = new ArrayList<>();
//리스트 생성을 위한 메서드
public void addAuthor(Author... author){
    Collections.addAll(this.authors, author)   
}

 

2) TEST 생성

- @ToString.Exclude : 순환관계에 있는 객체들은 선언을 해줄 필요가 있다.

@SpringBootTest
class AuthorRepositoryTest{
	@Autowired
    private AuthorRepository authorRepository;
    @Autowired
    private BookRepository bookRepository;
    
    @Test
    @Transactional
    void manyToManyTest(){
    	Book book1 = givenBook("책1");
        Book book2 = givenBook("책2");
        Book book3 = givenBook("책3");
        Book book4 = givenBook("책4");
        Author author1 = givenAuthor("작가 1");
        Author author2 = givenAuthor("작가 2");
        
        book1.addAuthor(author1);
        book2.addAuthor(author2);
        book3.addAuthor(author1, author2);
        book4.addAuthor(author1, author2);

        author1.addBook(book1,book3,book4);
        author1.addBook(book2,book3,book4);
        
        bookRepository.saveAll(List.newArrayList(book1,book2,book3,book4));
        bookRepository.saveAll(List.newArrayList(author1,author2));
        // 세번째 책을 쓴 작가들을 출력
        System.out.println("authors through book : " + bookRepository.findAll().get(2).getAuthors());
        // 첫번째 작가가 쓴 책들을 출력
        System.out.println("books through author : " + 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);
    }
    
}

 

 

profile

minlog

@jimin-log

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!