[인프런 워밍업 0기] JPA findById() vs getReferenceById()

[인프런 워밍업 0기] JPA findById() vs getReferenceById()

다음은 JPA에서 연관관계 매핑이 되어있는 객체를 save하는 상황이다.

    @Transactional
    public void recordArrivalTime(Long memberId, LocalDate attendanceDate, LocalTime startTime) {
        Member member = memberRepository.findById(memberId);
        workTimeRecordService.recordArrivalTime(member, attendanceDate, startTime);
    }

WorkTimeRecord를 save하기 위해서는 Member를 알아야만 했고,

Member를 찾기 위해서 기존에는 Id값으로 Member를 찾아왔지만, 문득 이는 굉장히 '비효율적'이라는 생각이 들었다.

WorkTimeRecord를 저장하기 위해 필요한 것은 Member의 Id 값이지, Member의 모든 정보를 찾아올 필요는 없었기 때문에 불필요한 select문이 발생하는 셈이다.

그래서, 이리저리 알아보던 차, Proxy객체라는 존재와 getReferenceById()라는 JpaRepository의 메소드를 알게 되었다.

Proxy는 여러 곳에서 쓰이는 용어이지만, JPA를 구현하고 있는 hibernate에서는 Proxy객체는 실제 Entity(여기서는 Member)를 상속 받은 껍데기 객체이다.

Entity를 상속받았기 때문에 Entity의 모든 역할을 대신 수행할 수 있으나, 내부의 값은 모두 비어있는 상태가 된다.

만일, 상태가 필요한 순간이 되면 그때 JPA의 영속성 컨텍스트를 통하여 실제 Entity를 조회하여 값을 찾아오게 된다.

위와 같은 기술을 Lazy라고 한다.

즉, 나의 처음의 고민은 이를 통해 해결할 수 있게 되었다.

    @Transactional
    public void recordArrivalTime(Long memberId, LocalDate attendanceDate, LocalTime startTime) {
        Member member = memberRepository.getReferneceById(memberId);
        workTimeRecordService.recordArrivalTime(member, attendanceDate, startTime);
    }

이렇게, Proxy객체로 Member를 찾게 되면, 실제로 select문은 발생하지 않고 정상적으로 WorkTimeRecord에 Member값을 할당할 수 있게 된다.

 

댓글을 작성해보세요.