Spring Boot 버전 2.5 이후 getById()메서드는 deprecated! 즉, 더이상 사용하지 않게 되었다.
대신 getReferenceById()를 사용한다.
내부적으로 EntityManager의 getReference() 메서드를 호출한다. getReference() 메서드를 호출하면 프록시 객체를 리턴한다. 실제 쿼리는 프록시 객체를 통해 최초로 데이터에 접근하는 시점에 실행된다. 이때 데이터가 존재하지 않을 경우 EntityNotFoundException이 발생한다.
@Override
public T getById(ID id) {
Assert.notNull(id, ID_MUST_NOT_BE_NULL);
return em.getReference(getDomainClass(), id);
}
@Override
public Product selectProduct(Long number) {
Product selectedProduct = productRepository.getReferenceById(number);
return selectedProduct;
}
내부적으로 EntityManager의 find() 메서드를 호출한다. 이 메서드는 영속성 컨텍스트의 캐시에서 값을 조회한 후 영속성 컨텍스트에 값이 존재하지 않는다면 실제 데이터베이스에서 데이터를 조회한다. 리턴 값으로 Optional 객체를 전달한다.
@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));
}
@Override
public Product updateProductName(Long number, String name) throws Exception {
Optional<Product> selectedProduct = productRepository.findById(number);
Product updatedProduct;
if(selectedProduct.isPresent()){
Product product = selectedProduct.get();
product.setName(name);
product.setUpdatedAt(LocalDateTime.now());
updatedProduct = productRepository.save(product);
} else{
throw new Exception();
}
return updatedProduct;
}
getById() 는 해당 엔티티를 사용하기 전까진 DB 에 접근하지 않기 때문에 성능상으로 좀더 유리하다.
따라서 특정 엔티티의 ID 값만 활용할 일이 있다면 DB 에 접근하지 않고 프록시만 가져와서 사용할 수 있다.
조회 기능 구현을 위해서 어떤 메서드를 사용하던지 무관하다. 비즈니스 로직을 구현하는데 적합한 방식을 선정해서 활용하면 된다.