[JPA] ErrorReport : 지연로딩으로 인한 JSON 오류

Hyebin Lee·2022년 4월 8일
0

JPA TIL

목록 보기
7/7

오류

POSTMAN으로 post 매핑 테스트 중 다음과 같은 오류메세지가 리턴되었다.
하지만 DB 상에는 post 매핑 기능이 잘 수행되어 데이터가 잘 들어가있었다.. 😅

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)

원인

Rest API 통신에서 response가 리턴되는 과정은 아래와 같다.
1. 일단 DB 상에 데이터가 저장된다. (POST 매핑의 경우)
2. DB에 저장된 객체를 JSON 형태로 리턴한다

그런데 이 과정은 지연로딩 때문에 에러가 발생할 수 있다.
저장에 성공한 ScrapArticle 객체 정보를 JSON으로 변환하는 과정에서 ScrapArticle과 연관이 되어있는 scrap member 객체와 article 객체를 serialize 해주려는 순간,
FetchType이 Lazy라 해당 필드에는 Proxy 객체만이 담겨있을 뿐 각 필드 객체의 실체가 없기 때문이다.

왜 프록시 객체가 담겨져 있는지는 지연로딩과 관련된 내용을 참고하면 쉽게 알 수 있다.

해결

@JsonIgnore

저장 성공한 객체 확인을 위한 JSON response에서 문제가 되는 필드를 제외하고 보내도록 설정하는 어노테이션이다.

문제가 되는 ScrapArticle Entity의 코드는 다음과 같은데,

package ewha.nlsushi.newsum.domain;

import com.fasterxml.jackson.annotation.JsonManagedReference;
import lombok.Getter;
import lombok.NoArgsConstructor;

import javax.persistence.*;

@Entity
@NoArgsConstructor
@Table(name="scrap_article")
@Getter
public class ScrapArticle {

    @Id @GeneratedValue(strategy =  GenerationType.IDENTITY)
    @Column(name="scrap_pk")
    Long id;

    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name = "member_pk")
    @JsonManagedReference
    private Member scrap_member;

    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name = "id")
    private Article scrap_article;

    public Member getScrap_member() {
        return scrap_member;
    }

    public Article getScrap_article() {
        return scrap_article;
    }

    public ScrapArticle(Member scrap_member, Article scrap_article) {
        this.scrap_member = scrap_member;
        this.scrap_article = scrap_article;
        scrap_article.scrap_articles.add(this);
        scrap_member.scrap_articles.add(this);
    }
}

지연로딩으로 가져와 문제가 되고 있는 scrap_member 와 scrap_article 객체가 프록시객체이니
response로 가져올 때 해당 객체들은 제외하고 json화해서 가져오라고 지정하는 것이다.

@ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name = "member_pk")
    @JsonManagedReference
    @JsonIgnore
    private Member scrap_member;

    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name = "id")
    @JsonManagedReference
    @JsonIgnore
    private Article scrap_article;

다음과 같이 추가해주었다.

0개의 댓글