[JPA, SpringBoot] KnockKnock 개발일지 - 1228 (Feat. Cascade 함부로 쓰지 말아야 하는 이유)

Hyebin Lee·2021년 12월 28일
0

knockknock 개발일지

목록 보기
5/29
post-thumbnail

✔오늘의 목표

  1. 기존에 있었던 PostHashTag insert 오류 해결하기
  2. 글 삭제시 관련 PostHashTag 같이 삭제, HashTag는 해당 글이 유일하게 갖고 있었던 HashTag인지 확인하고 맞으면 삭제하기 Service 만들기
  3. 해당 기능들 Test 코드 작성하고 검증하기
  4. 포스트와 해시태그 CRUD 핵심 기능 구현

오늘의 이슈

  1. 플러시와 트랜젝션 커밋 공부
  2. Referential integrity constraint violation 오류 해결하기
    (복잡하게 얽혀있는 엔티티 관계에서 올바른 시점에 commit 하기)
    2-1. 일대다 단방향 매핑 지양하기
  3. 💥원인 모를 QueryDSL 오류... QueryException could not resolve property : column of entity

1. 플러시와 트랜젝션 커밋 공부

플러시와 트랜젝션이 무엇인지 대략적인 개념은 알고 있었지만
개념을 구체적으로 이해하고 있는 것이 아니라 추상적으로 이해하고 있어서 이렇게 코드 상으로 응용할 때 문제가 되었다.
이번 기회에 제대로 정리해보고자 해서 플러시와 트랜젝션이 무엇인지, 어떻게 작동하는지, 어느 시점에서 commit되어 쿼리문이 DB에 반영되는지 다음 글에 정리하여 작성하였다. 🙌

자세한 내용은 링크를 참고하자!

2. Referential integrity constraint violation 오류 해결하기

자 결론부터 말하자면
cascade 옵션은 주인이 하나일때만 사용 가능하다!
cascade로 특정 Entity에 종속된 Entity를 다른 Entity에서 참조하면 안된다!
단, cascade로 종속된 Entity는 다른 Entity를 참조 가능하다.

이걸 꼼꼼하게 공부하지 않아서,, cascade로 Post에 종속되어있는 PostHashTag를 HashTag 의 FK로 쓰려고 했던 것,,
그래서 난 오류였다.
내가 이걸 찾아서 거의 일주일을 헤맸는데 따흑 😭😭

따라서 이 문제를 해결하려면,

  1. cascade 옵션을 없애기
  2. HashTag가 PostHashTag를 참조하는 것이 아닌 PostHashTag가 HashTag를 단방향으로 참조하도록 한다.

두 가지 방법이 있다.

2-1. 일대다 단방향 매핑 지양하기

그런데 찾다보니 일대다(1:N) 단방향 매핑은 DB 상에서 연관관계의 주인이 fk인 "다" 쪽에 있게 되어서 update 쿼리가 헷갈리게 나간다는 단점이 있었다.

이 부분도 따로 정리하면 좋을 것 같아서 여기에 정리하였다.

아무튼 현실적으로 생각해보면 HashTag가 PostHashTag를 어떻게든 참조해야 하기때문에 (HashTag 단위로 해당 해시태그가 있는 post들 조회 기능 구현 등)
결론적으로 HashTag와 PostHashTag의 양방향 연관관계 매핑이 필요하다.

그 말은 즉슨, cascade 옵션을 필히 없애줘야 한다는 소리..
그래서 cascade 옵션을 없애기로 했다.

3. 💥QueryException could not resolve property : column of entity

이 오류 때문에 또 몇 시간을 뻘짓했다.
처음에는 내가 아직 sql 문법이 완벽하지 않아서 실수하는 건가 싶었는데 그건 또 아닌게
오히려 쌩 sql 문법으로 조회해보면 다 나오는게 querydsl 에서 안나오는 것이다.

이 오류의 뜻은 특정 패키지 경로에 있는 entity 컬럼 찾을 수 없다는 오류 이다.
문제가 생긴 부분은 posthashtag 테이블의 hashtag 컬럼을 찾을 수 없다는 것이였다.
그러나 DB 상으로도 hashtag 컬럼은 명확히 있고ㅠ sql 문으로 조회도 잘되고,, 엔티티에 멤버변수로 hashtag가 얌전히 잘 있건만 대체 왜이러는 건지 모르겠다.

더 웃긴건 이걸 createQuery로 똑같이 작성하니까 해결되어버림....ㅎㅎㅎ
대체 뭐가 문제였을까.. 아직도 원인 파악중이다.

 public List<PostHashTag> findPostHashTags(Long id){
       try{
           return em.createQuery("select p from PostHashTag p " +
                   "where p.hashtag.id = :hashtag",PostHashTag.class)
                   .setParameter("hashtag",id)
                   .getResultList();
          /* List<PostHashTag> posthashtags = queryFactory.selectFrom(postHashTag)
               .where(postHashTag.hashTag.id.eq(id))
               .fetch();
           return posthashtags;*/}
       catch(NoResultException nre){return null;}
   }

문제의 코드..
주석처리된 부분은 오류나고 지금 em.createQuery로는 잘됨
둘다 같은 뜻인데 대체 whyrano

한 가지 가설로는 내가 오늘 PostHashTag - HashTag 관계를 양방향 연관관계로 바꿔주면서
posthashtag에 hashtag 컬럼을 새로 추가했는데
기존의 Qclass 파일에 그 부분이 반영이 안되어서 hashtag 컬럼을 못찾는건가 싶기도 하다.
그런데 그렇다고 하기엔 PostHashTag QClass 파일에 너무나 버젓이 hashtag가 있음..ㅎㅎㅎㅎㅎ
일단 갈길이 바쁘니 원인 파악은 천천히 해야겠다.. 해결 되었으니 일단은 된걸로

0개의 댓글