스프링데이터 + JPA/스프링 데이터 JPA

14. 스프링 데이터 JPA 반환 타입

sdafdq 2023. 11. 21. 07:18

스프링 데이터 JPA는 이 조회해는 것의 반환타입을 유연하게 제공함.

컬렉션으로, 아니면 단건, 아니면 단건인데 Optional로 등등..

 

List<Member> findListByUsername(String username);
Member findMemberByUsername(String username);
Optional<Member> findOptionalByUsername(String username);

굉장히 많은 반환타입이 보장된다.

 

컬렉션, 단건, 옵셔널 이거 외에도 많다.

 

컬렉션은 없으면 그냥 빈 컬렉션.

단건은 null. 이게 조금 순수 JPA와 다른 부분인데 순수 JPA는 없으면 예외를 날리는 데 스프링 데이터 JPA는 그 예외를 잡아서 null로 return함.

옵셔널은 마치 양자처럼 있거나 없거나.

 

이 외에도 엄청나게 많음. 반환타입으로 쓸 수 있는 게.

 

아 참고로, Optional이나 Member가 단건인데 조회해봤더니 복수가 나오면 예외를 날림.

 

그리고 이 예외는, 스프링의 추상적 예외로 중간에 바꿔서 날려줌.

 

에러 스택트레이스 쫒아가다 보면

Caused by: jakarta.persistence.NonUniqueResultException: query did not return a unique result: 2

이 jakarta, jpa예외에서,

 

org.springframework.dao.IncorrectResultSizeDataAccessException: query did not return a unique result: 2

이 스프링 예외로 변환해줘서, 특정기술에 종속적이 아닌 예외의 표준화? 가 가능.

 

그래서 저 스프링 예외만 참고하면 돼서 DB를 바꿔도 무난하게 쓸 수 있음.

 

@Test
public void testReturnType(){
    Member m1 = new Member("AAA", 10);
    Member m2 = new Member("BBB", 20);

    memberRepository.save(m1);
    memberRepository.save(m2);

    List<Member> listResult = memberRepository.findListByUsername("AAA");
    Member result = memberRepository.findMemberByUsername("AAA");
    Optional<Member> optionalResult = memberRepository.findOptionalByUsername("AAA");

    System.out.println("listResult = " + listResult.getClass());
    System.out.println("result = " + result.getClass());
    System.out.println("optionalResult = " + optionalResult.getClass());
}
listResult = class java.util.ArrayList
result = class study.datajpa.entity.Member
optionalResult = class java.util.Optional

다 타입들 제대로 나옴.

 

이거 외에도,

Return typeDescription

void Denotes no return value.
Primitives Java primitives.
Wrapper types Java wrapper types.
T A unique entity. Expects the query method to return one result at most. If no result is found, null is returned. More than one result triggers an IncorrectResultSizeDataAccessException.
Iterator<T> An Iterator.
Collection<T> A Collection.
List<T> A List.
Optional<T> A Java 8 or Guava Optional. Expects the query method to return one result at most. If no result is found, Optional.empty() or Optional.absent() is returned. More than one result triggers an IncorrectResultSizeDataAccessException.
Option<T> Either a Scala or Vavr Option type. Semantically the same behavior as Java 8’s Optional, described earlier.
Stream<T> A Java 8 Stream.
Streamable<T> A convenience extension of Iterable that directly exposes methods to stream, map and filter results, concatenate them etc.
Types that implement Streamable and take a Streamable constructor or factory method argument Types that expose a constructor or ….of(…)/….valueOf(…) factory method taking a Streamable as argument. See Returning Custom Streamable Wrapper Types for details.
Vavr Seq, List, Map, Set Vavr collection types. See Support for Vavr Collections for details.
Future<T> A Future. Expects a method to be annotated with @Async and requires Spring’s asynchronous method execution capability to be enabled.
CompletableFuture<T> A Java 8 CompletableFuture. Expects a method to be annotated with @Async and requires Spring’s asynchronous method execution capability to be enabled.
Slice<T> A sized chunk of data with an indication of whether there is more data available. Requires a Pageable method parameter.
Page<T> A Slice with additional information, such as the total number of results. Requires a Pageable method parameter.
GeoResult<T> A result entry with additional information, such as the distance to a reference location.
GeoResults<T> A list of GeoResult<T> with additional information, such as the average distance to a reference location.
GeoPage<T> A Page with GeoResult<T>, such as the average distance to a reference location.
Mono<T> A Project Reactor Mono emitting zero or one element using reactive repositories. Expects the query method to return one result at most. If no result is found, Mono.empty() is returned. More than one result triggers an IncorrectResultSizeDataAccessException.
Flux<T> A Project Reactor Flux emitting zero, one, or many elements using reactive repositories. Queries returning Flux can emit also an infinite number of elements.
Single<T> A RxJava Single emitting a single element using reactive repositories. Expects the query method to return one result at most. If no result is found, Mono.empty() is returned. More than one result triggers an IncorrectResultSizeDataAccessException.
Maybe<T> A RxJava Maybe emitting zero or one element using reactive repositories. Expects the query method to return one result at most. If no result is found, Mono.empty() is returned. More than one result triggers an IncorrectResultSizeDataAccessException.
Flowable<T> A RxJava Flowable emitting zero, one, or many elements using reactive repositories. Queries returning Flowable can emit also an infinite number of elements.

상당히 많음.

void, 원시타입, wrapper는 Integer 그런거고,

stream, 뭐 비동기 future,

page는 페이징 할 때 말할꺼고,

mono, flux는 reactor(리액트아님) 등등등..