JPA를 쓸 때 연관관계로 인한 매핑문제로 무한참조(@XToOne)가 생길 수 있다. 이를 막기 위해 default인 EagerLoading을 LazyLoading으로 거는데, 여기서 문제가 생길 수 있다.
바로, hibernateLazyInitializer 초기화
문제이다.
Lazy는 기본적으로 실제 객체가 아닌 프록시 객체를 감싸져 있는 hibernateLazyInitializer
를 jackson 라이브러리가 json으로 어떻게 직렬화할지 몰라서 예외 발생하는 것이다.
Hibernate5Module을 스프링 빈으로 등록하면 해결(스프링 부트 사용중)된다.
이 Hibernate5Module이 강제로 지연 로딩을 가능하게 한다.
Hibernate5Module 등록, SpringApplication 클래스에 추가해주는든가, config 파일로 따로 만들자.
1) build.gradle
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-hibernate5'
2) java
// hibernateLazyInitializer 제거용 라이브러리
@Bean
Hibernate5Module hibernate5Module(){
return new Hibernate5Module();
}
이것을 등록하면 기본적으로 초기화된 프록시 객체만 노출, 초기화 되지 않은 프록시 객체는 노출 안하게 설정하는 것이다.
이는 Dto로 변환
해주면 바로 해결되었다!
결론,
JPA를 쓸 때는
Hibernate5Module 등록 (Lazy 초기화)
방식보단,
1) @JsonIgnore (양방향 연관관계면 무한 루프에 걸리지 않게 한 필드에 @JsonIgnore를 추가한다.)
2) @ToString(exclude = {""}) 처리
3) 그리고 DTO 변환을 하면서 위 2),3) 과정을 같이 처리해주면 된다!
참고)
앞에서 계속 강조했듯이 정말 간단한 애플리케이션이 아니면 엔티티를 API 응답으로 외부로 노출하는 것은 좋지 않다. 따라서 Hibernate5Module 를 사용하기 보다는 DTO로 변환해서 반환하는 것이 더 좋은 방법이다. -김영한