[JPA] 연관관계와 getReferenceById()

조시현·2024년 7월 22일
0

JPA

목록 보기
2/2
post-thumbnail

이번 블로그는 간단한 내용이 될거 같습니다!
바로 JPA의 getReferenceById() 라는 메서드에 대해서 소개해드리려고 합니다!

우선 getReferenceById() 메서드를 사용하게 된 계기는
JPA만을 이용해서 객체를 만들고 싶은데 그 객체에 연관관계의 객체가 함께 있는 경우
연관관계의 객체의 Id만 필요함에도 불구하고 findById()를 통해서 모든 객체를 가져와야한다는 점에서 이 문제는 시작되었습니다.

getReferenceById()

이 메서드는 JpaRepository의 기본 메서드며, 구현을 해줄필요 없이 JpaRepository아래에서 라면 언제든지 사용이 가능하다

자바17 공식 주석

/**
 *
 * 주어진 식별자를 가진 엔티티에 대한 참조를 반환합니다. 
 * JPA 지속성 공급자가 구현된 방식에 따라 항상 인스턴스를 반환하고
 * 첫 번째 액세스 시 jakarta.persistence.EntityNotFoundException을
 * throw할 가능성이 매우 높습니다. 일부는 잘못된 식별자를 즉시 거부합니다.
 * @param:
 * id – null이 될 수 없습니다.
 * @return:
 * 주어진 식별자를 가진 엔터티에 대한 참조입니다.
 * @since:
 * 2.7
 * @see:
 * 예외가 발생하는 시기에 대한 자세한 내용은 EntityManager#getReference(Class, Object)를 참조하세요.

위의 소스는 getReferenceById의 공식 설명이다.

장점

해당 메서드를 사용하면 객체에 대한 ID만을 조회를 하여서 객체를 반환해준다.
기존 findByID는 Optional<객체>의 형태로 반환을 하였지만, getReferenceById()는 객체(프록시 객체를 반환)만 반환을 해주므로 간단한 작업에 편하게 사용할 수 있다.

그래서 얻을 수 있는 이점은
엔티티 내부의 모든 필드를 다 가져오지 않으므로 많은 필드를 가지고 있는 엔티티라도 가볍게 가져올 수 있다.
또한 findById와 달리 반환값이 Optional로 감싸서 주지않고 엔티티 객체를 직접 주므로 Optional에 대한 검증 코드를 직접 짜주지 않아도된다.

특징

대신 엔티티가 존재하지 않을 경우 EntityNotFoundException을 발생시킵니다.
또한, 이 메서드를 호출하면 JPA는 데이터베이스를 조회하지 않고 주어진 ID를 기반으로 프록시 객체를 생성합니다. 그리고 추후 다른 필드의 값들이 필요하다면 지연 로딩을 지원통해서 값들을 가지고 올 수도 있습니다.

따라서, getReferenceById는 엔티티의 지연 로딩이 필요한 경우에 유용하게 사용할 수 있습니다. 또한 저처럼 간단한 생성 로직을 만들때 간단하게 객체를 조회한 후 Id값 사용하는 경우가 많은데 이러한 경우 로직을 간단하게 할 수 있고 성능도 높힐 수 있다.

private StudentQuiz(Student student, Quiz quiz) {
    this.id = StudentQuizId.createStudentQuizId(student.getId(), quiz.getId());
    this.student = student;
    this.quiz = quiz;
}

위와 같은 상황에서
Student와 Quiz객체를 getReferenceById()를 통해서 가져온다면 간단하고 빠르게 객체 생성이 가능하다.

getReferenceById() vs findById()

특성getReferenceById()findById()
데이터베이스 접근 시점엔티티의 실제 데이터 접근 시점까지 지연메서드 호출 시 즉시 데이터베이스 조회
반환 객체프록시 객체실제 엔티티 객체
성능초기 단계에서 성능 최적화 가능즉시 조회로 인한 성능 저하 가능
LazyInitializationException영속성 컨텍스트 밖에서 프록시 접근 시 발생 가능영속성 컨텍스트 밖에서도 안전
데이터 유효성존재하지 않는 ID일 경우 예외 발생 가능존재하지 않는 ID일 경우 Optional.empty() 반환
사용 사례엔티티의 일부 필드만 필요할 때, 성능 최적화를 위해 사용전체 엔티티가 필요할 때 사용
주의 사항프록시 객체의 사용과 관련된 예외 발생 가능, 프록시의 실제 엔티티 변환 주의 필요데이터베이스 조회가 즉시 발생하므로 지연 로딩 효과 없음

결론

getReferenceById() 메서드는 JPA에서 프록시 객체를 반환하여 성능을 최적화하고 불필요한 데이터 조회를 줄이는 데 유용합니다. 이는 엔티티의 특정 필드만 필요할 때 사용되며, 효율적인 데이터 처리가 가능합니다.

그러나 전체 엔티티가 즉시 필요할 때는 findById()를 사용하는 것이 더 좋습니다.

이 두 가지 방법을 적절히 활용하여 상황에 맞게 사용하면 최적의 성능을 이끌어 낼 수 있을 것입니다! Happy coding!

profile
소프트웨어 관련 고민을 좋아하고 상황에 맞는 답을 함께 찾아가는 과정을 좋아합니다. 😀

0개의 댓글