일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- Spring Boot
- kotlin
- b3-propagation
- spring3 spring2 traceid
- asynccustomautoconfiguration
- aws secretmanager
- jpa
- traceasynccustomautoconfiguration
- java
- asyncconfigurer
- CompletableFuture
- traceId
- Sleuth
- map
- java list
- Spring JPA
- @FunctionalInterface
- java lambda
- EnableWebMvc
- awssecretsmanagerpropertysources
- spring
- HashMap
- ResponseBody
- java.util.list
- list
- elasticsearch
- SpringMVC
- DeferredImportSelector
- spring MVC
- micrometer tracing
- Today
- Total
du.study기록공간
JPA Null 처리 방법, List가 null이 아닌 이유 본문
이번에는 자바로 JPA Null 처리하는 방법에 대해 기록하려합니다.
당연하게 db조회시, 객체가 없을경우 null이 발생할 수 있고, 우리는 null을 대비해야만 합니다.
1. Optional
이전에 Java8 부터 등장한 Optional에 대해 포스팅을 한 적이 있습니다.
duooo-story.tistory.com/38?category=881766
JPA에서 단일 엔티티를 조회하는 경우, Optional을 사용하게 되어있습니다. 해당 부분으로 인하여 좀더 우아하게? null을 막을 수 있습니다.
public interface AccountRepository extends JpaRepository<Account,Long> {
Optional<Account> findById(Long id);
}
or
@NoRepositoryBean
public interface CrudRepository<T, ID> extends Repository<T, ID> {
Optional<T> findById(ID id);
}
Optional사용법은 위 포스팅을 참고 부탁드립니다.
이번에는 단일 entity가 아닌 List를 받는경우를 살펴보겠습니다.
우선 결과부터 작성하면 List로 받는 객체의 경우, null이 아닌 Empty List가 내려옵니다.
그렇다면 왜 그렇게 내려오는지를 확인하기위해 테스트를 진행하고자 몇가지의 코드를 작성했습니다.
// 1
(CrudRepository) findAll()
public interface AccountRepository extends JpaRepository<Account,Long> {
// 2
List<Account> findByIdGreaterThan(Long id);
// 3
@Query( value = "select myAccount from myAccount a where a.id > 1" ,nativeQuery = true)
List<Account> findAccountList(Long id);
}
1) 우선 기본 CrudRepository 에 있는 findAll을 살펴봤습니다.
기본 findAll 호출시, SimpleJpaRepository를 통해 findAll을 타고 들어가다 보면 다음과 같은 과정을 타게 됩니다.
- CriteriaQueryTypeQueryAdapter 에 있는 getResultList() 호출,
- org.hibernate.loader 에 processResultSet 과정을 통해 빈리스트 리턴
public List<X> getResultList() {
return jpqlQuery.getResultList();
}
-------------------------------------------
protected List processResultSet(
ResultSet rs,
QueryParameters queryParameters,
SharedSessionContractImplementor session,
boolean returnProxies,
ResultTransformer forcedResultTransformer,
int maxRows,
List<AfterLoadAction> afterLoadActions) throws SQLException {
....
final List results = new ArrayList();
....
final boolean debugEnabled = LOG.isDebugEnabled();
for ( count = 0; count < maxRows && rs.next(); count++ ) {
....
Object result = getRowFromResultSet(
rs,
session,
queryParameters,
lockModesArray,
optionalObjectKey,
hydratedObjects,
keys,
returnProxies,
forcedResultTransformer
);
results.add( result );
....
}
....
return results;
}
2) method Keyword를 통해 쿼리를 작성하고 리스트를 가져오는 경우에도 거의 비슷한 경우입니다.
static class CollectionExecution extends JpaQueryExecution {
@Override
protected Object doExecute(AbstractJpaQuery query, JpaParametersParameterAccessor accessor) {
return query.createQuery(accessor).getResultList();
}
}
public List<X> getResultList() {
return jpqlQuery.getResultList();
}
- JpaQueryExecution에 있는
- 이후 과정 위와 동일
3) 마지막으로 native Query를 이용하여 조회하는 경우, 2)와 동일한 과정을 통하여 결국 빈 리스트를 가져오게 됩니다.
다른 List조회 쿼리 생성방법이 많겠지만, 아마 거의 유사하거나 동일한 과정을 통해 결국 빈값을 가져오리라 생각합니다. 혹시 다른 케이스가 나오신다면 공유..! 부탁드립니다!
'JPA' 카테고리의 다른 글
JPA save() Domain Event 추가하기 (0) | 2020.12.13 |
---|---|
JPA - Pageable을 이용한 Limit설정 방법 (0) | 2020.09.17 |
JPA - JpaRepository API (0) | 2020.09.11 |
JPA Query update @modifying (0) | 2020.08.26 |