https://cheese10yun.github.io/jpa-jpql/
findById() 같은 경우는 영속성 컨텍스트를 먼저 찾고 영속성 컨텍스트에 해당 엔티티가 있으면 그 값을 바로 리턴합니다. 이를 1차 캐시라고 말합니다. 반면 JPQL은 영속성성 컨텍스트를 먼저 조회하지 않고 데이터베이스에 Query 하여 결과를 가져옵니다. 그리고 아래와 같은 흐름으로 영속성 컨텍스트를 저장을 시도합니다.

해당 코드는 단순합니다. Team은 N 개의 Member를 가질 수 있는 구조입니다. TeamRepository의 findFetchJoinBy 메서드는 단순히 팀 이름으로 Fetch Join 해서 해당 Team에 속한 모든 Member를 조회하는 JPQL 코드입니다. JPQL이 위에서 설명한 방식대로 동작하는지 아래 테스트 코드로 확인해보겠습니다.

해당 테스트는 실패합니다. teamA를 저장하고, member1, member2에 각각 teamA를 저장했습니다. 그리고 Fetch Join을 통해서 아래 SQL 문으로 데이터를 조회합니다.
올바르게 데이터가 저장되고, 조회 쿼리 또한 문제가 없는데 해당 테스트는 실패합니다.
주의! Team 객체를 저장할 때 member1, member2를 members 컬렉션에 저장하는 양방향 편의 메서드를 작성하면 해당 테스트는 실패하지 않습니다. JPQL의 동작 방식을 테스트해보기 위해서 작성했습니다.

영속성 컨텍스트와 데이터베이스 흐름을 자세히 살펴 보겠습니다.