본문 바로가기
SpringBoot

@OneToOne

by se0nghyun2 2024. 4. 22.

도서(Book)와 도서 이미지(BookImage) 간 요구사항은 아래와 같다.

 

<요구사항>
일단은 도서 별로 도서이미지는 하나만 가지도록 해주시고!!

추후에 도서 별로 도서이미지는 여러 개 등록해주세요!!

 

위 요구사항에 대해 연관관계로는 @OneToOne으로 맺어주려 한다.

1:1관계는 반대로 해도 1:1이 된다.

즉, 주테이블이나 대상테이블 중 외래키를 어느쪽에서든 선택하여 지정할 수 가 있다.

 * 도서를 주테이블, 도서이미지를 대상 테이블라고 칭함

 

아래 @OneToOne에 대해 두 케이스를 가지고 어떤 장단점이 있는지 잊지 않도록 정리해보려 한다.

1. 연관관계 주인의 위치(외래키를 가지고 있는 테이블이 주인)
2. 양방향? 단방향?

 

 

Entity 객체

public class BookEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long bookCode;

    ...
}

public class BookImageEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long imgNo;
    
    ...
}

case1) 단방향 + Book(주테이블)이 연관관계 주인인 경우

Entity 객체

public class BookEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long bookCode;

    ...
    
    @OneToOne(cascade = CascadeType.PERSIST)
    @JoinColumn(name="img_no")                                                                                                            를 들고 있으므로 연관관계의 주인
    private BookImageEntity bookImage;

}

public class BookImageEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long imgNo;
    ...
}

 

테이블 구조

Book(외래키 컬럼 소유,오른쪽), BookImage(왼쪽)

Book 테이블에서 bookImage테이블의 img_no를 외래키를 가지게 된다.

 

 

도서 등록 실행

 

 

쿼리 로그 및 데이터 삽입 확인

위 메소드 실행 시 아래와 같이 두 번의 쿼리가 나가게 되며, 데이터 정상적으로 저장된다.

 

저장된 Book 데이터(오른쪽) ,  BookImage데이터(왼쪽) 

 

장점(개인적 주관)

regBook 메소드 내부 살펴보면, 코드 가독성이 올라갔다. 아 도서에 도서 이미지 등록했구나~~ 라고 바로 알 수 있게 된다.

 

단점

요구사항 중 여러 개의 도서 이미지를 등록에 대한 내용이 있었다.

현재 테이블 구조로는 여러 개의 이미지 등록을 나타낼 수 없다.

해당 요구사항을 충족시키려면 BookImage 테이블에서 Book의 외래키(book_code)를 가져야 한다.

주테이블과 대상테이블의 관계가 1:N이 되어버리면 엔티티구조,테이블 구조(외래키 위치 변경) 등 전반적인 수정이 필요할 것이다.

 

case2) 양방향 + Book(주테이블)이 연관관계 주인인 경우

두번째 요구사항의 해결을 위해선 테이블 구조 변경이 필요하여 패스

 

 

 


 

case3) 단방향 + BookImage(대상테이블)이 연관관계 주인인 경우

Entity 객체

public class BookEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long bookCode;

    ...
    
}

public class BookImageEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long imgNo;
    
    ...
    
    @OneToOne(cascade = CascadeType.PERSIST)
    @JoinColumn(name="book_no")
    private BookEntity book;
}

 

 

테이블구조

Book(오른쪽), BookImage(외래키 소유,왼쪽)

 

도서 등록

 

쿼리 로그 및 데이터 삽입 확인

위 메소드 실행 시 아래와 같이 두 번의 쿼리가 나가게 되며, 데이터 정상적으로 저장된다.

 

저장된 Book 데이터(오른쪽) ,  BookImage데이터(왼쪽) 

장점

요구사항 중 여러 개의 도서 이미지를 등록에 대한 내용이 있었다.

다시 말하면, 도서와 도서이미지 간 일대다 관계로 변경이 필요하며 일대다 관계는 다쪽에서 외래키를 들고 있어야 한다.

대상 테이블이 외래키를 소유하고 있기에 별도 테이블 구조 없이 일대다 적용이 가능하다. 

즉, 일대다 연관관계 변경에 용이하다.

 

단점

regBook메소드 내부를 봤을 때, 도서이미지를 저장함에 따라 도서엔티티가 저장된다. 

도서가 저장됨에 따라 도서이미지 엔티티가 저장되는 식의 구조를 생각했기에 해당 부분이 단점이라 생각한다.

 

그렇다면 장점을 유지한 채 도서가 저장됨에 따라 도서이미지 엔티티가 저장되게 할 순 없을까?? ( case4 도서등록v2로 해결가능) 

 

case4) 양방향 + BookImage(대상테이블)이 연관관계 주인인 경우

엔티티

public class BookEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long bookCode;
    
    //양방향
    @OneToOne(fetch = FetchType.LAZY, mappedBy = "book")
    private BookImageEntity bookImage;

    ...
    
}

public class BookImageEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long imgNo;
    
    ...
    
    @OneToOne
    @JoinColumn(name="book_no")
    private BookEntity book;
}

 

테이블구조

case3 와 동일

 

도서 등록 v1 (연관관계 주인(bookImage)을 통한 save)

  BookImage 엔티티(cascade 추가)

    @OneToOne(cascade = CascadeType.PERSIST)
    @JoinColumn(name="book_no")
    private BookEntity book;

 

흠.... case3 장점은 가지고 있으나 아직 단점에 대해선 보완되지 못하였다. v2를 보자.

 

 

도서 등록 v2 (연관관계 주인이 아닌 엔티티 (book) 를 통한 save)

  Book 엔티티(cascade추가)

    @OneToOne(fetch = FetchType.LAZY, mappedBy = "book",cascade = CascadeType.PERSIST)
    private BookImageEntity bookImage;

 

case3의 장점 및 단점에 대한 보완까지 이루어졌다!!

대신 양방향으로 묶여 혹여라도 객체 간의 참조를 통하여 불필요한 데이터 변경이 이루어 질 수 있다.

 

쿼리 로그 및 데이터 삽입 확인

case3와 동일

 

 


정리 ( save에 한해 )

주테이블이 연관관계 주인

장점: 코드 가독성 증가 

단점: 주테이블과 대상테이블 간의 관계가 1:N 변경 시 변경에 취약

 

대상 테이블이 연관관계 주인

장점: 주테이블과 대상테이블 간의 관계가 1:N 변경 시 변경 용이

단점: 단방향 시 코드 가독성 감소, 양방향 시 코드 가독성은 올라가나 양방향 객체 참조 가능으로 인한 문제 야기