原题目:Spring认证|应用 Spring Data Repositories(中)起源:(Spring中国教育管理中心)
4.4.5. 限度查问后果
您能够应用first或top关键字来限度查询方法的后果,这两个关键字能够调换应用。您能够将一个可选的数值附加到top或first指定要返回的最大后果大小。如果疏忽该数字,则假设后果大小为 1。以下示例显示了如何限度查问大小:
示例 20. 应用Top和限度查问的后果大小First
User findFirstByOrderByLastnameAsc();
User findTopByOrderByAgeDesc();
Page queryFirst10ByLastname(String lastname, Pageable pageable);
Slice findTop3ByLastname(String lastname, Pageable pageable);
List findFirst10ByLastname(String lastname, Sort sort);
List findTop10ByLastname(String lastname, Pageable pageable);
限度表达式还反对Distinct反对不同查问的数据存储的关键字。此外,对于将后果集限度为一个实例的查问,Optional反对将后果用关键字包装。
如果分页或切片利用于限度查问分页(以及可用页数的计算),则在受限后果内利用。
通过应用Sort参数限度后果与动静排序相结合,您能够表白“K”最小元素和“K”最大元素的查询方法。
4.4.6. 返回汇合或可迭代对象的存储库办法
查询方法,返回多个后果能够应用规范的Java Iterable,List和Set。除此之外,咱们反对返回 Spring Data 的Streamable、 的自定义扩大Iterable以及Vavr提供的汇合类型。请参阅解释所有可能的查询方法返回类型的附录。
应用 Streamable 作为查询方法返回类型
您能够应用任何汇合类型的Streamable代替Iterable品。它提供了拜访非并行Stream(短少 from Iterable)的便捷办法,以及间接….filter(…)和….map(…)笼罩元素并将其连贯Streamable到其余元素的能力:
示例 21. 应用 Streamable 组合查询方法后果
interface PersonRepository extends Repository {
Streamable findByFirstnameContaining(String firstname);
Streamable findByLastnameContaining(String lastname);
}
Streamable result = repository.findByFirstnameContaining("av")
.and(repository.findByLastnameContaining("ea"));
返回自定义流包装器类型
为汇合提供专用包装器类型是一种罕用模式,用于为返回多个元素的查问后果提供 API。通常,通过调用存储库办法返回类汇合类型并手动创立包装器类型的实例来应用这些类型。您能够防止该额定步骤,因为 Spring Data 容许您将这些包装器类型用作查询方法返回类型,前提是它们满足以下条件:
类型实现Streamable.
的类型公开任一个结构或命名动态工厂法of(…)或valueOf(…)该取Streamable作为参数。
以下清单显示了一个示例:
class Product {
MonetaryAmount getPrice() { … }
}
@RequiredArgsConstructor(staticName = "of")
class Products implements Streamable {
private final Streamable streamable;
public MonetaryAmount getTotal() {
return streamable.stream()
.map(Priced::getPrice)
.reduce(Money.of(0), MonetaryAmount::add);
}
@Override
public Iterator iterator() {
return streamable.iterator();
}
}
interface ProductRepository implements Repository {
Products findAllByDescriptionContaining(String text);
}
一个Product裸露的API来拜访产品的价格实体。
Streamable能够通过应用Products.of(…)(应用 Lombok 正文创立的工厂办法)结构的的包装器类型。采纳Streamablewill 的规范构造函数也能够。
包装器类型公开了一个额定的 API,在Streamable.
实现Streamable接口并委托给理论后果。
该包装器类型Products能够间接用作查询方法返回类型。您不须要Streamable在存储库客户端中的查问之后返回并手动包装它。
反对 Vavr 汇合
Vavr是一个蕴含 Java 函数式编程概念的库。它附带一组自定义汇合类型,您能够将其用作查询方法返回类型,如下表所示:
您能够应用第一列(或其子类型)中的类型作为查询方法返回类型,并依据理论查问后果(第三列)的 Java 类型获取第二列中的类型作为实现类型。或者,您能够申明Traversable(Iterable相当于Vavr ),而后咱们从理论返回值派生实现类。也就是说, ajava.util.List变成了 VavrList或Seq, ajava.util.Set变成了 Vavr LinkedHashSet Set,依此类推。
4.4.7. 存储库办法的空解决
从 Spring Data 2.0 开始,返回单个聚合实例的存储库 CRUD 办法应用 Java 8Optional来批示可能短少值。除此之外,Spring Data 反对在查询方法上返回以下包装器类型:
com.google.common.base.Optional
scala.Option
io.vavr.control.Option
或者,查询方法能够抉择基本不应用包装器类型。而后通过返回来批示不存在查问后果null。返回汇合、汇合代替、包装器和流的存储库办法保障永远不会返回null,而是返回相应的空示意。无关详细信息,请参阅“存储库查问返回类型”。
可空性正文
您能够应用Spring Framework 的可空性正文来表白存储库办法的可空性束缚。它们null在运行时提供了一种工具敌对的办法和抉择退出查看,如下所示:
@NonNullApi: 在包级别上用于申明参数和返回值的默认行为别离是既不承受也不产生null值。
@NonNull: 用于不得为的参数或返回值null(在@NonNullApi实用的参数和返回值上不须要)。
@Nullable: 用于能够是的参数或返回值null。
Spring 正文应用JSR 305正文(一种休眠但宽泛应用的 JSR)进行元正文。JSR 305 元正文让工具供应商(例如IDEA、Eclipse和Kotlin)以通用形式提供空平安反对,而无需对 Spring 正文进行硬编码反对。要为查询方法启用可空性束缚的运行时查看,您须要应用 Spring 的@NonNullApiin在包级别激活非可空性package-info.java,如以下示例所示:
示例 22. 在 package-info.java
@org.springframework.lang.NonNullApi
package com.acme;
一旦非空默认设置到位,存储库查询方法调用将在运行时验证为可空性束缚。如果查问后果违反了定义的束缚,则抛出异样。当该办法将返回null但被申明为不可为空时(在存储库所在的包上定义的默认正文),就会产生这种状况。如果您想再次抉择可空后果,请有选择地应用@Nullable单个办法。应用本节结尾提到的后果包装器类型持续按预期工作:空后果被转换为示意不存在的值。
以下示例显示了刚刚形容的许多技术:
示例 23.应用不同的可空性束缚
package com.acme;
import org.springframework.lang.Nullable;
interface UserRepository extends Repository {
User getByEmailAddress(EmailAddress emailAddress);
@Nullable
User findByEmailAddress(@Nullable EmailAddress emailAdress);
Optional findOptionalByEmailAddress(EmailAddress emailAddress);
}
存储库驻留在咱们定义了非空行为的包(或子包)中。
EmptyResultDataAccessException当查问未产生后果时抛出。IllegalArgumentException当emailAddress传递给办法是时抛出null。
null当查问未产生后果时返回。也承受null作为 的值emailAddress。
Optional.empty()当查问未产生后果时返回。IllegalArgumentException当emailAddress传递给办法是时抛出null。
基于 Kotlin 的存储库中的可空性
Kotlin在语言中定义了可空性束缚。Kotlin 代码编译为字节码,它不通过办法签名而是通过编译元数据来表白可空性束缚。确保kotlin-reflect在您的我的项目中蕴含JAR 以启用对 Kotlin 的可空性束缚的内省。Spring Data 存储库应用语言机制来定义这些束缚以利用雷同的运行时查看,如下所示:
示例 24.在 Kotlin 存储库上应用可空性束缚
interface UserRepository : Repository {
fun findByUsername(username: String): User
fun findByFirstname(firstname: String?): User?
}
该办法将参数和后果都定义为不可为空(Kotlin 默认值)。Kotlin 编译器回绝传递null给办法的办法调用。如果查问产生空后果,EmptyResultDataAccessException则抛出an 。
该办法承受null的firstname参数,并返回null,如果查问不产生后果。
4.4.8. 流式查问后果
您能够应用 Java 8Stream作为返回类型以增量形式解决查询方法的后果。不是将查问后果包装在 a 中Stream,而是应用数据存储特定的办法来执行流式传输,如以下示例所示:
示例 25. 应用 Java 8 流式传输查问后果 Stream
@Query("select u from User u")
Stream findAllByCustomQueryAndStream();
Stream readAllByFirstnameNotNull();
@Query("select u from User u")
Stream streamAllPaged(Pageable pageable);
AStream潜在地包装了底层数据存储特定的资源,因而必须在应用后敞开。您能够Stream应用close()办法或应用 Java 7try-with-resources块手动敞开,如以下示例所示:
示例 26.Stream在try-with-resources块中处理结果
try (Stream stream = repository.findAllByCustomQueryAndStream()) {
stream.forEach(…);
}
并非所有 Spring Data 模块以后都反对Stream作为返回类型。
4.4.9. 异步查问后果
您能够应用Spring 的异步办法运行能力异步运行存储库查问。这意味着该办法在调用时立刻返回,而理论查问产生在已提交给 Spring 的工作中TaskExecutor。异步查问不同于反应式查问,不应混合应用。无关反应式反对的更多详细信息,请参阅商店特定的文档。以下示例显示了一些异步查问:
@Async
Future findByFirstname(String firstname);
@Async
CompletableFuture findOneByFirstname(String firstname);
@Async
ListenableFuture findOneByLastname(String lastname);
应用java.util.concurrent.Future作为返回类型。
应用 Java 8java.util.concurrent.CompletableFuture作为返回类型。
应用 aorg.springframework.util.concurrent.ListenableFuture作为返回类型。
4.5. 创立存储库实例
本节介绍如何为定义的存储库接口创立实例和 bean 定义。一种办法是应用反对存储库机制的每个 Spring Data 模块附带的 Spring 命名空间,只管咱们通常倡议应用 Java 配置。
4.5.1. XML 配置
每个 Spring Data 模块都蕴含一个repositories元素,可让您定义 Spring 为您扫描的根本包,如以下示例所示:
示例 27. 通过 XML 启用 Spring Data 存储库
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.o...
http://www.springframework.or...
https://www.springframework.o...d">
在后面的示例中,批示 Spring 扫描com.acme.repositories及其所有子包以查找扩大Repository的接口或其子接口之一。对于找到的每个接口,根底构造注册特定FactoryBean于持久性技术以创立解决查询方法调用的适当代理。每个 bean 都在从接口名称派生的 bean 名称下注册,因而 的接口UserRepository将在 下注册userRepository。嵌套存储库接口的 Bean 名称以其关闭的类型名称为前缀。该base-package属性容许应用通配符,以便您能够定义扫描包的模式。
应用过滤器
默认状况下,基础设施会抉择每个接口,这些接口扩大Repository位于配置的根本包下的持久性技术特定的子接口,并为其创立一个 bean 实例。然而,您可能心愿更精密地管制哪些接口为其创立了 bean 实例。为此,请在元素内应用和元素。语义齐全等同于 Spring 上下文命名空间中的元素。无关详细信息,请参阅这些元素的Spring 参考文档。
例如,要将某些接口从实例化中排除为存储库 bean,您能够应用以下配置:
示例 28. 应用 exclude-filter 元素
后面的示例排除了所有以SomeRepository实例化结尾的接口。
内容起源:(Spring中国教育管理中心)
应用 Spring Data Repositories,未完待续.....