共计 6335 个字符,预计需要花费 16 分钟才能阅读完成。
原题目: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,未完待续 …..