본문 바로가기

Spring boot/스프링 데이터 JPA

외래키 참조 쿼리 비교(findByMemberId, findByMember)

프로젝트를 진행할 때 쿼리를 하나하나 살펴보는 편인데... 문뜩 의문점 발견했습니당 

member entity가 team을 가진다고 하면,

findByTeamId와 findByTeam 쿼리가 다르게 나가는 것을 알았습니다..!

teamId로 찾을땐 left outer join을 하길래 무슨 차이일지, 실무에서는 어떤 것을 더 많이 사용하는지 궁금했습니다. 

 

이 차이를 언급하며 내 인프런 교수님 영한님께 여쭤봤을땐 

이 대답을 들었고 저 강의를 참고하면 

// findByTeam
Team team = em.find(Team.class, 1L);

String qlString = "select m from Member m where m.team = :team";
List resultList = em.createQuery(qlString)
		    .setParameter("team", team)
                    .getResultList();
// findByTeamId
Team team = em.find(Team.class, 1L);

String qlString = "select m from Member m where m.team.id = :teamId";
List resultList = em.createQuery(qlString)
                    .setParameter("teamId", team.getId())
                    .getResultList();

둘 다 select m.* from Member m where m.team_id = ? 쿼리가 실행될거라고 하셨습니다!

 


 

그래서 남기는 블로그.. !!! 내가 해보잣 하하

 

[Spring boot + Spring data JPA + MySQL]


@Entity
public class Event{
	@Id
	@GeneratedValue(generator = "uuid2")
	@GenericGenerator(name = "uuid2", strategy = "uuid2")
	@Column(columnDefinition = "BINARY(16)")
	private UUID id;

	@Column(nullable = false)
	private String name;

	@ManyToOne(fetch = FetchType.LAZY, optional = true, cascade = CascadeType.ALL)
	@JoinColumn(name = "member_id")
	private Member member;

	// builder 생략
}
@Entity
public class Member {

	@Id
	@GeneratedValue(generator = "uuid2")
	@GenericGenerator(name = "uuid2", strategy = "uuid2")
	@Column(columnDefinition = "BINARY(16)")
	private UUID id;

	@Column(nullable = false)
	private String name;
    
	// builder 생략
}

 

딱 아래와 같은 상황입니다!

 


JPA Repository는 여기!

public interface EventJpaRepository extends JpaRepository<Event, UUID> {

	Event findByMemberId(UUID memberId);

	Event findByMember(Member member);
}

 


[Test code]

public class EventTest {

	@Autowired
	EventJpaRepository eventJpaRepository;

	@Autowired
	MemberJpaRepository memberJpaRepository;

	@Test
	public void findTest(){

		Member member = memberJpaRepository.save(
				Member.builder()
				.name("배지현")
				.build()
		);


		Event event = eventJpaRepository.save(
				Event.builder()
						.name("신나는 여름 이벤트")
						.member(member)
						.build()

		);

		Event findByOrganizer = eventJpaRepository.findByMember(member);	// 1번
		Event findByOrganizerId = eventJpaRepository.findByMemberId(member.getId());  // 2번
	}
}

 

결과

둘의 차이는 맨 끝에

1번 쿼리는 where 

2번 쿼리는 left outer join을 하네욥

 

비교

1번(findByMember)은 member를 찾는 findMember 쿼리 1개 + findByMember로 event를 찾는 쿼리 1개를 날려줘야합니다. 대신 가독성이 좋고 1차캐시에 member가 이미 있다면 뒷 쿼리 하나만 날리면 되네요!

 

2번(findByMemberId)은 1번이 날려야하는 쿼리 2개를 1개로 퉁쳐줘서 DB 접근을 줄여준다는 장점이 있지만 가독성이 나쁩니다. 

 

사실 아직도 실무에서는 뭘 쓰는지 잘 모르겠네요...

아는 분 댓글 부탁드려요 ..!!

속도 개선을 위해.. 저는 그때그때 알맞는 걸로 적용하겠습니다.. 오늘의 호기심 탐구 이상 끝!