getReference() EntityNotFoundException 오류

선종우·2023년 6월 12일
0

오답노트

목록 보기
3/5

1. 오류

  • 쿼리 최적화를 진행하는 과정에서 getReference()를 이용하면 불필요한 쿼리 발생을 줄일 수 있지 않을까 싶어서 아래와 같은 코드를 작성해보았다.
		Optional<Article> article = articleRepository.getReferenceById(commentDto.getArticleId());
        Optional<Member> member = memberRepository.getReferenceById(11L);
        
        if(article.isEmpty() || member.isEmpty()){
            System.out.println("log");
            throw new ResourceCreationException(ErrorCode.COMMENT_CREATE_ERROR, article.isEmpty() ? "article" : "member");
        }
  • getReference()를 호출하면 DB에서 id값만을 select해올 것이라고 생각해서 작성하였으나, 이후 로직에서 entityNotFoundException이 발생했다.

2. 오류해결

  • 프록시의 작동원리에 대해 잘못이해하여 오류가 발생했다.
  • getReference()는 DB로의 조회 쿼리를 지연시키고 프록시를 생성하는 메소드이다. 즉 getReference()호출 시점에서는 DB에 데이터가 있는지 없는지 알 수 없다. 단순히 전달한 ID값을 가진 프록시객체를 생성할 뿐이다.
  • 프록시 객체를 생성하기 때문에 Optional.ofNullable(em.getReference(~~)) 이런 식으로 코드를 작성하면, isPresent()가 true가 된다.(optional의 value에 프록시 객체가 담기기 때문)
  • 그렇기 때문에 isEmpty()에서 적절한 에러처리가 일어나지 않고 이후 프록시 객체 초기화 과정에서 entityNotException이 발생한 것이다.
    • 프록시 초기화 과정에서 예외가 발생하기 때문에 getReference()구문을 try {} catch{}로 감싸더라도 예외가 전파돼 버린다.
  • getReference()를 사용하더라도 결국 엔티티의 존재유무를 체크하려면 sql문이 실행되어야 하기 때문에 getReference()를 사용하는 이점이 없다고 판단하여, find()를 그냥 사용하기로 하였다.

0개의 댓글