무한참조 해결방법은?  @JsonIgnoreProperties

최초의 Board 객체 실행할때 getId, getTitle, getContent, getCount, getUser, getReply, getCreateDate 전부 호출이 되는데

이때 Reply 정보를 들고올때 Reply 안에서 board를 호출을 하지않으면 된다. 

 

 

어떻게?

여러가지 방법이 있으나 그 중의 첫번째는 @JsonIgnoreProperties

 

 

 

1. @JsonIgnoreProperties

[Board.js]

board객체에 있는 reply에 @JsonIgnoreProperties({"board"}) 붙이기 

@OneToMany(mappedBy = "board",fetch = FetchType.EAGER)
@JsonIgnoreProperties({"board"})
private List<Reply> replys;

이러면 Reply 객체 안에서 board를 호출(getter)을 하지않는다

 

 

 

 

[ReplyControllerTest]

@RestController
public class ReplyControllerTest {

	@Autowired
	private BoardRepository boardRepository;
	
	@GetMapping("/test/board/{id}")
	public Board getBord(@PathVariable int id) {
		return boardRepository.findById(id).get();
	}
	
}

리턴 board객체 

 

 

- 결과 

* url : http://localhost:8000/test/board/15

Reply 객체안에 있는 board를 호출 안한걸 알 수 있다.

 

Baord 오브젝트 실행시 차례로 get호출할 때 

user는 EAGER 전략이라서 바로 뽑아주고(보라색 네모 안)

replys도 똑같이 EAGER 전략이니까 바로 뽑아주는데 안에 board가 없다  = json으로 파싱하지 않는다. 

 

 

 

[board]

...
@ManyToOne(fetch = FetchType.EAGER)  // Many = Many,  User = One
@JoinColumn(name="userId")
private User user; // DB는 오브젝트를 저장할 수 없다. FK, 자바는 오브젝트를 저장할 수 있다. 

@OneToMany(mappedBy = "board", fetch = FetchType.EAGER, cascade = CascadeType.REMOVE)
@JsonIgnoreProperties({"board"})
@OrderBy("id desc")
private List<Reply> replys;

   

 

 

 

 

만약 user도 안뽑는다면?
@OneToMany(mappedBy = "board",fetch = FetchType.EAGER) 
@JsonIgnoreProperties({"board","user"})
private List<Reply> replys;

board 오브젝트에서 실행했을때 reply안에서 board, user 생략

 

 

-결과

Reply 객체가 board와 user를 호출 안했음 

 

 

 

 

 

2. 무한참조 방지하는 또 다른 방법
다이렉트로 reply 객체 호출하기

 

 

 

위처럼 @JsonIgnoreProperties 을 썼을때 board 객체를 호출하면 reply객체안의 board가 무시되지만

reply 객체를 다이렉트로 호출하면 board 무시를 하지 않는다!!

 

 

 

 

[ReplyControllerTest]

@RestController
public class ReplyControllerTest {

	@Autowired
	private ReplyRepository replyRepository;
	
	@GetMapping("/test/reply")
	public List<Reply> getReply() {
		return replyRepository.findAll().get();
	}
	
}

리턴 reply객체

 

 

 

- 결과 

Reply 객체를 호출했을때 board,user 가 호출이 된다.

reply를 다이렉트로 주었을때 board,user 호출 된다

 

 

 

그러나 board안의 reply에는 board,user가 없다.

이렇게만 해도 무한참조 방지가 된다. 

 

 

Reply 객체를 호출하면 user객체, board 객체를 들고온다

user 객체는 연관관계가 없어 그대로 들고오고

board 객체는 reply 객체를 돌고오나 reply객체안의 board,user 는 가져오지 않는다. 

이렇게 해도 무한참조를 방지 가능하다.

 

 

 

그리고 boardService에서 글상세보기를 했을때 getter 호출이 안된다

 

[boardService]

@Transactional(readOnly = true) 
public Board 글상세보기(int id){
    return boardRepository.findById(id)
            .orElseThrow(()->{
                return new IllegalArgumentException("글 상세보기 실패 : 아이디를 찾을 수 없습니다.");
            });
}

[BoardController]

@GetMapping("/board/{id}")
public String findById(@PathVariable int id, Model model) {
    model.addAttribute("board",boardService.글상세보기(id));
    return "board/detail";
}

 

 

[detail.jsp]

<div class="card-header">댓글 리스트</div>
<ul id="reply--box" class="list-group">
    <c:forEach var="reply" items="${board.replys}">
        <li id="reply--1" class="list-group-item d-flex justify-content-between">
            <div>${reply.content}</div>
            <div class="d-flex">
                <div class="font-italic">작성자 : ${reply.user.username} &nbsp;</div>
                <button class="badge">삭제</button>
                <div>${reply.board}</div>
            </div>
        </li>
    </c:forEach>
</ul>

 

${reply.board}

를 호출한다면?

reply에 안에서 board를 호출하고 board에 들어가면 replys호출하고... StackOverflowError 에러가 뜬다.

> 무한참조 때문

 

 

반응형
LIST

+ Recent posts