Spring/Spring Data JPA

[Spring Data JPA] 3-1. Defining Query Methods (2)

noahkim_ 2024. 8. 2. 10:59

4. Repository Methods Returning Collections or Iterables

Streamable

  • 스트림을 제공하는 인터페이스
  • Iterable을 확장
  • 스트림을 비병렬로 처리할 수 있게 함. (filter(), map() 등의 스트림 메서드 사용 가능)


예제

더보기
interface PersonRepository extends Repository<Person, Long> {
    Streamable<Person> findByFirstnameContaining(String firstname);
    Streamable<Person> findByLastnameContaining(String lastname);
}

Streamable<Person> result = repository
    .findByFirstnameContaining("av")
    .and(repository.findByLastnameContaining("ea"));

 

Custom Streamable (Wrapper Types)

  • Streamable 인터페이스 구현
  • 정적 팩토리 메서드 제공 (of() or valueOf())

 

예제

더보기
class Product {                                         
    MonetaryAmount getPrice() { … }
}

@RequiredArgsConstructor(staticName = "of")
class Products implements Streamable<Product> {         
    private final Streamable<Product> streamable;

    public MonetaryAmount getTotal() {                    
        return streamable.stream()
                        .map(Product::getPrice)
                        .reduce(Money.of(0), MonetaryAmount::add);
    }

    @Override
    public Iterator<Product> iterator() {                 
    	return streamable.iterator();
    }
}


interface ProductRepository extends Repository<Product, Long> {
    Products findAllByDescriptionContaining(String text); 
}

 

 

Support for Vavr Collections

  • 함수형 프로그래밍 라이브러리인 Vavr의 컬렉션 타입을 지원
Vavr 컬렉션 타입 자바 인터페이스
io.vavr.collection.Seq java.util.List
io.vavr.collection.Set java.util.List
io.vavr.collection.Map java.util.Map


5. Streaming Query Results

  • Stream<T> 타입 반환
  • 쿼리 메서드 결과를 점진적으로 처리 O

 

예제) 선언

더보기
// 커스텀 쿼리를 사용하여 결과를 스트리밍
@Query("select u from User u")
Stream<User> findAllByCustomQueryAndStream();

// 특정 조건을 만족하는 모든 결과를 스트리밍
Stream<User> readAllByFirstnameNotNull();

// 페이지 단위로 결과를 스트리밍
@Query("select u from User u")
Stream<User> streamAllPaged(Pageable pageable);

 

예제) 사용

더보기
try (Stream<User> users = userRepository.findAllByCustomQueryAndStream()) {
    users.forEach(user -> {
        // 각 user를 처리하는 로직
        System.out.println(user.getFirstname() + " " + user.getLastname());
    });
}

 

주의사항

  • Stream은 사용 후 반드시 닫아야 함 (데이터 리소스를 감싸고 있음)
  • 모든 Spring Data 모듈이 Stream<T>를 반환 타입으로 지원하지 않음 (확인 필요)

 

6. Asynchronous Query Results

  • 쿼리 메서드 호출 시, 결과 즉시 반환
  • 비동기적으로 실행됨
    • 백그라운드 동작
    • TaskExecutor에 제출됨

 

@Async

  • 비동기 쿼리 메서드 정의

 

예제

더보기
@Async
Future<User> findByFirstname(String firstname);

@Async
CompletableFuture<User> findOneByFirstname(String firstname);
Future<User> future = userRepository.findByFirstname("John");
User user = future.get(); // 쿼리 실행 완료를 기다린 후 결과를 가져옴
CompletableFuture<User> completableFuture = userRepository.findOneByFirstname("John");
completableFuture.thenAccept(user -> {
    // callback func
    // 쿼리 실행 완료 후 사용자에 대해 작업 수행
});