JpaRepository에서 findBy<Entity> vs findBy<Entity>Id
JpaRepository의 쿼리 메서드의 작동방식을 정확히 이해해보자
2025. 04. 11
어떤 엔티티의 외래키에 해당하는 엔티티의 Id로 조회하려고 할 때, findBy<Entity> 와 findBy<Entity>Id 를 사용할 수 있다.
둘 다 외래키에 해당하는 엔티티의 정보로 조회를 실행하게 해주는 메서드인데, 넘겨주는 파라미터가 id값인지 엔티티 그 자체인지에 따라 달라진다.
나는 처음에 파라미터로 엔티티 전체를 넘겨주는 것보다는 id값만 넘겨주는 것이 더 효율적이라고 생각하여 findBy<Entity>Id 를 자주 사용하였는데, 알고보니 이 메서드에는 큰 문제가 있었다.
findBy<Entity>의 Hibernate Logselect rh1_0.id, ... from referral_history rh1_0 where rh1_0.referrer_id=?
findBy<Entity>Id의 Hibernate Logselect rh1_0.id, ... from referral_history rh1_0 left join account r1_0 on r1_0.id=rh1_0.referrer_id where r1_0.id=?
findBy<Entity> 를 사용하면 Hibernate가 자동으로 넘겨준 엔티티의 id값을 가져와 곧바로 외래키 필드(referrer_id) 자체를 조회해 결과를 가져오는 방식을 사용한다.
그러나 findBy<Entity>Id 를 사용하면 외래키 필드를 바로 조회하지 않고 JOIN을 수행한 다음 엔티티의 id값으로 조회하는 방식을 사용한다.
왜 쿼리 메서드 뒤에 Id를 붙이면 쓸데없는 JOIN 연산이 추가되는지 의문이다.
그 의문은 꽤 간단하게 해결될 수 있었는데, spring data jpa의 쿼리 메서드 기능이 “nested properties”, 즉 필드의 필드도 조회할 수 있도록 지원하기 때문이었다.
findBy<Entity>Id 는 언뜻보면 외래키 조회를 id만으로 수행하라는 메서드인 것 같지만, nested properties가 적용되어 “
따라서
만약 JOIN 연산 없이 외래키의 id값만으로 엔티티를 조회하고 싶다면 아래와 같이 Query를 직접 명시하는 방법을 사용해야 한다.
@Query("select m from Member m where m.team.id = :teamId")
List<Member> findByTeamId(final Long teamId);