|
此版本仍在开发中,尚未被视为稳定版本。如需最新稳定版本,请使用 Spring Data Cassandra 5.0.4! |
预先优化
本章介绍 Spring Data 的预编译(Ahead of Time,AOT)优化,这些优化基于Spring 的预编译优化。
运行时提示
与常规的 JVM 运行时相比,以原生镜像(native image)方式运行应用程序需要额外的信息。 Spring Data 在 AOT(提前编译)处理过程中会为原生镜像的使用提供运行时提示(Runtime Hints)。 这些提示尤其包括:
-
审计
-
ManagedTypes用于捕获类路径扫描的结果 -
仓库
-
实体、返回类型和 Spring Data 注解的反射提示
-
仓库片段
-
Querydsl
Q类 -
Kotlin 协程支持
-
-
Web 支持(针对
PagedModel的 Jackson 提示)
提前编译存储库
AOT 仓库是对 AOT 处理的一种扩展,通过预生成符合条件的查询方法实现。 对于开发者而言,查询方法在其调用时所执行的底层查询是不透明的。 AOT 仓库基于在构建时已知的派生查询、注解查询和命名查询,提供查询方法的实现。 此优化将查询方法的处理从运行时移至构建时,从而显著提升性能,因为应用程序每次启动时不再需要通过反射来分析查询方法。
生成的 AOT 仓库片段遵循 <Repository FQCN>Impl__Aot 的命名规则,并放置在与仓库接口相同的包中。
您可以在其中找到所有为生成的仓库查询方法所对应的字符串形式的查询语句。
| 请将AOT仓库类视为内部优化。 不要在您的代码中直接使用它们,因为生成方式和实现细节在未来版本中可能会发生变化。 |
使用 AOT 仓库运行
AOT 是将 Spring 应用程序转换为原生可执行文件的必要步骤,因此在此模式下运行时会自动启用。
当启用 AOT(无论是用于原生编译,还是通过设置 spring.aot.enabled=true)时,默认会自动启用 AOT 仓库。
你可以完全禁用 AOT 仓库生成,或者仅禁用 Cassandra AOT 仓库:
-
设置
spring.aot.repositories.enabled=false属性以禁用所有 Spring Data 模块的生成仓库。 -
设置
spring.aot.cassandra.repositories.enabled=false属性以仅禁用 Cassandra AOT 仓库。
AOT 仓库向实际的仓库 Bean 注册贡献配置更改,以注册生成的仓库片段。
| 当包含AOT(提前编译)优化时,一些在构建时做出的决策会被硬编码到应用程序的配置中。 例如,在构建时启用的配置文件(profiles)在运行时也会自动启用。 此外,实现仓库(repository)的Spring Data模块也被固定下来。 如需更改实现,必须重新进行AOT处理。 |
符合条件的
AOT 仓库会筛选出符合 AOT 处理条件的方法。 这些方法通常是所有未由实现片段支持的查询方法。
支持的功能
-
派生查询方法、
@Query以及命名查询方法。 -
Window、Slice、Stream和Optional返回类型 -
排序查询重写
-
接口和 DTO 投影
-
值表达式(这些需要一些反射信息。 请注意,使用值表达式需要进行表达式解析以及上下文信息来对表达式求值)
限制
-
尚未支持向量搜索
排除的方法
-
CrudRepository及其他基础接口的方法,其具体实现由各自的基础类片段提供 -
向量搜索方法
仓库元数据
AOT 处理会内省查询方法,并收集有关仓库查询的元数据。 Spring Data Cassandra 将这些元数据存储在 JSON 文件中,文件名与仓库接口相同,并与其存放在一起(即位于同一个包内)。 仓库 JSON 元数据包含有关查询和片段的详细信息。 以下展示了针对下列仓库的一个示例:
interface UserRepository extends CrudRepository<User, Integer> {
List<User> findUserNoArgumentsBy(); (1)
Slice<User> findSliceOfUsersByLastnameStartingWith(String lastname, Pageable page); (2)
@Query("select * from User where emailAddress = :emailAddress")
User findAnnotatedQueryByEmailAddress(String emailAddress); (3)
User findByEmailAddress(String emailAddress); (4)
}
| 1 | 无参数的派生查询。 |
| 2 | 使用分页的派生查询。 |
| 3 | 带注解的查询。 |
| 4 | 命名查询。 |
{
"name": "com.acme.UserRepository",
"module": "Cassandra",
"type": "IMPERATIVE",
"methods": [
{
"name": "findUserNoArgumentsBy",
"signature": "public abstract java.util.List<com.acme.User> com.acme.UserRepository.findUserNoArgumentsBy()",
"query": {
"query": "select * from user"
}
},
{
"name": "findSliceOfUsersByLastnameStartingWith",
"signature": "public abstract org.springframework.data.domain.Slice<com.acme.User> com.acme.UserRepository.findSliceOfUsersByLastnameStartingWith(java.lang.String,org.springframework.data.domain.Pageable)",
"query": {
"query": "select * from user where lastname like ?"
}
},
{
"name": "findAnnotatedQueryByEmailAddress",
"signature": "public abstract com.acme.User com.acme.UserRepository.findAnnotatedQueryByEmailAddress(java.lang.String)",
"query": {
"query": "select * from user where emailaddress = ?"
}
},
{
"name": "findByEmailAddress",
"signature": "public abstract com.acme.User com.acme.UserRepository.findByEmailAddress(java.lang.String)",
"query": {
"name": "User.findByEmailAddress",
"query": "select * from user where emailaddress = ?"
}
},
{
"name": "count",
"signature": "public abstract long org.springframework.data.repository.CrudRepository.count()",
"fragment": {
"fragment": "org.springframework.data.cassandra.repository.support.SimpleCassandraRepository"
}
}
]
}
查询可能包含以下字段:
-
query:如果该方法是一个查询方法,则为查询描述符。-
query用于获取查询方法结果的查询语句。 -
name:如果查询是一个命名查询,则为该命名查询的名称。
-
-
fragment:如果方法调用被委托给一个存储库(repository 基类、函数式片段如 Querydsl)或用户自定义片段,则此为对应的目标片段。 如果没有其他接口,片段仅用fragment表示;如果存在接口(例如 Querydsl 或用户声明的片段接口),则片段以interface和fragment的元组形式描述。
|
标准化查询表单
对查询的静态分析仅能有限地表示运行时查询行为。 查询以其规范化(预解析并重写)的形式表示:
|