共计 7718 个字符,预计需要花费 20 分钟才能阅读完成。
原题目:Spring 认证中国教育管理中心 -Spring Data Couchbase 教程五(Spring 中国教育管理中心)
Spring Data Couchbase 教程五
4.4.5 限度查问后果
您能够应用 firstortop 关键字来限度查询方法的后果,您能够调换应用它们。您能够将可选数值附加到 top 或 first 指定要返回的最大后果大小。如果省略该数字,则假设后果大小为 1。以下示例显示了如何限度查问大小:
示例 39. 应用 Topand 限度查问的后果大小 First
User findFirstByOrderByLastnameAsc();
User findTopByOrderByAgeDesc();
Page<User> queryFirst10ByLastname(String lastname, Pageable pageable);
Slice<User> findTop3ByLastname(String lastname, Pageable pageable);
List<User> findFirst10ByLastname(String lastname, Sort sort);
List<User> 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(短少 Iterable)以及间接….filter(…)和….map(…)笼罩元素并将其连贯 Streamable 到其余元素的能力:
示例 40. 应用 Streamable 组合查询方法后果
interface PersonRepository extends Repository<Person, Long> {
Streamable<Person> findByFirstnameContaining(String firstname);
Streamable<Person> findByLastnameContaining(String lastname);
}
Streamable<Person> result = repository.findByFirstnameContaining(“av”)
.and(repository.findByLastnameContaining(“ea”));
返回自定义 Streamable Wrapper 类型
为汇合提供专用的包装器类型是为返回多个元素的查问后果提供 API 的罕用模式。通常,通过调用返回相似汇合类型的存储库办法并手动创立包装器类型的实例来应用这些类型。您能够防止该额定步骤,因为 Spring Data 容许您将这些包装器类型用作查询方法返回类型,如果它们满足以下条件:
类型实现 Streamable.
的类型公开任一个结构或命名动态工厂法 of(…)或 valueOf(…)该取 Streamable 作为参数。
以下清单显示了一个示例:
class Product {
MonetaryAmount getPrice() { …}
}
@RequiredArgsConstructor(staticName = “of”)
class Products implements Streamable<Product> {
private final Streamable<Product> streamable;
public MonetaryAmount getTotal() {
return streamable.stream()
.map(Priced::getPrice)
.reduce(Money.of(0), MonetaryAmount::add);
}
@Override
public Iterator<Product> iterator() {
return streamable.iterator();
}
}
interface ProductRepository implements Repository<Product, Long> {
Products findAllByDescriptionContaining(String text);
}
一个 Product 裸露的 API 来拜访产品的价格实体。
Streamable<Product> 能够通过应用 Products.of(…)(应用 Lombok 正文创立的工厂办法)结构的包装器类型。采纳 Streamable<Product> 意志的规范构造函数也能够。
包装器类型公开了一个额定的 API,用于计算 Streamable<Product>.
实现 Streamable 接口并委托给理论后果。
该包装器类型 Products 能够间接用作查询方法返回类型。您不须要 Streamable<Product> 在存储库客户端中的查问之后返回并手动包装它。
Spring Data Couchbase 教程五
反对 Vavr 汇合
Vavr 是一个蕴含 Java 函数式编程概念的库。它附带一组自定义汇合类型,您能够将其用作查询方法返回类型,如下表所示:
Spring Data Couchbase 教程五
您能够将第一列(或其子类型)中的类型用作查询方法返回类型,并依据理论查问后果的 Java 类型(第三列)获取第二列中用作实现类型的类型。或者,您能够申明 Traversable(VavrIterable 等效项),而后咱们从理论返回值派生实现类。也就是说,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 如下例所示:
示例 41. 申明不可为空 package-info.java
@org.springframework.lang.NonNullApi
package com.acme;
一旦非空默认设置到位,存储库查询方法调用将在运行时验证可空性束缚。如果查问后果违反了定义的束缚,则会引发异样。当办法将返回 null 但被申明为不可为空(默认状况下,在存储库所在的包上定义正文)时,就会产生这种状况。如果您想再次抉择可空后果,请有选择地应用 @Nullable 单个办法。应用本节结尾提到的后果包装类型持续按预期工作:空后果被转换为示意缺席的值。
以下示例显示了刚刚形容的一些技术:
示例 42. 应用不同的可空性束缚
package com.acme;
import org.springframework.lang.Nullable;
interface UserRepository extends Repository<User, Long> {
User getByEmailAddress(EmailAddress emailAddress);
@Nullable
User findByEmailAddress(@Nullable EmailAddress emailAdress);
Optional<User> findOptionalByEmailAddress(EmailAddress emailAddress);
}
存储库位于咱们为其定义了非空行为的包(或子包)中。
EmptyResultDataAccessException 当查问不产生后果时抛出一个。IllegalArgumentException 当 emailAddress 交给办法时抛出一个 null。
null 当查问没有产生后果时返回。也承受 null 作为 的值 emailAddress。
Optional.empty()当查问没有产生后果时返回。IllegalArgumentException 当 emailAddress 交给办法时抛出一个 null。
Spring Data Couchbase 教程五
基于 Kotlin 的存储库中的可空性
Kotlin 将可空性束缚的定义融入到语言中。Kotlin 代码编译为字节码,它不通过办法签名表白可空性束缚,而是通过编译的元数据。确保 kotlin-reflect 在您的我的项目中蕴含 JAR 以启用对 Kotlin 可空性束缚的自省。Spring Data 存储库应用语言机制来定义这些束缚以利用雷同的运行时查看,如下所示:
示例 43. 在 Kotlin 存储库上应用可空性束缚
interface UserRepository : Repository<User, String> {
fun findByUsername(username: String): User
fun findByFirstname(firstname: String?): User?
}
该办法将参数和后果都定义为不可为空(Kotlin 默认)。Kotlin 编译器回绝传递 null 给办法的办法调用。如果查问产生空后果,
EmptyResultDataAccessException 则抛出 an。
该办法承受 null 的 firstname 参数,并返回 null,如果查问不产生后果。
4.4.8 流式查问后果
您能够应用 Java 8Stream<T> 作为返回类型以增量形式解决查询方法的后果。不是将查问后果包装在 a 中 Stream,而是应用特定于数据存储的办法来执行流式传输,如以下示例所示:
示例 44. 应用 Java 8 流式传输查问后果 Stream<T>
@Query(“select u from User u”)
Stream<User> findAllByCustomQueryAndStream();
Stream<User> readAllByFirstnameNotNull();
@Query(“select u from User u”)
Stream<User> streamAllPaged(Pageable pageable);
AStream 可能包装底层数据存储特定的资源,因而必须在应用后敞开。您能够 Stream 应用该 close()办法或应用 Java 7try-with-resources 块手动敞开,如以下示例所示:
示例 45. 解决块中的 Stream<T> 后果 try-with-resources
try (Stream<User> stream = repository.findAllByCustomQueryAndStream()) {
stream.forEach(…);
}
并非所有 Spring Data 模块以后都反对 Stream<T> 作为返回类型。
4.4.9 异步查问后果
您能够应用 Spring 的异步办法运行能力异步运行存储库查问。这意味着该办法在调用时立刻返回,而理论查问产生在已提交给 Spring 的工作中 TaskExecutor。异步查问与响应式查问不同,不应混用。无关响应式反对的更多详细信息,请参阅特定于商店的文档。以下示例显示了许多异步查问:
@Async
Future<User> findByFirstname(String firstname);
@Async
CompletableFuture<User> findOneByFirstname(String firstname);
@Async
ListenableFuture<User> 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 为您扫描的根本包,如以下示例所示:
示例 46. 通过 XML 启用 Spring Data 存储库
<?xml version=”1.0″ encoding=”UTF-8″?>
<beans:beans xmlns:beans=”http://www.springframework.org/schema/beans”
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.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/data/jpa
https://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
<repositories base-package=”com.acme.repositories” />
</beans:beans>
在后面的示例中,批示 Spring 扫描 com.acme.repositories 其所有子包以查找扩大接口 Repository 或其子接口之一。对于找到的每个接口,基础设施都会注册特定的持久性技术,FactoryBean 以创立适当的代理来解决查询方法的调用。每个 bean 都在从接口名称派生的 bean 名称下注册,因而接口 UserRepository 将在 userRepository. 嵌套存储库接口的 Bean 名称以它们的关闭类型名称为前缀。该 base-package 属性容许应用通配符,以便您能够定义扫描包的模式。
应用过滤器
默认状况下,基础设施会抉择扩大 Repository 位于已配置根本包下的特定于持久性技术的子接口的每个接口,并为其创立一个 bean 实例。然而,您可能心愿更细粒度地管制哪些接口具备为其创立的 bean 实例。为此,请在元素内应用 <include-filter /> 和 <exclude-filter /> 元素 <repositories />。语义齐全等同于 Spring 上下文命名空间中的元素。无关详细信息,请参阅这些元素的 Spring 参考文档。
例如,要从实例化中排除某些接口作为存储库 bean,您能够应用以下配置:
示例 47. 应用 exclude-filter 元素
<repositories base-package=”com.acme.repositories”>
<context:exclude-filter type=”regex” expression=”.*SomeRepository” />
</repositories>
后面的示例排除了所有以 SomeRepository 实例化结尾的接口。
4.5.2.Java 配置
您还能够通过 @Enable${store}Repositories 在 Java 配置类上应用特定于存储的正文来触发存储库根底构造。无关 Spring 容器的基于 Java 的配置的介绍,请参阅 Spring 参考文档中的 JavaConfig。
启用 Spring Data 存储库的示例配置相似于以下内容:
示例 48. 基于正文的存储库配置示例
@Configuration
@EnableJpaRepositories(“com.acme.repositories”)
class ApplicationConfiguration {
@Bean
EntityManagerFactory entityManagerFactory() {
// …
}
}
后面的示例应用特定于 JPA 的正文,您能够依据理论应用的存储模块对其进行更改。这同样实用于 EntityManagerFactorybean 的定义。请参阅涵盖商店特定配置的局部。
4.5.3. 独立应用
您还能够在 Spring 容器之外应用存储库基础架构——例如,在 CDI 环境中。您的类门路中依然须要一些 Spring 库,但通常您也能够通过编程形式设置存储库。提供存储库反对的 Spring Data 模块附带了特定 RepositoryFactory 于您能够应用的持久性技术,如下所示:
示例 49. 存储库工厂的独立应用
RepositoryFactorySupport factory = … // Instantiate factory here
UserRepository repository = factory.getRepository(UserRepository.class);