본문 바로가기
Spring/JPA

1 대 1 관계 설정하는 방법

by step 1 2021. 7. 24.
반응형

Book 코드 수정


@GeneratedValue(strategy = GenerationType.IDENTITY):  테이블마다 각각의 ID값이 증가하도록 설정

@OneToOne: 1대1 관계를 형성할 때 사용하는 어노테이션

optional = false: 절대 null값을 허용하지 않겠다는 의미 (inner join), 기본값으로 설정하면 left outer 조인이 된다.

mappedBy = "book": 해당 객체가 테이블로 생성될때 선언한 컬럼은 키값을 생성하지 않도록 설정 

@ToString.Exclude: 어노테이션을 이용하여 해당 컬럼이 ToString에서 제외될 수 있도록 설정, 선언하지 않으면 스택오버플로우 에러가 발생하게 된다. 따라서 단방향 관계를 맺거나 ToString에서 해당 컬럼을 제외를 시켜주어야 한다.

package com.example.bookmanager.domain;

import com.example.bookmanager.domain.listener.Auditable;
import com.example.bookmanager.domain.listener.MyEntityListener;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;

import javax.persistence.*;
import java.time.LocalDateTime;

@Entity
@NoArgsConstructor
@Data
// 상속받은 BaseEntity를 사용하기 위해서 ToString, EqualsAndHashCode 재정의
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
// 해당 객체에 사용자가 정의한 Entity Listener가 수행되도록 선언해준다.
public class Book extends BaseEntity {
    @Id
    // 테이블마다 ID값이 증가하도록 설정
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    private String category;

    private Long authorId;

    private Long publisherId;

    @OneToOne(mappedBy = "book")
    // toString에서 제외
    @ToString.Exclude
    private BookReviewInfo bookReviewInfo;
}

mappedBy = "book" 설정으로 인한 ID값이 생성되지 않았다

 

BookReviewInfo 클래스 수정

기존의 BookId 값을 제거하고 Book 객체를 직접 참조하도록 설정

@OneToOne: 1대1 관계를 형성할 때 사용하는 어노테이션

optional = false: 절대 null값을 허용하지 않겠다는 의미 (inner join), 기본값으로 설정하면 left outer 조인이 된다.

package com.example.bookmanager.domain;

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

import javax.persistence.*;

@Entity
@NoArgsConstructor
@Data
// 상속받은 BaseEntity를 사용하기 위해서 ToString, EqualsAndHashCode 재정의
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
public class BookReviewInfo extends BaseEntity{

    @Id
    // 테이블마다 ID값이 증가하도록 설정
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

//    private Long bookId;

    // 1 대 1로 연관관계를 맵핑
    // book은 절대로 null을 허용하지 않도록 설정
    @OneToOne(optional = false)
    private Book book;

    private float averageReviewScore;

    private int reviewCount;
}

 

Test 코드 작성

    @Test
    void crudTest2() {

        givenBookReviewInfo();
        Book result = bookReviewInfoRepository
                .findById(1L)
                .orElseThrow(RuntimeException::new)
                .getBook();

        System.out.println("result >>> " + result);

        BookReviewInfo result2 = bookRepository
                .findById(1L)
                .orElseThrow(RuntimeException::new)
                .getBookReviewInfo();
        System.out.println("result2 >>> " + result2);
    }

    private Book givenBook(){

        Book book = new Book();
        book.setName("Jpa 초격차 패키지");
        book.setAuthorId(1L);
        book.setPublisherId(1L);
        System.out.println("book >>> " + book.toString());
        return bookRepository.save(book);
    }

    private void givenBookReviewInfo() {
        BookReviewInfo bookReviewInfo = new BookReviewInfo();
//        bookReviewInfo.setBookId(1L);
        bookReviewInfo.setBook(givenBook());
        bookReviewInfo.setAverageReviewScore(4.5f);
        bookReviewInfo.setReviewCount(2);

        bookReviewInfoRepository.save(bookReviewInfo);

        System.out.println(">>> " + bookReviewInfoRepository.findAll());
    }

 

테스트 코드를 실행시켜 보면 1대1 맵핑한 객체의 해당하는 id값을 자동으로 생성해주는 것을 확인할 수 있다.

result >>> Book(super=BaseEntity(createdAt=2021-07-24T22:58:16.274, updatedAt=2021-07-24T22:58:16.274), 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=?
2021-07-24 22:58:16.444 TRACE 17160 --- [    Test worker] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [BIGINT] - [1]
2021-07-24 22:58:16.445 TRACE 17160 --- [    Test worker] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([id1_2_1_] : [BIGINT]) - [1]
2021-07-24 22:58:16.445 TRACE 17160 --- [    Test worker] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([created_2_1_0_] : [TIMESTAMP]) - [2021-07-24T22:58:16.274]
2021-07-24 22:58:16.445 TRACE 17160 --- [    Test worker] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([updated_3_1_0_] : [TIMESTAMP]) - [2021-07-24T22:58:16.274]
2021-07-24 22:58:16.445 TRACE 17160 --- [    Test worker] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([author_i4_1_0_] : [BIGINT]) - [1]
2021-07-24 22:58:16.446 TRACE 17160 --- [    Test worker] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([category5_1_0_] : [VARCHAR]) - [null]
2021-07-24 22:58:16.446 TRACE 17160 --- [    Test worker] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([name6_1_0_] : [VARCHAR]) - [Jpa 초격차 패키지]
2021-07-24 22:58:16.446 TRACE 17160 --- [    Test worker] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([publishe7_1_0_] : [BIGINT]) - [1]
2021-07-24 22:58:16.446 TRACE 17160 --- [    Test worker] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([created_2_2_1_] : [TIMESTAMP]) - [2021-07-24T22:58:16.320]
2021-07-24 22:58:16.446 TRACE 17160 --- [    Test worker] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([updated_3_2_1_] : [TIMESTAMP]) - [2021-07-24T22:58:16.320]
2021-07-24 22:58:16.446 TRACE 17160 --- [    Test worker] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([average_4_2_1_] : [FLOAT]) - [4.5]
2021-07-24 22:58:16.446 TRACE 17160 --- [    Test worker] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([book_id6_2_1_] : [BIGINT]) - [1]
2021-07-24 22:58:16.446 TRACE 17160 --- [    Test worker] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([review_c5_2_1_] : [INTEGER]) - [2]
result2 >>> BookReviewInfo(super=BaseEntity(createdAt=2021-07-24T22:58:16.320, updatedAt=2021-07-24T22:58:16.320), id=1, book=Book(super=BaseEntity(createdAt=2021-07-24T22:58:16.274, updatedAt=2021-07-24T22:58:16.274), id=1, name=Jpa 초격차 패키지, category=null, authorId=1, publisherId=1), averageReviewScore=4.5, reviewCount=2)
반응형

'Spring > JPA' 카테고리의 다른 글

N 대 N 연관관계 설정  (0) 2021.08.29
1대N 연관관계  (0) 2021.08.06
연관 관계 설정 -1  (0) 2021.07.24
연관관계, ERD  (0) 2021.07.24
Entity Listener 사용 예제 2  (0) 2021.07.18