thumbnail

@OneToOne에서 주인이 아닐 때 Lazy가 안된다!

@OneToOne은 1 :1 일 관계이다.

ContentThumbnail가 있다고 하자.
그리고 ContentThumbnail는 1:1관계이다

1:1관계는 연관관계의 주인을,
두 엔티티중 어느 것에도 지정 할 수있지만,

외래키를 가지는 테이블이,
관계의 주인이 되는 것이 좀더 객체지향 관점일 것이다.

테이블을 구성하면, 다음과 같다.

<img src="https://static.podo-dev.com/blogs/images/2019/12/05/origin/a2df29d1-bbb1-4f77-b3f2-daccd565d2e0.png" alt="base64.png" style="width:436px;">

코드는 다음과 같을 것이다.

//나는 주인!
public class Content{
    @Id 
    @Column("content_id")
    private id;
    
    @OneToOne
    @JoinColumn("thumbnail_id")
    private Thumbnail thumbnail;
    
    private String contentTitle;    
}
public class Thumbnail{
    @Id 
    @Column("thumbnail_id")
    private id;
    
    @OneToOne(mappedby="thumbnail")
    private Content content;
    
    private String thumbnailName
}

<br>

Content가 관계의 주인 역할을 하고 있다.

그리고 앞서 말했듯이,
주인이 아닌 Thumbnail이 주인인 ContentLazy fetch할 수 없다.

<br>

이유는 프록시의 한계점에 있다.

Lazy 페치 전략에서
프록시는 참조엔티티를 감싸게되고
참조엔티티의 내부를 조회하게되면, Querry가 요청되어 엔티티의 정보를 가져온다.

    contentA.getThumbnail().getThumbnailName() // 쿼리 요청!

<br>

그럼, 컨텐츠에 참조되는 썸네일이 없다면 어떻게 될까?

    contentA.getThumbnail ()  // NULL
    contentA.getThumbnail () .getThumnailName() // NullPointException!!!

프록시null을 감쌀 수는 없다.
따라서, 애초에 프록시는 참조엔티티를 감싸지도 않으며
thumbnail값은 null을 반환하게된다.

<br>

이제 다음 테이블 데이터를 보자.

content 테이블의 다음 데이터가 있다고 가정하자.

content_id thumbnail_id content_name
1 1 난 1번 썸네일을 가지고있는 컨텐츠야!
2 null 난 썸네일이 없는 컨텐츠야 ㅠㅠ..

content 테이블을 가독함으로써,
contentthubmnail을 가지고 있는지, 가지고 있지 않은지를 알 수 있다.
번역하면, contentthumbnail을 가지고 있지 않다면, null값을 주입 할 수 있는 것이다.

//나는 주인!
public class Content{
    @Id 
    @Column("content_id")
    private id;
    
    @OneToOne
    @JoinColumn("thumbnail_id")
    private Thumbnail thumbnail;  // null 인지 아닌지 알수 있다!!!!
    
    private String contentTitle;    
}

<br>

반대로 thumbnail 테이블을 살펴보자

thumbnail_id thumbnail_name
1 누군가 날 가지고 잇겠지?
2 누군가 날 가지고 잇겠지?
3 누군가 날 가지고 잇겠지?

thubmnail 테이블을 가독함으로써,
어떤 content가 어떤 thumbnail을 참조 하는지 알 수 있는 방법이 없다.
번역하면, thumbnail이 어떤 content에 의해 참조되고 있는지를 알 수가 없어, null값을 주입 할 수 가 없는 것이다.

public class Thumbnail{
    @Id 
    @Column("thumbnail_id")
    private id;
    
    @OneToOne(mappedby="thumbnail")
    private Content content; // JPA say.. : null로해야되나.. 프록시로감싸야되나..ㅠ
    
    private String thumbnailName
}

즉, 프록시로 감싸서 주입해야할지, null을 주입해야할지 JPA는 결정을 할 수없다.

따라서 Lazy전략이더라도,
참조하는 content의 존재여부를 확인해야되기 때문에,

다음과 같은 쿼리를 요청할 수 밖에 없게된다.

## 1번 썸네일 가지고 있는 컨텐츠는 누구니..?
SELECT A.*
FROM content A
WHERE A.thumbnail_id = 1
## 아 1번 컨텐츠가 가지고있구나, 1번컨텐츠를 주입해야지!


## 2번 썸네일 가지고 있는 컨텐츠는 누구니..?
SELECT A.*
FROM content A
WHERE A.thumbnail_id = 2
## 아 아무도 안가지고있구나, NULL을 주입해야지!

## 3번 썸네일 가지고 있는 컨텐츠는 누구니..?
SELECT A.*
FROM content A
WHERE A.thumbnail_id = 3
## 아 아무도 안가지고있구나, NULL을 주입해야지!

<br>

결론

@OneToOne 관계에서,
주인이 아닌 엔티티는, 주인엔티티를 Lazy 전략으로 Fetch 할 수 없으며,
그 이유는 프록시의 한계점에 있다.

CommentCount 0
이전 댓글 보기
등록
TOP