백엔드/JPA

[ JPA ] 5-2. Entity Relations ( 1:1 @OneToOne )

Reference. 한 번에 끝내는 Java/Spring 웹 개발 마스터 초격차 패키지 Online

이전 글

1. 속성

  • @OneToOne 속성
    • optional: 데이터가 필수적(not null)인지, 아닌지(null) 여부 ( default: true )
      → 필수적일 때(optional = false) 컬럼은 not null, select 쿼리는 inner join으로 변경
      Hibernate: 
          
          create table book_review_info (
             id bigint generated by default as identity,
              created_at timestamp,
              updated_at timestamp,
              average_review_score float not null,
              review_count integer not null,
              book_id bigint not null,
              primary key (id)
          )
      
      Hibernate: 
          select
              bookreview0_.id as id1_2_0_,
              bookreview0_.created_at as created_2_2_0_,
              bookreview0_.updated_at as updated_3_2_0_,
              bookreview0_.average_review_score as average_4_2_0_,
              bookreview0_.book_id as book_id6_2_0_,
              bookreview0_.review_count as review_c5_2_0_,
              book1_.id as id1_1_1_,
              book1_.created_at as created_2_1_1_,
              book1_.updated_at as updated_3_1_1_,
              book1_.author_id as author_i4_1_1_,
              book1_.category as category5_1_1_,
              book1_.name as name6_1_1_,
              book1_.publisher_id as publishe7_1_1_ 
          from
              book_review_info bookreview0_ 
          inner join
              book book1_ 
                  on bookreview0_.book_id=book1_.id 
          where
              bookreview0_.id=
    • mappedBy: 연관키를 해당 테이블에서는 가지지 않음
      • mappedBy="bookReviewInfo" 해당 Entity의 bean id로 사용, 값이 안맞으면 에러
      //mappedBy 설정 전
      public class BookReviewInfo extends BaseEntity{
      		...
      		@OneToOne(optional = false)
          private Book book;	
      		...
      }
      
      //실행결과 DDL book_id bigint not null
      Hibernate: 
          
      create table book_review_info (
         id bigint generated by default as identity,
          created_at timestamp,
          updated_at timestamp,
          average_review_score float not null,
          review_count integer not null,
          book_id bigint not null,
          primary key (id)
      )
      //mappedBy 설정 후
      public class BookReviewInfo extends BaseEntity{
      		...
      		@OneToOne(optional = false, mappedBy = "bookReviewInfo")
          private Book book;	
      		...
      }
      
      //실행결과 DDL book_id 없어짐
      Hibernate: 
      
          create table book_review_info (
             id bigint generated by default as identity,
              created_at timestamp,
              updated_at timestamp,
              average_review_score float not null,
              review_count integer not null,
              primary key (id)
          )

2. 최종 실행

  • @ToString.Exclude: Entity 릴레이션을 사용하는 경우에 toString()가 순환참조가 발생. 릴레이션을 단방향으로 걸거나 toString()에서 제거 필요 ( @ToString.exclude )
Book.java
public class Book extends BaseEntity{
		...
		@OneToOne(mappedBy = "book")
    @ToString.Exclude
    private BookReviewInfo bookReviewInfo;
}
BookReviewInfo.java
public class BookReviewInfo extends BaseEntity{
		...
		@OneToOne(optional = false)
    private Book book;	
		...
}
실행결과
//book에서 book_review_info_id가 mappedBy의해 사라짐
Hibernate: 
    
    create table book (
       id bigint generated by default as identity,
        created_at timestamp,
        updated_at timestamp,
        author_id bigint,
        category varchar(255),
        name varchar(255),
        publisher_id bigint,
        primary key (id)
    )

Hibernate: 
    
    create table book_review_info (
       id bigint generated by default as identity,
        created_at timestamp,
        updated_at timestamp,
        average_review_score float not null,
        review_count integer not null,
        book_id bigint not null,
        primary key (id)
    )

//쿼리 로그
Hibernate: 
    select
        bookreview0_.id as id1_2_0_,
        bookreview0_.created_at as created_2_2_0_,
        bookreview0_.updated_at as updated_3_2_0_,
        bookreview0_.average_review_score as average_4_2_0_,
        bookreview0_.book_id as book_id6_2_0_,
        bookreview0_.review_count as review_c5_2_0_,
        book1_.id as id1_1_1_,
        book1_.created_at as created_2_1_1_,
        book1_.updated_at as updated_3_1_1_,
        book1_.author_id as author_i4_1_1_,
        book1_.category as category5_1_1_,
        book1_.name as name6_1_1_,
        book1_.publisher_id as publishe7_1_1_ 
    from
        book_review_info bookreview0_ 
    inner join
        book book1_ 
            on bookreview0_.book_id=book1_.id 
    where
        bookreview0_.id=?

>>>Book(super=BaseEntity(createdAt=2021-07-25T10:06:09.851706, updatedAt=2021-07-25T10:06:09.851706), id=1, name=JPA 책, category=null, authorId=1, publisherId=1)

Hibernate: 
    select
        book0_.id as id1_1_0_,
        book0_.created_at as created_2_1_0_,
        book0_.updated_at as updated_3_1_0_,
        book0_.author_id as author_i4_1_0_,
        book0_.category as category5_1_0_,
        book0_.name as name6_1_0_,
        book0_.publisher_id as publishe7_1_0_,
        bookreview1_.id as id1_2_1_,
        bookreview1_.created_at as created_2_2_1_,
        bookreview1_.updated_at as updated_3_2_1_,
        bookreview1_.average_review_score as average_4_2_1_,
        bookreview1_.book_id as book_id6_2_1_,
        bookreview1_.review_count as review_c5_2_1_ 
    from
        book book0_ 
    left outer join
        book_review_info bookreview1_ 
            on book0_.id=bookreview1_.book_id 
    where
        book0_.id=?

>>>BookReviewInfo(super=BaseEntity(createdAt=2021-07-25T10:06:09.953707, updatedAt=2021-07-25T10:06:09.953707), id=1, book=Book(super=BaseEntity(createdAt=2021-07-25T10:06:09.851706, updatedAt=2021-07-25T10:06:09.851706), id=1, name=JPA 책, category=null, authorId=1, publisherId=1), averageReviewScore=4.5, reviewCount=2)