sumday11
410
2021-05-07 23:41:43
3
595

JPA Fetch Join 질문이 있습니다.!!!


안녕하세요 JPA 를 학습하며 casacade 와 Fetch 조인을 적용해보고 있었습니다.

먼저 저는 POST 와 Comment Entity 들을 이용해서 이들의 관계를 1:N 관계로 보고 스터디를 진행했습니다.

그리고 이제 POST 를 조회할 때 Comment 를 가져오는 것을 LAZY 속성을 준 뒤 Fetch Join 으로 한 방에 조회 할려고 했습니다. 

다름이 아니라 이 과정은 매우 성공적으로 잘 이행 되었습니다. 근데 문제는 여기서 발생했습니다. 보통 POST가 최초 posting 되면 당연히 comment는 null 일 것입니다. 이제 comment 저장을 위해 POST 를  findById() 를 통해서 찾아봤습니다. (POST 와 연관관계를 맺어주기 위해서 입니다.) 그런데 여기서는 LAZY 옵션 때문에 조회에 실패합니다. 

아 그래서 여기서도 FetchJoin 을 사용해서 가져와야 하고 Fetch Join을 사용하는 메서드를 실행했습니다. 그러니까 이번에는 조회되는 POST 가 Null 이 나옵니다. 


선배님들 이럴땐 어떻게 해결 해야할 까요 코드와 에러는 아래에 공개하겠습니다.

POST Entity



Comment Entity



테스트 코드

- findById 로 조회시 Lazy 옵션으로 인한 no Session 이슈



Fetch Join 을 이용한 조회


저장되어 있는 Comment 가 없기 때문에 조회되는 POST 가 없어서 NullPoint 이슈


마지막으로 Fetch Join 메서드




이상 입니다. 잘못된 개념이나 잘못된 코드 등등 잘못을 지적해주신다면 정말 감사하겠습니다.

0
  • 답변 3

  • java칩프라푸치노
    565
    2021-05-09 20:02:44 작성 2021-05-09 20:04:12 수정됨

    1. cascade 는 Post 쪽에서 걸어줘야하는데 주석보니까 궁금해서 저렇게 해놓으신거라 생각하겠습니다.


    2. Lazy 사용시 @Transactional 을 걸어줘야지 같은 트랜잭션으로 사용하여 프록시 no session 오류가 안뜹니다.


    3. 게시글을 불러올 때 댓글도 같이 한번에 fetch join 하는 과정에서 오류가 생겼다고 하셨습니다
    일단 게시글 한개를 불러오는 코드인거 같은데 뒤에 where 절로 id 값을 지정해서 찾아줘야지 그에 맞는 1개만 검색됩니다.
    그리고 NPE 가 뜬 이유는 당연히 게시물의 댓글이 없기 때문입니다. 따라서 left join fetch 로 조회해야지 댓글이 없어도 게시물이 조회가 가능합니다. (left join 과 일반 join 의 차이를 보시면 좋을 것 같습니다)  


     @Query("select p from Post p left join fetch p.comments where p.id = :id")
     Optional<Post> findPostUserFetchJoin(@Param("id") Long id);


  • sumday11
    410
    2021-05-11 11:20:41

    1. 네네 맞습니다. 궁금해서 그렇게 해보았고 그부분은 내용정리해서 이해를 했습니다. !!

    2. Test 를 진행할 때 @Transactional을 걸면 그 DB 반영이 안되더라구요!! 그래서 없이 진행했는데 같은 트랜잭션에 묶이지 않아 영속성 컨텍스트가 서로 다른거 같습니다.  하지만 똑같은 로직을 수행하는 서비스 Layer 단에서 테스트를 해본 결과 원하는 결과로 반영이 되어서 일단은 넘어갔습니다.


    3. 정말 좋은 팁 감사합니다!!! letf 조인 걸어봐야겠다는건 생각을 못했네요 ㅠㅠ 기존에는 Post 정보와 Comment 정보를 묶어서 내려보내는 Response 객체를 따로 썻기 때문에 post 따로 조회 하고 comment 를 따로 조회하는 방법만 사용하다보니 많이 미숙했던거 같습니다.


    좋은 지적 감사드리며 다시 한번 JOIN 을 학습하고 토이프로젝트에 반영해보겠습니다.  감사합니다.!!!

  • java칩프라푸치노
    565
    2021-05-11 11:30:16 작성 2021-05-11 11:32:50 수정됨

    @Transactional 을 걸때 @Test 어노테이션이 있다면 테스트 끝나고 롤백이 되기 때문에 DB에 남지 않게되는거라서
    @Rollback(value="false") 로 롤백안되게하고 DB에 남기게 할수도 있습니당ㅎㅎ

  • 로그인을 하시면 답변을 등록할 수 있습니다.