문제의 에러
httpMessageConversionException: Type definition error: [simple type, class org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class org.hibernate.proxy.pojo.
bytebuddy.ByteBuddyInterceptor and no properties discovered to create BeanSerializer
...
Lazy Loading은 DB에서 값을 가지고 오지않고 하이버네이트에서 프록시객체(bytebuddy)를 생성해서 넣어놓는다.
해당 객체의 값에 접근할때 실제 db에 쿼리를 날려 해당 객체를 가져온다.
이같은 에러는 jackson 라이브러리가 해당 객체를 serialize하려 할때 해당객체가 실제 객체가 아니고 프록시 객체이기 때문에 실패한 것이다.
해결 방법
- eager 사용
- 이 방법은 조회할때 프록시 객체가 아닌 실제 객체를 바로 가져오도록 하는 것인데 성능상으로 이점을 얻기 어렵다..
연관관계가 있는 모든 애들을 전부조회하기 때문에 성능에 좋지않고 N+1은 덤으로 발생할 수 있다.
단건 쿼리 같은 경우엔 사용할 수 있으나 기본적으로 lazy를 추천한다.
한번에 가져와야 한다면 fetch join을 사용하자.
- 이 방법은 조회할때 프록시 객체가 아닌 실제 객체를 바로 가져오도록 하는 것인데 성능상으로 이점을 얻기 어렵다..
- Hibernate5Module 모듈을 빈으로 등록하여 사용
- 엔티티를 외부에 노출할 일 없어야 하기 때문에 추천하지 않는다.
또 기본적으로 Hibernate5Module은 lazy를 무시한다.
- 엔티티를 외부에 노출할 일 없어야 하기 때문에 추천하지 않는다.
- 양방향 연관관계가 걸린 곳은 @JsonIgnore 처리 해야한다.
- 안그러면 jackson 라이브러리가 연관관계가 있는 양쪽을 계속 호출하며 무한루프에 빠진다.
- 강제적으로 초기화 해준다.
- 실제 값에 접근하여 사용함으로써 프록시객체가 아닌 실제 객체로 초기화 해준다.
DTO를 사용하는 것이 좋다.
- 실제 값에 접근하여 사용함으로써 프록시객체가 아닌 실제 객체로 초기화 해준다.