2023.11.11 - [웹/Spring vue 웹 개발] - spring vue 댓글04
기존에 좀 많이 힘들었던 부분이 제법있었습니다.
먼저
hibernate.HibernateException: collection was evicted
이 문제가 발생했었는데요.
이 코드에서의 문제가 발생했었습니다.
@Override
public Optional<Notice> findWithCommentsById(Long id) {
//Criteria API 사용
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
//Notice 사용 이유는 댓글들을 불러오기때문
CriteriaQuery<Notice> cq = cb.createQuery(Notice.class);
/*select * from Notice LEFT JOIN Comments where id='id'*/
//from Notice
Root<Notice> notice = cq.from(Notice.class);
//left join
notice.fetch("comments", JoinType.LEFT);
cq.where(cb.equal(notice.get("id"), id));
//cq 쿼리 실행
TypedQuery<Notice> query = entityManager.createQuery(cq);
List<Notice> result = query.getResultList();
//삼항 연산자 result 비엇을시 empty() 존재지 resutl 리턴
return result.isEmpty() ? Optional.empty(): Optional.of(result.get(0));
}
TypedQuery<Notice> query = entityManager.createQuery(cq);
이 쿼리 실행문에서 발생했었는데 알고보니 제가 이전에
@JsonManagedReference
@OneToMany(mappedBy = "notice", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Set<Comment> comments = new HashSet<>();
해쉬셋으로 댓글을 가져왔었습니다.
이것저것 찾아보다가
https://stackoverflow.com/questions/65058723/hibernateexception-in-hashcode-or-in-equals
글을 빌리자면
- 컬렉션 로딩: Hibernate는 Company 엔티티의 garages와 같은 내부 컬렉션을 로딩해야 할 필요가 있습니다.
- 해시 코드 호출 시점: Company의 hashCode 메소드가 호출되는 시점에서 Hibernate는 아직 내부 컬렉션을 로딩하지 않았습니다. 이는 HashSet 내부에서 Hibernate의 내부 코드에 의해 발생합니다.
- 내부 혼란: 컬렉션이 로딩되어야 한다는 요청은 있었지만, 실제로 아직 로딩되지 않았기 때문에 Hibernate는 혼란스러워합니다.
이런 문제가 발생한다고 하여서
@JsonManagedReference
@OneToMany(mappedBy = "notice", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private List<Comment> comments = new ArrayList<>();
리스트로 바꿔서 해결했습니다.
ㅠㅠㅠㅠㅠ
그리고 나서 또 문제가 발생했습니다.
HttpMessageNotWritableException
위에처럼 messageNotWritabelException이 발생햇는데
다행히도 이문제는
@JsonManagedReference
@JsonBackReference
으로 해결할수 있었습니다.
무슨 문제이길래 이 어노테이션으로 해결한걸까요? 다음과 같습니다.
@JsonManagedReference와 @JsonBackReference
이 두 어노테이션은 순환 참조 문제를 해결하는 데 사용됩니다. 순환 참조는 JSON 직렬화 과정에서 무한 루프를 발생시킬 수 있으며, 이를 방지하기 위해 이 어노테이션이 필요합니다.
- @JsonManagedReference: '부모' 측에 사용되며, 직렬화 과정에서 이 어노테이션이 적용된 필드를 포함시킵니다.
- @JsonBackReference: '자식' 측에 사용되며, 직렬화 과정에서 이 어노테이션이 적용된 필드를 제외합니다. 이 어노테이션은 역직렬화 과정에서는 유효합니다.
결론적으론 JSON 직렬화 과정에서 무한 루프를 방지하기 위함인데 JSON 직렬화 과정에서 무한 루프는 왜 일어날까요?
JSON 직렬화 과정에서 무한 루프가 발생하는 주된 이유는 "순환 참조" 때문입니다. 순환 참조는 객체가 직접적이거나 간접적으로 자기 자신을 참조할 때 발생합니다. 예를 들어, 두 객체가 서로를 참조하거나, 객체가 자신을 포함하는 컬렉션을 참조하는 경우가 있습니다.
순환참조로 인한 무한루프가 발생할수 있다고해서 이를 방지하기 위함이라고 합니다. 음 쉽게 설명해서 양방향으로 서로 참조하는걸 단방향으로 바꿔주는 셈이죠 (제가 이해한건 이거인데 틀리면 지적부탁드립니다.)
그래서 댓글을 넣고 게시판을 확인해봤습니다. 아직 vue는 개발이 덜 되어서 postman으로 확인해봤습니다.
결과 화면 :
잘 나왔죠! 내일은 vue쪽도 만들어서 댓글도 보이도록 해보겠습니다. 시간이 나오려나 모르겠네요 ㅎㅎ ㅠ
'웹 > Spring vue 웹 개발' 카테고리의 다른 글
spring vue 어드민 리팩토링01 (0) | 2023.11.18 |
---|---|
spring vue 댓글 완료 (0) | 2023.11.12 |
spring vue 댓글04 (1) | 2023.11.11 |
spring vue 댓글03 (0) | 2023.11.05 |
spring vue 댓글 02 (0) | 2023.10.14 |