`StudyWithMe` 프로젝트를 하면서 잊고 있었던 `getReferenceById()` JPA 메서드를 사용했다.
findById()와 getReferenceById()
findById()와 getReferenceById()가 데이터를 가져오는 방식에는 어떤 차이가 있을까?
findById()
Optional<T> findById(ID id)
- Optional<T>: 조회된 엔티티를 Optional로 감싼 반환 타입이다.
- Optional은 엔티티가 존재하지 않을 수도 있는 경우에 사용된다.
- ID: 조회할 엔티티의 식별자(ID) 타입이다.
- 조회된 엔티티 객체를 Optional로 감싸서 반환한다.
- `CrudRepository`와 `JpaRepository` 인터페이스에서 모두 제공되는 메소드이다.
getReferenceById()
public T getReferenceById(ID id)
- T: 반환 타입으로 엔티티의 클래스 타입이다.
- ID: 조회할 엔티티의 식별자(ID) 타입이다.
- JpaRepository 인터페이스에서만 제공된다.
- 데이터가져오는 방식
- 지연로딩(Lazy Loading) : 엔티티를 실제로 사용할 때까지 데이터베이스 조회를 지연한다.
- 실제 엔티티 객체가 필요한 시점에서는 프록시 객체가 아닌 실제 엔티티를 반환환다.
- 처음에는 Proxy객체로 가지고 있다.
좀 더 간단히 정리하자면,
findById()
`findById()`는 DB에서 실제로 조회하여 존재한다면 영속성 컨텍스트에 저장한 뒤,
`Optional`로 감싼 엔티티 객체를 반환한다.(쿼리 발생)
getReferenceById()
`getReferenceById()`는 우선, ID를 받아 그걸 프록시 객체로 감싸서 반환해준다.
그리고 추후 지연 로딩 시 저장된 ID를 토대로 데이터베이스에서 조회한다.
만약, 해당 엔티티의 정보가 없다면 -> 오류 발생
만약, 엔티티 정보가 있다면 -> 실제 엔티티를 반환
(지연 로딩이므로 조회 전까지 쿼리 발생 X, 또한, ID만 조회하는 경우는 쿼리 발생 X)
지금까지 개념을 알아보았고 내가 생각한 유용하게 적용할 수 있는 상황은 아래와 같다.
적용 가능 코드 예시
@Transactional
public CreateStudyRoomLikeResponse createLike(Long studyRoomId, UUID userId) {
validateExistsLike(studyRoomId, userId);
StudyRoom studyRoom = validateStudyRoomWithLock(studyRoomId);
User user = userRepository.getReferenceById(userId);
StudyRoomLike studyRoomLike = StudyRoomLike.of(studyRoom, user);
likeRepository.save(studyRoomLike);
studyRoom.likeStudyRoom();
return CreateStudyRoomLikeResponse.from(studyRoomLike);
}
코드를 보면 알 수 있겠지만, `StudyRoomLike`를 생성하기 위해서는 `StudyRoom`, `User`의 정보가 둘다 필요하다.
그리고 `userId`는 필터단에서 이미 유효한 `userId` 임이 입증이 되어있는 상태라고 가정했을 때,
`StudyRoomLike`를 생성하기 위해 `User`를 한 번더 검증하는 것은 불필요한 쿼리 작업이 된다.
그렇기에 `getReferenceById()`를 사용해 `User` 프록시 객체를 받고 그걸 `StudyRoomLike` 생성에 활용한다.
위의 경우가 아니더라도 양방향 관계에서 객체지향 언어를 사용 시 객체 간의 관계도 설정해주어야 하는데,
해당 작업에서는 해당 객체의 모든 정보가 필요한 것이 아니라 `ID`만 필요한 경우가 많다.
그래서 그 경우 `getReferenceById()`를 사용하면 프록시 객체를 사용해 객체지향적으로 설계하는데도 도움이 될 것이다.
'Spring > JPA' 카테고리의 다른 글
[QueryDSL] QueryDSL이란? (0) | 2024.03.30 |
---|---|
Spring Pagination 연습 (0) | 2024.03.08 |
[SpringBoot] OSIV와 성능 최적화 (0) | 2024.02.01 |
[SpringBoot] JPA Collection 페이징 처리 (0) | 2024.01.29 |
[SpringBoot] JPA Collection 페치 조인 최적화 (0) | 2024.01.29 |