1.概述
Spring Data现在支持核心Java 8功能 - 例如Optional,Stream API和CompletableFuture。
在这篇快速文章中,我们将通过一些示例来说明如何在框架中使用这些示例。
2. Optional
让我们从CRUD存储库方法开始 - 现在将结果包装在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还支持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提供程序 - 我们现在可以定义我们的存储库方法只返回一个对象Stream:
public interface UserRepository extends JpaRepository<User, Integer> {
// ...
Stream<User> findAllByName(String name);
// ...
}
Spring Data使用特定于提供程序的实现来传输结果(Hibernate使用ScrollableResultSet,EclipseLink使用ScrollableCursor)。它减少了内存消耗量和查询对数据库的调用。因此,它也比前面提到的两个解决方案快得多。
使用Stream处理数据需要我们在完成后关闭Stream。
可以通过在Stream上调用close()方法或使用try-with-resources来完成:
try (Stream<User> foundUsersStream
= userRepository.findAllByName(USER_NAME_ADAM)) {
assertThat(foundUsersStream.count(), equalTo(3l));
我们还必须记住在事务中调用存储库方法。否则,我们会得到一个例外:
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);
调用此方法的客户端将立即返回未来,但方法将继续在不同的线程中执行。