개발하는 자몽

[JPA Error] FetchType.LAZY로 인한 오류 : Type definition error 본문

Java/Spring

[JPA Error] FetchType.LAZY로 인한 오류 : Type definition error

jaamong 2023. 2. 13. 10:55

오류 질문을 받았는데, 내가 지난번에 겪었던 에러와 유사한 것 같아서 정리해두려고 한다.

 

상황

API에 요청을 하고 해당 정보를 DB에 담는 것까지는 에러 없이 진행이 된다. 하지만 저장한 정보를 조회하면 아래와 같은 에러가 콘솔창에 나타난다. Postman에서는 500 에러라고 알려준다. (오류 전문이 아닌 중요한 부분만 가져왔다)

2023-02-13T09:52:21.966+09:00 ERROR 71150 --- [nio-8080-exec-3] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor]] with root cause

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: com.xxx.xxx.domain.dto.Response["xxx"]->com.xxx.xxx.domain.dto.record.XxxResponse["xxx"]->java.util.ArrayList[0]->com.xxx.x.domain.entity.xxx["xxx"]->com.xxx.xxx.domain.entity.Xxx["xxx"]->com.xxx.xxx.domain.entity.Xxx["xxx"]->com.xxx.xxx.domain.entity.Group$HibernateProxy$iFEdWF88["hibernateLazyInitializer"])

아래줄(hibernateLazyInitializer)에서 오류(InvalidDefinitionException)가 발생했다고 알려준다. 잘 보면, 에러와 함께 아래처럼 해서 오류를 피하라고 알려준다.

to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS

 

 

에러가 난 코드를 비슷하게 작성해봤다.

@Entity
...
class Xxx {

    @Id @generatedvalue(strategy = generationtype.identity)
    private Long id;
    
    
    @ManyToOne(Fetch = fetchType.LAZY)
    private type fieldA;
    
    ...
}

엔티티의 ManyToOne + 지연 로딩 필드에서 발생했다. (fetchType은 DB에서 엔티티 정보를 조회할 때 연관되어 있는 다른 엔티티의 정보를 어느 시점에 가져올지 정하는 옵션이다)

 

클라이언트로부터 받은 데이터를 저장하고, 성공적으로 저장이 되면 해당 객체를 반환하도록 했는데 에러가 발생한 것이다. 저장에 성공한 Xxx 객체에 대한 정보를 JSON 타입으로 변환하는 과정에서 Xxx 객체와 매핑되어 있는 fieldA를 serialize(직렬화)할 때 지연 로딩으로 인해 실제 fieldA 객체가 아닌 프록시 객체를 serialize하려고 했기 때문에 이러한 에러가 발행했다. (지연 로딩으로 설정 시 데이터를 요청하면 연관 엔티티는 hibernate가 프록시 객체를 반환한다)

 

해결

해당 필드에 Jackson 애노테이션인 @JsonIgnore를 적용했다.

오류 본문에 나와있는 hibernateLazyInitializer는 엔티티를 지연 로딩하기 위해 사용된다. DB에 엔티티를 저장할 때 JPA 엔티티는 엔티티의 모든 필드와 hibernateLazyInitializer 필드를 serialize 한다. 이러한 필드를 무시하지 않으면 해당 필드들은 JSON 형태로 serialize 된다. 이렇게 불필요한 serialization을 피하려면 @JsonIgnore를 사용해야 한다. 이는 serialize된 JSON이 hibernateLazyInitializer 필드를 갖지 않으며, 객체에 가지고 있다면 무시하라는 의미이다.

 

따라서 아래처럼 코드를 작성하면 Xxx를 JSON 형태로 변환할 때 fieldA를 제외한 정보만 serialize 된다.

@Entity
...
class Xxx {

    @Id @generatedvalue(strategy = generationtype.identity)
    private Long id;
    
    
    @ManyToOne(Fetch = fetchType.LAZY)
    @JsonIgnore
    private relatedEntityType fieldA;
    
    ...
}

 

 

 

 

 

참고

 

What does @JsonIgnoreProperties({"hibernateLazyInitializer", "handler"}) do?

What does this following piece of code do in Java Sprint Boot? @JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})

stackoverflow.com

 

[JPA] FetchType.Lazy로 인한 JSON 오류 (InvalidDefinitionException: No serializer found for class)

발단 Front에서 엔티티를 저장하는 과정에서 처음 데이터를 저장하는 순간에는 올바르게 작동하지만 수정(edit)하고 저장할 때에는 에러(HttpStatus 500)를 리턴한다는 문제가 발생했다. (다만 DB상으

ahndding.tistory.com

Comments