본문 바로가기
JPA

JPA - findById() & existById() & getById() 메서드 관련 내용 정리 (쿼리, 성능 등등)

by devLog by Ronnie's 2022. 3. 25.

들어가며


JPA를 통해 개발을 하다보면 해당 객체가 존재하는지 안하는지에 대한 여부를 판단해야 될 때가 있다. 그때 보통 findById 또는 existById를 통해서 존재 여부를 알 수 있다. 둘의 차이점에 따라서 맞는 상황에 해당되는 메서드를 쓰면 되지만 이때 '둘 중의 어느것이 성능이 좀 더 좋을까?' 라는 의문을 시작으로 해서 이 글을 정리하게 되었다. 이 과정에서 알게 된 getById에 대해서도 같이 정리한다.

 

findById & existById 차이점들

 

리턴값


findById existById 차이점은 메서드명에서도 있듯이 반환 타입이 다르다. findById Entity 반환하며 existById 존재 여부에 대한 Boolean 타입을 반환하게 된다. 그러니 존재 여부를 확인하고 존재하는 Entity 대하여 이후 로직이 진행되는 경우에 findById 사용하고 단순히 존재여부의 값만 필요할때는 existById 사용하면 된다. 

 

쿼리문


findById select 쿼리를 날린다.

existById count 쿼리를 날린다.

성능


count 쿼리를 사용하게 되면 결국 몇건인지를 확인하기 위해 전체를 확인해봐야하기 때문에 성능 차이가 밖에 없다. 아래에 표로 성능의 차이를 있다.

 

existsById 재정의하여 성능 올리는 방법


아래의 소스를 참고 하여 querydsl 사용하여 재정의한 코드입이다. 여기서 핵심은 fetchFirst이다. 쿼리를 확인해보면 limit 1 걸리는 것을 확인 있고 이것은 전체를 조회하지 않고 첫번째 결과만 확인하기 때문에 성능 향상을 가지고 온다

public Boolean exist(Long bookId) {
    Integer fetchOne = queryFactory
            .selectOne()
            .from(book)
            .where(book.id.eq(bookId))
            .fetchFirst(); // limit 1

    return fetchOne != null; // 1개가 있는지 없는지 판단 (없으면 null이라 null체크)
}

 

getById란?


자료를 정리하다가 알게 되어 같이 정리하게 되었다. getById() 메서드는 기존에 getOne() 메서드와 하는 일은 동일하여 Spring Data JPA 2.5.3 이후부터 getOne() 메서드가 Deprecated 되고 추가된 메서드이다. 

 

getById()메서드는 내부적으로 EntityManager.getReference() 메서드를 호출하므로 엔티티를 직접 반환하는것이 아닌 프록시 객체를 반환한다. 그렇기 때문에 실제로 사용하기 전까지는 DB에 접근하지 않으며 만약 나중에 프록시에서 DB에 접근할때 데이터가 없다면 EntityNotFoundException이 발생하게 된다.

 

특정 엔티티의 ID 값만 활용할 일이 있다면 DB 접근하지 않고 프록시만 가져와서 사용할 있다.

 

getById 쿼리와 findById 쿼리 차이


첫번째 쿼리가 getById 쿼리로써 findById와는 다르게 select하는 조회 쿼리가 없음을 확인할 수 있다. 위에서 말했듯이 실제로 사용하기전까지는 DB에 직접 접근하지 않기 때문이다. DB에 접근을 하게되고 쿼리문이 늘어나게 되면 당연히 성능상으로도 영향이 갈 수 있으므로 이 차이를 알고 적절하게 메서드를 사용하면 성능 향상을 기대해 볼 수 있다. 

추가적으로 getById() 지연 로딩으로 작동하기 때문에 ID 값을 제외한 나머지 필드에 접근했을때 쿼리가 발생하게 되는 것이다. (ex - member.getId() 쿼리 발생 x , member.getName() 쿼리 발생 o)

 

정리


  • 존재 여부를 확인할 때는 existBy
  • Id 값만 사용할 엔티티가 필요한 경우에는 getBy (의미적으로 get은 무엇인가를 얻는다는 의미이므로 null을 return하는 경우에는 사용하지 x)
  • Id 이외의 데이터도 사용하는 엔티티의 경우에는 findBy
    사용하면 된다 (find 마찬가지로 의미로 보면 무엇인가를 찾을 수도 있지만 찾을 수도 없다는 뜻이 내포되어 있으므로 선택적으로 제공하는 .)

댓글