1. Обзор
Spring Data теперь поддерживает основные функции Java 8 – такие как Optional , Stream API и CompletableFuture .
В этой краткой статье мы рассмотрим несколько примеров того, как мы можем использовать их с фреймворком.
2. Опционально
Давайте начнем с методов репозитория CRUD, которые теперь оборачивают результаты в Необязательный :
public interface CrudRepositoryextends Repository { Optional findById(ID id); }
При возврате экземпляра Optional это полезный намек на то, что существует вероятность того, что значение может не существовать. Более подробную информацию о дополнительном можно найти здесь .
Все, что нам теперь нужно сделать, это указать тип возвращаемого значения как Необязательный :
public interface UserRepository extends JpaRepository{ Optional findOneByName(String name); }
3. Потоковый API
Spring Data также обеспечивает поддержку одной из наиболее важных функций Java 8 – API Stream .
В прошлом, когда нам нужно было вернуть более одного результата, нам нужно было вернуть коллекцию:
public interface UserRepository extends JpaRepository{ // ... List findAll(); // ... }
Одной из проблем с этой реализацией было потребление памяти.
Нам пришлось жадно загружать и хранить в нем все найденные предметы.
Мы могли бы улучшить ситуацию, используя пейджинг:
public interface UserRepository extends JpaRepository{ // ... Page findAll(Pageable pageable); // ... }
В некоторых сценариях этого достаточно, но в других – разбиение на страницы действительно не лучший путь из-за большого количества запросов, необходимых для извлечения данных.
Благодаря Java 8 Stream API и JPA – провайдерам-теперь мы можем определить, что наш метод репозитория возвращает только Поток объектов :
public interface UserRepository extends JpaRepository{ // ... Stream findAllByName(String name); // ... }
Spring Data использует специфичную для поставщика реализацию для потоковой передачи результата (Hibernate использует Scrollable ResultSet , EclipseLink использует ScrollableCursor ). Это уменьшает объем потребления памяти и запросов к базе данных. Из-за этого он также намного быстрее, чем два решения, упомянутые ранее.
Обработка данных с помощью Потока требует, чтобы мы закрыли поток , когда закончим его .
Это можно сделать, вызвав метод close() в потоке или используя try-with-resources :
try (StreamfoundUsersStream = userRepository.findAllByName(USER_NAME_ADAM)) { assertThat(foundUsersStream.count(), equalTo(3l));
Мы также должны помнить о вызове метода репозитория в транзакции . В противном случае мы получим исключение:
org.springframework.dao.InvalidDataAccessApiUsageException : Вы пытаетесь выполнить метод потокового запроса без окружающей транзакции, которая сохраняет соединение открытым, чтобы Поток действительно мог быть использован. Убедитесь, что код, потребляющий поток, использует @Transactional или любой другой способ объявления транзакции (только для чтения).
4. CompletableFuture
Репозитории данных Spring могут работать асинхронно с поддержкой Java 8 CompletableFuture и механизма Spring для асинхронного выполнения методов:
@Async CompletableFuturefindOneByStatus(Integer status);
Клиент, вызывающий этот метод, немедленно вернет будущее, но метод продолжит выполнение в другом потоке.
Более подробную информацию о CompletableFuture processing можно найти здесь .
5. Заключение
В этом уроке мы показали, как функции Java 8 работают вместе с данными Spring.
Полная реализация примеров доступна на Github .