JPA

find vs get (네이밍 컨벤션과 JPA에서의 내부 동작 차이)

수수한개발자 2022. 8. 3.
728x90

프로젝트를 하면서 getReferenceByid라는것을 알았는데요 여기에 대해서 정리해 보도록 하겠습니다.

 

여기서 getReferenceByid는 findById와 다른데요. 간단하게 알아 보겠습니다.

 

Optional<T> findById(ID id) : 탐색하다. 탐색 결과가 없을 수 있음. 내부 예외 발생 없음.

T getOne(ID id) : 가져오다. 가져오려는 대상이 없을 시, 내부에서 예외 발생. (EntityNotFoundException)

getOne은 Deprecated 되었고 대신 getReferenceById 가 권장됨.

getReferenceById는 EntityManager#getReference 를 사용하며, 조회된 entity 내부값 접근 전까지 lazy loading처리함.

 

Repository 내 구현되는 메서드 명으로 find 와 get 을 선택함에는 다소 신중함이 필요합니다.

메서드명으로 find를 쓰느냐, get을 쓰느냐에 따라서
메서드 내부 구현이 어떻게 되어있을지도 함께 전달할 수 있기 때문입니다.

 

findById 

 

CrudRepository 인터페이스에 있는 findById 메서드입니다.

Returns 를 살펴보면, 매개변수로 전달된 ID에 해당하는 entity를 반환하거나,
해당하는 entity가 없을 경우 Optional.empty()를 반환한다고 합니다.
즉, 탐색 결과가 없더라도 내부에서 예외를 발생시키지 않습니다.

Throws 를 살펴보면, ID가 null일 경우엔 IllegalArgumentException이 발생할 수 있다고 합니다.

 

JpaRepository#getOne

 

JpaRepository 인터페이스에 있는 getOne 메서드입니다.

Optional<T> 가 아닌 T가 반환값입니다.
즉, 매개변수로 전달된 ID에 해당하는 entity를 반환하되,
없을 경우 내부에서 예외를 발생시킵니다.

Returns 문장 이후 캡쳐에 잘린 내용은 다음과 같습니다.

Returns a reference to the entity with the given identifier.
Depending on how the JPA persistence provider is implemented
this is very likely to always return an instance and throw an EntityNotFoundException on first access.
Some of them will reject invalid identifiers immediately.

특정 대상이 존재하지 않을 때의 커스텀 예외를 XXNotFoundException이라고 할 수 있겠구나 하는 점도 눈에 띄네요.
표준 예외를 사용하지 않았다는 점에서 친절하다는 생각도 듭니다.

 

JpaRepository #gerReferenceById

 

앞서 살펴본 T getOne(ID id) 메서드는 Deprecated 되었고,
대신 T getReferenceById(ID id) 를 사용하라고 안내되어 있습니다.

Since 2.7 이라고 표기되어 있는데요, 2.7 버전은 2022년에 릴리즈되었기 때문에 상당히 최근에 추가된 메서드입니다.

Returns 문장 이후로 잘린 내용은 아래와 같습니다.

Returns a reference to the entity with the given identifier.
Depending on how the JPA persistence provider is implemented
this is very likely to always return an instance and throw an EntityNotFoundException on first access.
Some of them will reject invalid identifiers immediately.

getOne과 동일합니다.

여기까지는 get과 find의 메서드 네이밍에 따른 구현 차이를 알아봤습니다.

 

getOne, getReferenceById 의 동작

 

getOne, getReferenceById 는 findById와 동작도 다릅니다.
단순히 Optional 로 반환하느냐, 내부에서 예외를 발생시키느냐 아니냐의 말고도 다른 점이 있습니다.

 

바로 lazy loading 입니다,
getOne 또는 getReferenceById 메서드로 반환된 객체 내부의 정보를 요청하는 시점에
그제서야 DB를 조회합니다.
즉, 내부의 값을 필요로 하지는 않고, 다른 객체에게 할당하는 목적으로만 조회하는 경우,
getReferenceById 를 사용하면 성능상 이점이 있을 수 있다는 의미입니다.

getReferenceById 는 EntityManager의 getReference 메서드를 호출하여,
참조값만 가져온 후, 조회된 entity의 내부 값이 필요해지는 시점에 lazy loading으로
DB를 조회해 값을 가져오도록 동작한다는 것인데요,

 

이런 의미에서 getOne 보다는 getReferenceById, 즉 참조값만 가져온다
라는 메서드 이름이 훨씬 정확한 의미를 전달한다고 볼 수 있는것 같습니다.

728x90

댓글