이번 블로그는 간단한 내용이 될거 같습니다!
바로 JPA의 getReferenceById() 라는 메서드에 대해서 소개해드리려고 합니다!
우선 getReferenceById() 메서드를 사용하게 된 계기는
JPA만을 이용해서 객체를 만들고 싶은데 그 객체에 연관관계의 객체가 함께 있는 경우
연관관계의 객체의 Id만 필요함에도 불구하고 findById()를 통해서 모든 객체를 가져와야한다는 점에서 이 문제는 시작되었습니다.
이 메서드는 JpaRepository의 기본 메서드며, 구현을 해줄필요 없이 JpaRepository아래에서 라면 언제든지 사용이 가능하다
/**
*
* 주어진 식별자를 가진 엔티티에 대한 참조를 반환합니다.
* 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!