Перейти к основному содержимому

Поддержка Spring Data Java 8

· 3 мин. чтения

Задача: Сумма двух чисел

Напишите функцию twoSum. Которая получает массив целых чисел nums и целую сумму target, а возвращает индексы двух чисел, сумма которых равна target. Любой набор входных данных имеет ровно одно решение, и вы не можете использовать один и тот же элемент дважды. Ответ можно возвращать в любом порядке...

ANDROMEDA

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);

}

При возврате необязательного экземпляра это полезный намек на то, что значение может не существовать. Более подробную информацию о Факультативе можно найти здесь .

Все, что нам теперь нужно сделать, это указать тип возвращаемого значения как необязательный :

public interface UserRepository extends JpaRepository<User, Integer> {

Optional<User> findOneByName(String name);

}

3. Потоковое API

Spring Data также обеспечивает поддержку одной из самых важных функций Java 8 — Stream 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 теперь мы можем определить, что наш метод репозитория возвращает только поток объектов :

public interface UserRepository extends JpaRepository<User, Integer> {
// ...
Stream<User> findAllByName(String name);
// ...
}

Spring Data использует специфичную для провайдера реализацию для потоковой передачи результата (Hibernate использует ScrollableResultSet , EclipseLink использует ScrollableCursor ). Это уменьшает объем потребления памяти и запросов к базе данных. Из-за этого это также намного быстрее, чем два решения, упомянутые ранее.

Обработка данных с помощью Stream требует от нас закрытия Stream , когда мы его закончим .

Это можно сделать, вызвав метод close() для Stream или используя try-with-resources :

try (Stream<User> foundUsersStream 
= userRepository.findAllByName(USER_NAME_ADAM)) {

assertThat(foundUsersStream.count(), equalTo(3l));

Мы также должны помнить о вызове метода репозитория внутри транзакции . В противном случае мы получим исключение:

org.springframework.dao.InvalidDataAccessApiUsageException : вы пытаетесь выполнить метод потокового запроса без окружающей транзакции, которая поддерживает соединение открытым, чтобы поток мог фактически использоваться. Убедитесь, что код, потребляющий поток, использует @Transactional или любой другой способ объявления транзакции (только для чтения).

4. Завершаемое будущее

Репозитории Spring Data могут работать асинхронно с поддержкой CompletableFuture Java 8 и механизма Spring для асинхронного выполнения методов:

@Async
CompletableFuture<User> findOneByStatus(Integer status);

Клиент, который вызывает этот метод, немедленно вернет будущее, но метод продолжит выполнение в другом потоке.

Подробнее об обработке CompletableFuture можно узнать здесь .

5. Вывод

В этом руководстве мы показали, как функции Java 8 работают вместе с Spring Data.

Полная реализация примеров доступна на Github .