상황 : 양방향 1:1 관계를 설정하고, fetch 타입을 Lazy로 설정함에 있어도 eager와 같이 동작하는 것을 보았다.
연관 관계 주인 테이블을 A, 아닌 테이블을 B라고 설정하겠다.
문제 : B테이블을 조회할 때 eager로 동작하여 A 테이블도 조회하게 된다.
원인
- 지연로딩으로 설정하면 엔티티를 조회할 때 해당 엔티티에서 지연로딩으로 설정된 객체는 프록시로 감싸서 동작하게 되는데, 프록시는 null을 감쌀 수 없기 때문에 발생한 문제이다. ( A에서 B테이블이 null일 때는 로딩자체를 하지 않는다. )
- A와 달리 B입장에서는 A에 대한 참조키 같은 것이 없기 때문에 null인지 아닌지 알 수 없고, 따라서 eager로 동작하여 null인지 확인하는 것이다.
해결
- 본인의 경우 유저와 이미지 테이블 간에서 발생한 문제였는데, 굳이 이미지 테이블을 만들어서 저장해야 할 필요가 있을까해서 이미지 테이블을 지우고 filename만 저장하는 방식으로 설정했다. 즉, 연관관계를 아예 없앴다.
- B테이블에서 조회가 많이 일어나면 외래키를 B로 옮겨 A테이블이 되도록한다. or 1:N 양방향 관계로의 전환도 고려해볼 수 있다. or OneToOne 단방향도 가능하다.
- 양쪽 테이블에서 모두 조회가 많이 일어나면 fetch join이나 batch size를 설정할 수 있다.
궁금점 : @OneToMany 관계에서는 왜 lazy로만 동작하는가?
이유 : @OneToOne과 달리 리스트를 인자로 받기 때문에, null이 아닌 빈 리스트를 프록시가 감싸게 되기 때문이다.
'Spring Boot > JPA' 카테고리의 다른 글
사용자 정의 리포지토리 (0) | 2024.08.29 |
---|---|
벌크 연산 주의 사항 (0) | 2024.08.24 |
Spring Boot existsBy (0) | 2024.07.29 |
Spring Boot Batch Insert - 문제점 보충 설명 (0) | 2024.07.27 |
Spring Boot jpa 컬럼에 기본값 주기 (0) | 2024.07.19 |