JPA Proxy 객체를 통한 쿼리 횟수 줄이기
상황
Friend
테이블에 친구 요청 row를 추가하려고 한다.- 요청 송신자와 수신자가 각각
Member
객체로 등록되어 있음. (Friend
엔티티에) - 그럼 매 번 쿼리를 세 번씩 날려야 하나?
- 송신자 가져오기
- 수신자 가져오기
- 친구 요청 저장하기
public void addFriend(Long requesterId, Long addresseeId) {
//여기서 한 번
Member requester = memberRepository.findById(requesterId)
.orElseThrow(() -> new RuntimeException("Requester not found"));
//여기서 두 번
Member addressee = memberRepository.findById(addresseeId)
.orElseThrow(() -> new RuntimeException("Addressee not found"));
//여기서 세 번
Friend friend = new Friend();
friend.setRequester(requester);
friend.setAddressee(addressee);
friendRepository.save(friend);
}
해결
- JPA의
EntityManager
에는getReference()
라는 함수가 존재. find()
를 사용하면 각 객체를 불러오기 위해 쿼리를 날려야 하지만getReference()
를 사용하면 각 객체 대신 임시 프록시 객체 생성- 고로 쿼리를 날리지 않고 Proxy객체만으로 데이터를 삽입할 수 있다!
public void addFriend(Long requesterId, Long addresseeId) {
//쿼리를 날리지 않고 프록시 객체 생성
Member requester = entityManager.getReference(Member.class, requesterId);
Member addressee = entityManager.getReference(Member.class, addresseeId);
//쿼리는 여기서 한 번만!
Friend friend = new Friend();
friend.setRequester(requester);
friend.setAddressee(addressee);
friendRepository.save(friend);
}
고려할 점
- 해당하는 id에 맞는 객체가 존재하는지 검증이 이뤄지지 않음.
- addressee에 대한 검증만 해 준다면 쿼리를 세 번에서 두 번으로 줄일 수 있다! (requester는 토큰 정보로 사용하기 때문에 괜찮을 것이라는 판단… 물론 중간에 탈퇴하는 경우도 생각해야 할 것 같긴 함.)
Leave a comment