«1. Обзор
Spring Data теперь поддерживает основные функции Java 8, такие как Optional, Stream API и CompletableFuture.
В этой быстрой статье мы рассмотрим несколько примеров того, как мы можем использовать их с фреймворком.
2. Необязательный
Начнем с методов репозитория CRUD, которые теперь оборачивают результаты в необязательный: может не существовать. Дополнительную информацию о факультативе можно найти здесь.
public interface CrudRepository<T, ID> extends Repository<T, ID> {
Optional<T> findById(ID id);
}
Теперь все, что нам нужно сделать, это указать тип возвращаемого значения как необязательный:
3. Stream API
public interface UserRepository extends JpaRepository<User, Integer> {
Optional<User> findOneByName(String name);
}
Spring Data также обеспечивает поддержку одной из наиболее важных функций Java 8 — потоковый API.
В прошлом всякий раз, когда нам нужно было вернуть более одного результата, нам нужно было вернуть коллекцию:
Одной из проблем с этой реализацией было потребление памяти.
public interface UserRepository extends JpaRepository<User, Integer> {
// ...
List<User> findAll();
// ...
}
Нам пришлось жадно загружать и хранить в нем все извлеченные объекты.
Мы могли бы улучшить, используя разбиение по страницам:
В некоторых сценариях этого достаточно, но в других случаях разбивка на страницы действительно не подходит из-за большого количества запросов, необходимых для извлечения данных. .
public interface UserRepository extends JpaRepository<User, Integer> {
// ...
Page<User> findAll(Pageable pageable);
// ...
}
Благодаря Java 8 Stream API и поставщикам JPA — теперь мы можем определить, что наш метод репозитория возвращает только поток объектов:
Spring Data использует специфичную для поставщика реализацию для потоковой передачи результата (Hibernate использует ScrollableResultSet, EclipseLink использует ScrollableCursor). Это уменьшает объем потребления памяти и запросов к базе данных. Из-за этого это также намного быстрее, чем два решения, упомянутые ранее.
public interface UserRepository extends JpaRepository<User, Integer> {
// ...
Stream<User> findAllByName(String name);
// ...
}
Обработка данных с помощью потока требует, чтобы мы закрыли поток, когда мы его закончим.
Это можно сделать, вызвав метод close() для Stream или используя try-with-resources:
Мы также должны помнить о вызове метода репозитория внутри транзакции. В противном случае мы получим исключение:
try (Stream<User> foundUsersStream
= userRepository.findAllByName(USER_NAME_ADAM)) {
assertThat(foundUsersStream.count(), equalTo(3l));
4. CompletableFuture
org.springframework.dao.InvalidDataAccessApiUsageException: You’re trying to execute a streaming query method without a surrounding transaction that keeps the connection open so that the Stream can actually be consumed. Make sure the code consuming the stream uses @Transactional or any other way of declaring a (read-only) transaction.
Spring Репозитории данных могут работать асинхронно с поддержкой механизма Java 8 CompletableFuture и Spring для асинхронного выполнения методов:
Клиент, который вызывает это Метод немедленно вернет будущее, но метод продолжит выполнение в другом потоке.
@Async
CompletableFuture<User> findOneByStatus(Integer status);
Дополнительную информацию об обработке CompletableFuture можно найти здесь.
5. Заключение
В этом руководстве мы показали, как функции Java 8 работают вместе со Spring Data.
Полная реализация примеров доступна на Github.
«