JPA에서 ID값으로 객체를 가져오는 메소드는 두가지이다.
getById / findById
@Override
public T getById(ID id) {
Assert.notNull(id, ID_MUST_NOT_BE_NULL);
return em.getReference(getDomainClass(), id);
}
getById() 는 원래 getOne() 이었으나 해당 메소드가 Deprecated 되고 대체되었다.
내부적으로 EntityManager.getReference() 메소드를 호출하기 때문에 엔티티를 직접 반환하는게 아니라 프록시만 반환한다.
프록시만 반환하기 때문에 실제로 사용하기 전까지는 DB 에 접근하지 않으며, 만약 나중에 프록시에서 DB 에 접근하려고 할 때 데이터가 없다면 EntityNotFoundException 이 발생한다.
@Override
public Optional<T> findById(ID id) {
Assert.notNull(id, ID_MUST_NOT_BE_NULL);
Class<T> domainType = getDomainClass();
if (metadata == null) {
return Optional.ofNullable(em.find(domainType, id));
}
LockModeType type = metadata.getLockModeType();
Map<String, Object> hints = new HashMap<>();
getQueryHints().withFetchGraphs(em).forEach(hints::put);
return Optional.ofNullable(type == null ? em.find(domainType, id, hints) : em.find(domainType, id, type, hints));
}
실제 DB 에 요청해서 엔티티를 가져온다.
정확히 말하면 영속성 컨텍스트의 1차 캐시를 먼저 확인하고 데이터가 없으면 실제 DB 에 데이터가 있는지 확인한다.
findById의 리턴 형식은 Optional인데 이게 또 까다롭다..
null일때(찾는 element가 없을때) 처리를 해주기 위함인데,
나는 NoSuchElementException을 던지도록 해주었다.