Spring Data Java 8 Support – Spring Data Java 8支持

最后修改: 2018年 1月 2日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

Spring Data now supports core Java 8 features – such as Optional, Stream API and CompletableFuture.

Spring Data现在支持Java 8的核心特性–如OptionalStream API和CompletableFuture

In this quick article, we’ll go through some examples of how we can use these with the framework.

在这篇快速文章中,我们将通过一些例子来说明我们如何用框架来使用这些。

2. Optional

2.可选

Let’s start with the CRUD repository methods – which now wrap results in an Optional:

让我们从CRUD存储库方法开始–现在将结果包在一个Optional中。

public interface CrudRepository<T, ID> extends Repository<T, ID> {
    
    Optional<T> findById(ID id);
    
}

When returning an Optional instance, it’s a useful hint that there’s a possibility that the value might not exist. More information on Optional can be found here.

当返回一个Optional实例时,它是一个有用的提示,即该值有可能不存在。关于Optional的更多信息可以在这里找到。

All we now have to do is to specify return type as an Optional:

我们现在要做的就是把返回类型指定为Optional

public interface UserRepository extends JpaRepository<User, Integer> {
    
    Optional<User> findOneByName(String name);
    
}

3. Stream API

3.Stream API

Spring Data also provides the support for one of the most important features of Java 8 – the Stream API.

Spring Data还提供了对Java 8最重要特性之一的支持–Stream API。

In the past, whenever we needed to return more than one result, we needed to return a collection:

在过去,只要我们需要返回一个以上的结果,我们就需要返回一个集合。

public interface UserRepository extends JpaRepository<User, Integer> {
    // ...
    List<User> findAll();
    // ...
}

One of the problems with this implementation was the memory consumption.

这种实现方式的问题之一是内存消耗。

We had to eagerly load and keep all retrieved objects in it.

我们不得不急切地加载并将所有检索到的对象保存在其中。

We could improve by leveraging paging:

我们可以通过利用分页来改进。

public interface UserRepository extends JpaRepository<User, Integer> {
    // ...
    Page<User> findAll(Pageable pageable);
    // ...
}

In some scenarios, that’s enough, but in others – pagination is really not the way to go, due to the high number of requests necessary to retrieve the data.

在某些情况下,这就足够了,但在其他情况下–分页确实不是办法,因为检索数据所需的请求数量很多。

Thanks to Java 8 Stream API and JPA providers – we can now define that our repository method returns just a Stream of objects:

感谢Java 8 Stream API和JPA提供者–我们现在可以定义我们的存储库方法只返回一个Stream对象

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

Spring Data uses provider-specific implementation to stream the result (Hibernate uses ScrollableResultSet, EclipseLink uses ScrollableCursor). It reduces the amount of memory consumption and query calls to a database. Because of that, it’s also much faster than two solutions mentioned earlier.

Spring Data使用特定提供者的实现来流化结果(Hibernate使用ScrollableResultSet,EclipseLink使用ScrollableCursor)。它减少了内存消耗和对数据库的查询调用。正因为如此,它也比前面提到的两种解决方案快得多。

Processing data with a Stream requires us to close a Stream when we finish it.

Stream处理数据,需要我们在结束时关闭Stream

It can be done by calling the close() method on a Stream or by using try-with-resources:

它可以通过调用Stream上的close()方法或使用try-with-resources来完成。

try (Stream<User> foundUsersStream 
  = userRepository.findAllByName(USER_NAME_ADAM)) {
 
assertThat(foundUsersStream.count(), equalTo(3l));

We must also remember to call a repository method within a transaction. Otherwise, we’ll get an exception:

我们还必须记住在一个事务中调用一个存储库方法。否则,我们会得到一个异常。

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.

org.springframework.dao.InvalidDataAccessApiUsageException:你试图执行一个流式查询方法,而没有一个周围的事务来保持连接的开放性,以便Stream能够真正被消费。请确保消费流的代码使用@Transactional或任何其他声明(只读)事务的方式。

4. CompletableFuture

4.CompletableFuture

Spring Data repositories can run asynchronously with the support of Java 8’s CompletableFuture and Spring mechanism for asynchronous method execution:

在Java 8的CompletableFuture和Spring异步方法执行机制的支持下,Spring Data存储库可以异步运行。

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

A client which calls this method will return a future immediately but a method will continue an execution in a different thread.

调用该方法的客户端将立即返回一个未来,但一个方法将在不同的线程中继续执行。

More info about CompletableFuture processing can be found here.

关于CompletableFuture处理的更多信息可以在这里找到。

5. Conclusion

5.结论

In this tutorial, we showed how Java 8 features work together with Spring Data.

在本教程中,我们展示了Java 8的特性如何与Spring Data一起工作。

The full implementation of the examples is available over on Github.

完整的示例实现可在Github上获得over