2023.11.11 - [웹/Spring vue 웹 개발] - spring vue 댓글04

 

spring vue 댓글04

2023.11.05 - [웹/Spring vue 웹 개발] - spring vue 댓글03 spring vue 댓글03 2023.10.14 - [웹/Spring vue 웹 개발] - spring vue 댓글 02 spring vue 댓글 02이전에 이어서 service랑 controller를 작성을 전부 완료하였고 테스트

kwaksh2319.tistory.com

기존에 좀 많이 힘들었던 부분이 제법있었습니다. 

먼저 

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

 

HibernateException in hashCode or in equals

I am using spring and hibernate. When fetching without having implemented equals and hashCode, everyting works fine. When I add the two methods and execute the query a Lazyinitializationexception is

stackoverflow.com

글을 빌리자면 

  • 컬렉션 로딩: 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

+ Recent posts