@OneToOne에서 주인이 아닐 때, Lazy가 안된다!
@OneToOne
에서 주인이 아닐 때 Lazy가 안된다!
@OneToOne
은 1 :1 일 관계이다.
Content
와 Thumbnail
가 있다고 하자.
그리고 Content
와 Thumbnail
는 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
이 주인인 Content
를 Lazy 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
테이블을 가독함으로써,
content
가 thubmnail
을 가지고 있는지, 가지고 있지 않은지를 알 수 있다.
번역하면, content
가 thumbnail
을 가지고 있지 않다면, 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 할 수 없으며,
그 이유는 프록시의 한계점에 있다.