본문 바로가기
공부/프로그래밍

[JPA] @OneToMany 와 @ManyToOne 로 연결된 엔터티, JSON으로 파싱할때 StackOverflowError(@JsonIdentityInfo 로 해결)

by demonic_ 2018. 9. 4.
반응형

@OneToMany 와 @ManyToOne 로 연결되어있는 엔터티에서

데이터를 조회하여 스프링에서 RestController 를 이용해

Json 으로 리턴하는데 파싱에러가 난다.

로그를 보니 다음문구가 눈에 띈다.


nested exception is com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (StackOverflowError)


출력시 상호참조로 인해 stack overflow 오류가 발생하는 것이다.


이것의 해결점으로는 다음의 것을 참조한다.

Jackson 1.6+ 버전에서는

@JsonManagedReference와 @JsonBackReference 를 이용하고.

Jackson 2.0+ 에서는

@JsonIdentityInfo 를 사용하면 된다.


현재사용하고 있는 것은 Jackson 2.9.x 이므로 @JsonIdentityInfo 를 사용한다.


내 경우 Post.java 와 PostImg.java 라는 두개가 서로 연결되어 있는데, 다음과 같다.




Post.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Data
// 아래처럼 하지 않으면 post 와 핑퐁하면서 stackoverflow를 뱉는다.
@ToString(exclude = "post")
@Entity
@Table(name = "tb_post")
public class Post extends TimeStampEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
 
    @NotNull
    private long accountId;
 
    private String content;
 
    @OneToMany(mappedBy = "post")
    private Collection<PostImg> postImgs;
}
cs



PostImg.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@Data
@Entity
@Table(name="tb_post_img")
public class PostImg extends TimeStampEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
 
    // 파일크기
    private long size;
    // 파일 확장자
    private String suffix;
 
    // 저장경로
    private String orgPath;
    // 파일 본이름
    private String orgName;
 
    // 온라인에 쓸 파일 경로
    private String onlinePath;
    // 온라인에 쓸 파일 이름
    private String onlineName;
 
    @ManyToOne
    @JoinColumn(name="post_id")
    private Post post;
}
cs


둘중 한곳에 @JsonIdentityInfo 를 사용한다.

여기서는 Post.java 에 사용했다.


1
2
3
4
5
6
7
8
9
10
11
@Data
// 아래처럼 하지 않으면 post 와 핑퐁하면서 stackoverflow를 뱉는다.
@ToString(exclude = "post")
@Entity
@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class)
@Table(name = "tb_post")
public class Post extends TimeStampEntity {
    /**
    *
    */
}
cs





1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
/* 결과 */
{
    "content": [
        {
            "@id"1,
            "content""ccccccccccc",
            "postImgs": [
                {
                    "id"3,
                    "size"250658,
                    "suffix""jpg",
                    "onlineName""20180903174749_1",
                    "post"1
                }
            ]
        },
        {
            "@id"2,
            "content""bbbbbbbb",
            "postImgs": [
                {
                    "id"2,
                    "size"275827,
                    "suffix""jpg",
                    "onlineName""20180903174745_1",
                    "post"2
                }
            ]
        },
        {
            "@id"3,
            "content""aaaaa",
            "postImgs": [
                {
                    "id"1,
                    "size"626358,
                    "suffix""jpg",
                    "onlineName""20180903162410_1",
                    "post"3
                }
            ]
        }
    ],
    "pageable": {
        "sort": {
            "sorted"true,
            "unsorted"false
        },
        "offset"0,
        "pageSize"10,
        "pageNumber"0,
        "unpaged"false,
        "paged"true
    },
    "last"true,
    "totalPages"1,
    "totalElements"3,
    "number"0,
    "size"10,
    "sort": {
        "sorted"true,
        "unsorted"false
    },
    "first"true,
    "numberOfElements"3
}
cs



반응형

댓글