1.概述
Spring Data 已支持Java8一些核心的特性-例如Optional,Stream,CompletableFuture。在此篇文章中,我们将通过一些例子来介绍如何在框架中使用这些特性。
2.Optional
让我们先从一个 JPA CrudRepository
方法看看,如何用Optional来装载数据。
public interface CrudRepository<T, ID> extends Repository<T, ID> {
Optional<T> findById(ID id);
}
当返回一个Optional实例时,一个有用的提示是其中所包含的值并不一定存在。想了解更多关于Optional的信息,请访问此处。
我们现在要做的就是将Optional指定为返回类型。
public interface UserRepository extends JpaRepository<User, Integer> {
Optional<User> findOneByName(String name);
}
3.Stream API
Spring Data 当然也支持 Stream API--Java8最重要的的特性之一。在以往,我们需要返回多个结果时,我们需要返回一个集合对象:
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
的支持,我们现在可以让Repository
方法返回一个Stream
对象:
public interface UserRepository extends JpaRepository<User, Integer> {
// ...
Stream<User> findAllByName(String name);
// ...
}
Spring Data 使用 特定提供的流式实现以传输结果。它减少了一定的内存调用和调用数据库的次数。正因为此,它比我们之前提到的两种方法要快得多。
在用流式API处理数据完要记得在使用完关闭它,可以通过调用Stream的close()
方法和使用try-with-resources
:
try (Stream<User> foundUsersStream = userRepository.findAllByName(USER_NAME_ADAM)) {
assertThat(foundUsersStream.count(), equalTo(3l));
}
此外此方法必须在一个事物中运行(异常了很清楚的说明了需要使用@Transactional(readOnly = true) )。不然我们会得到一个异常:
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.
4.CompletableFuture
Spring Data 存储仓库通过java 8 CompletableFuture 和Spring 异步执行的机制来支持异步运行:
@Async
CompletableFuture<User> findOneByStatus(Integer status);
调用此方法的客户端将立即返回一个future以继续完成接下来的业务逻辑,但方法将在不同的线程中继续执行。即不阻塞主线程。
更多关于CompletableFuture的信息可以访问此处
5.结论
在本教程中,我们展示了如何使用SpringData来使用Java 8的新特性。完整的代码可以在github上查阅。