SpringBoot/오류

@OneToOne 지연로딩?

se0nghyun2 2024. 4. 22. 11:58

@OneToOne 양방향 연관관계에서 조회 시 Lazy로딩이 먹히지 않았다. 

좀더 정확히는 연관관계의 주인이 아닌 쪽에서 엔티티 조회하니 Lazy로딩이 먹히지 않았다!!

이유와 해결책을 정리해두려 한다. 

 

양방향 연관관계 엔티티

 도서와 도서이미 1대1 관계

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

    ...

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

public class BookImageEntity{ //연관관계의 주인
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "img_no")
    private Long imgNo;

    ...

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name="book_no")
    private BookEntity book;
}

 


case1) 연관관계의 주인이 아닌 엔티티에서 조회

연관관계의 주인이 아닌 엔티티에서 FetchType.LAZY 걸려있음에도 지연로딩은 먹히지 않았다.

 

case2) 연관관계의 주인인 엔티티에서 조회

연관관계의 주인에서 하니 정상적으로 지연로딩이 작동하였다.

 

 

정리하면, 

@OneToOne 양방향 연관관계에선 연관관계의 주인인 엔티티에서만 조회 시, Lazy 동작한다.

 

 

왜 그럴까??

Lazy 로딩할 연관된 엔티티엔 프록시가 들어가야 하며, 프록시는 null을 프록시객체로 감쌀 수 없다

그렇기에 null을 할당할지, 프록시객체를 할당할지 결정해야 한다.

연관관계의 주인은 FK 컬럼을 가지고 있기에 FK컬람 값 유무로 연관된 엔티티에 대한 존재 유무를 판단할 수 있다.

FK가 존재하면 아 연관된 데이터 있다 프록시객체 할당!

FK 존재하지 않으면 연관된 데이터 없다 null 할당!

그러나 연관관계의 주인이 아닌 쪽에선 FK를 가지고 있지 않기 때문에 연관관계를 맺는 엔티티의 존재유무를 판단할 수 없다. 따라서, 필수적으로 쿼리를 돌려 null로 할당할지 프록시객체를 할당할지 정하게 되므로 Lazy로딩이 무시되어 Eager로 동작하게 된다.

 

@OneToMany는 문제 없나?

연관관계의 주인은 다쪽에 있다. 일쪽에선 다의 존재 유무를 알 수 없다.

그러나 일에선 다의 엔티티를 collection으로 지니고 있다. (ex. List<BookImageEntity> bookImageList) 

컬렉션의 경우는 null의 표현을 해당 컬렉션이 비어있다 라고 정의할 수 있기에 연관관계의 주인이 아닌 곳에서도 Lazy로딩이 가능하다.

 

@ManyToOne은 문제 없을까?

다쪽에서 외래키를 지니고 있기에 연관된 엔티티에 대한 존재유무를 판단할 수 있다.

문제 없다

 

해결책?

연관관계의 주인이 아닌 쪽에서의 조회 시 Lazy로딩 해결책으론 아래 두 가지를 생각하였다.

1. 연관관계의 주인 변경

2. fetchJoin -> 해당 방법으로 해결

 

추가로 아래 방법도 있다고 한다.

3. OneToOne을 OneToMany나 ManyToOne으로 분리

 

 

참고)

https://jeong-pro.tistory.com/249

 

JPA @OneToOne은 FetchType.LAZY가 안 먹힐 수 있다?

JPA에서 @OneToOne 연관관계일 때 지연 로딩이 안 될 수 있다? 이제는 JPA가 상당히 많이 쓰이고 있기도 하고 유명한 모 강의도 있어서 많은 사람들이 잘 알고 쓰고 있긴하다. 그러나 실제 경험해본

jeong-pro.tistory.com

https://hwannny.tistory.com/116

 

OneToOne 연관관계에서 Lazy 로딩 전략이 작동하지 않는 이슈

들어가며 연관관계 주인이 아닌 엔티티쪽에 OneToOne 연관관계 및 Lazy 로딩 전략을 설정한 뒤 연관관계 주인이 아닌 엔티티 조회시 당연하게 Lazy 로딩될줄 알았지만 쿼리로그를 확인해보니 Eager 로

hwannny.tistory.com

https://shirohoo.github.io/spring/spring-data-jpa/2021-05-31-one-to-one/

 

OneToOne에 대해서

JPA 사용 시 만악의 근원, @OneToOne에 대한 고찰

shirohoo.github.io