ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 게시물 상세페이지 조회. LazyInitializationException
    졸업과제/BackEnd 2023. 2. 17. 16:48

    @GetMapping(value = "/post/detailPost")
    public void post_detailPost(Long PostId)
    {
        LOGGER.info("[post_detailPost] 게시물 세부사항 관련 로직 동작 PostId:{}",PostId);
    
        Post post = postService.findPost(PostId);
        RoomPicture photo = postService.findPhoto(PostId);
        List<Reply> replies = postService.findReply(PostId);
    
    
        DetailPostDto detailPostDto = new DetailPostDto(post.getTitle(), post.getContext(), post.getRoomPay_type(),
                                      photo.getFilename(), photo.getFilepath());
    
        for (Reply reply : replies) {
            detailPostDto.getReplies().add(reply);
        }
    
        System.out.println("****************************************************");
        System.out.println(detailPostDto.getTitle());
        System.out.println(detailPostDto.getPhoto_path());
    
        for (Reply reply : detailPostDto.getReplies()) {
            System.out.println(reply);
        }
    
    }

    현재 게시물의 Id를 받아와 Repository에서 PostId를 이용해 게시물, 사진, 댓글들을 DB에서 가져온 뒤
    DetailPostDto로 받아오고 댓글들은 반복문을 이용해 Dto객체에 세팅해 주었다.
    로직상 잘 돌아갈 거 같아 확신에 찬마음으로 돌려보았다.

    어림도 없지

    당연히 되지 않았다. Swagger에는 500 에러만 자꾸 떠서 어떤 값들이 출력이 되는지 일단 확인을 해보았다.
    게시물의 제목과 사진의 경로는 제대로 출력이 됐지만 댓글들을 조회해서 가져오면서 에러가 발생했다.
    LazyInitializationException이라는 오류가 발생했다. 이름도 어렵네.
    게시물과 댓글 간에 연관관계에서 fetch 설정이 무언가 잘못됐나 싶어 엔티티 간에 연관관계를 확인해 보았다.

    왼쪽이 댓글 엔티티, 오른쪽이 게시물 엔티티

    김영한 님 강의에서 LAZY로 연관관계를 세팅해 줘야 객체가 실제로 사용되는 시점에 연관관계를 맺게 되고
    무분별한 쿼리문을 남발하지 않도록 막아 성능을 향상할 수 있다고 해서 적어놓았다.
    혹시 몰라 게시물 엔티티에도 FetchType.LAZY를 적용해 보았지만 되지 않았다.

    https://cantcoding.tistory.com/78

    JPA/ could not initialize proxy - no Session

    1.문제점 JPA를 통한 개발을 하다보면 한번쯤 만날 수 밖에없는 에러이다. JPA를 사용하여 DB에 저장된 리소스를 불러와서 반환하는 경우, 혹은 사용할 때 발생했던 에러이다. 2.접근 JPA에 대한 이

    cantcoding.tistory.com

    이분의 블로그를 읽어본 결과
    게시물과 댓글 연관관계가 LAZY로 세팅돼있는대 Reply객체가 생성될 때 FetchType이 LAZY이기 때문에
    Reply안에 Post객체는 진짜 객체가 아닌 가짜 객체 Proxy객체로 채워지게 된다.
    이렇게 Proxy객체가 채워져 있는 상태에서 내가 Dto로 변환하려 하니 Reply안에 Post객체가 초기화되지 않은 상태여서
    에러가 발생했던 것이다.

    서비스단에서 트랜잭션이 일어나도록 설정을 해두었는데 JPA의 영속성 콘텍스트는 트랜잭션과 생명주기를 같이한다.
    따라서 컨트롤러 안 즉 트랜잭션 안에서 영속성을 관리하게 설정해야 하므로 Dto를 생성하는 코드를
    Service안에서 실행되도록 변경해 보았다.

    @Transactional
    public DetailPostDto detail_post(Post post, RoomPicture photo,List<Reply>replies)
    {
    
        logger.info("[detail_post] 게시물 세부사항 서비스 로직 동작 PostId:{}",post.getPostId());
        DetailPostDto detailPostDto = DetailPostDto.builder()
                .title(post.getTitle())
                .context(post.getContext())
                .photo_name(photo.getFilename())
                .photo_path(photo.getFilepath())
                .replies(replies)
                .build();
    
        return detailPostDto;
    }

    위에서 Controller에서 하던 Dto 생성을 Service에서 그대로 실행해서 Dto를 리턴할 수 있도록 해보았다.


    게시물의 id = 21번을 조회


    21번 게시물이 가지고 있는 댓글이 잘 출력되는 모습을 확인된다.


    FetchType.LAZY에 대해서 좀 더 자세히 알 수 있었던 계기였다. 강의에서는 코드를 그대로 따라 치면서
    그냥 이런 기능이구나 싶었는데 내가 작성한 코드에 적용하면서 오류를 고쳐나가다 보니 좀 더 이해가 잘되는 것
    같기는 하지만 아직은 아리송한 느낌이다.

    댓글

Designed by Tistory.