此版本仍在开发中,尚不被认为是稳定的。对于最新的稳定版本,请使用 Spring Data Relational 3.5.2! |
持久化实体
保存聚合可以使用CrudRepository.save(…)
方法。
如果聚合是新的,则会导致聚合根的插入,然后是所有直接或间接引用的实体的插入语句。
如果聚合根不是新的,则删除所有引用的实体,更新聚合根,并再次插入所有引用的实体。 请注意,实例是否为新实例是实例状态的一部分。
这种方法有一些明显的缺点。 如果实际上只有少数引用的实体被更改,则删除和插入是浪费的。 虽然这个过程可以而且可能会得到改进,但 Spring Data JDBC 可以提供的功能存在某些限制。 它不知道聚合的先前状态。 因此,任何更新过程始终必须获取它在数据库中找到的任何内容,并确保将其转换为传递给 save 方法的实体的任何状态。 |
另请参阅实体状态检测以了解更多详细信息。
加载聚合
Spring Data JDBC 提供了两种加载聚合的方法:
-
传统的和 3.2 版本之前的唯一方法非常简单: 如果查询基于
CrudRepository
方法、派生查询或带注释的查询。 如果聚合根引用其他实体,则使用单独的语句加载这些实体。 -
Spring Data JDBC 3.2 允许使用单查询加载。 这样,可以使用单个 SQL 查询完全加载任意数量的聚合。 这应该会更加高效,特别是对于由许多实体组成的复杂聚合。
目前,单查询加载以不同的方式受到限制:
-
聚合不得具有嵌套集合,这包括
Map
. 计划在未来消除这一约束。 -
聚合不得使用
AggregateReference
或嵌入式实体。 计划在未来消除这一约束。 -
数据库方言必须支持它。在 Spring Data JDBC 提供的方言中,除了 H2 和 HSQL 之外,所有方言都支持此功能。 H2 和 HSQL 不支持分析函数(又名窗口函数)。
-
它仅适用于
CrudRepository
,不适用于派生查询,也不适用于带注释的查询。 计划在未来消除这一约束。 -
需要在
JdbcMappingContext
,通过调用setSingleQueryLoadingEnabled(true)
-
如果未满足任何条件,Spring Data JDBC 将回退到加载聚合的默认方法。
单查询加载应被视为实验性。 我们感谢有关它如何为您工作的反馈。 |
虽然单查询加载可以缩写为 SQL,但我们强烈建议不要这样做,因为几乎可以肯定会与结构化查询语言混淆。 |
ID 生成
Spring Data 使用标识符属性来标识实体。
也就是说,查找这些或创建针对特定行的语句。
实体的 ID 必须使用 Spring Data 的@Id
注解。
当数据库具有 ID 列的自动递增列时,生成的值将在将其插入数据库后在实体中设置。
如果另外使用@Sequence
如果基础Dialect
支持序列。
否则,当实体是新的并且标识符值默认为其初始值时,Spring Data不会尝试插入标识符列的值。 那是0
对于原始类型和null
如果 identifier 属性使用数字包装器类型,例如Long
.
实体状态检测详细解释了检测实体是新实体还是数据库中是否应存在的策略。
一个重要的约束是,在保存实体后,该实体不能再是新的。请注意,实体是否为新实体是实体状态的一部分。使用自动递增列,这是自动发生的,因为 ID 是由 Spring Data 使用 ID 列中的值设置的。
模板 API
作为存储库的替代方案,Spring Data JDBC 提供了JdbcAggregateTemplate
作为在关系数据库中加载和持久化实体的更直接的方法。在很大程度上,存储库使用JdbcAggregateTemplate
实现其功能。
本节仅重点介绍JdbcAggregateTemplate
. 有关更完整的概述,请参阅 JavaDocJdbcAggregateTemplate
.
访问 JdbcAggregateTemplate
JdbcAggregateTemplate
旨在用作 Spring bean。如果您已将应用程序设置为包含 Spring Data JDBC,则可以配置对JdbcAggregateTemplate
,并且 Spring Framework 会注入一个正确配置的实例。
这包括您用于为 Spring Data Repositories 实现自定义方法的片段,让您使用JdbcAggregateTemplate
以自定义和扩展存储库。
坚持
JdbcAggregateTemplate
提供三种类型的持久化实体方法:save
,insert
和update
. 每种都有两种类型:在单个聚合上运行,与上述名称完全相同,并使用All
后缀作Iterable
.
save
与存储库中同名的方法相同。
insert
和update
如果实体是新的,请跳过测试,并假设其名称所示为新的或现有的聚合。
查询
JdbcAggregateTemplate
提供了大量用于查询聚合和聚合集合的方法。有一种方法需要特别注意。这是采用Query
作为参数。它们允许执行以编程方式构造的查询,如下所示:
template.findOne(query(where("name").is("Gandalf")), Person.class);
这Query
由query
方法定义要选择的列列表、where 子句(通过 CriteriaDefinition)以及限制和偏移子句的指定。有关Query
类,请参阅其 JavaDoc。
这Criteria
类,其中where
是一个静态成员,提供 org.springframework.data.relational.core.query.CriteriaDefinition[] 的实现,它们表示查询的 where 子句。
Criteria类的方法
这Criteria
class 提供了以下方法,所有这些方法都对应于 SQL 运算符:
-
Criteria
和(String column)
:添加一个链式的Criteria
使用指定的property
到当前Criteria
并返回新创建的。 -
Criteria
或(String column)
:添加一个链式的Criteria
使用指定的property
到当前Criteria
并返回新创建的。 -
Criteria
大于(Object o)
:使用运算符创建条件。>
-
Criteria
大于或等于(Object o)
:使用运算符创建条件。>=
-
Criteria
在(Object… o)
:使用IN
varargs 参数的运算符。 -
Criteria
在(Collection<?> collection)
:使用IN
运算符。 -
Criteria
是(Object o)
:使用列匹配 (property = value
). -
Criteria
isNull :使用()
IS NULL
算子。 -
Criteria
isNotNull :使用()
IS NOT NULL
算子。 -
Criteria
小于(Object o)
:使用运算符创建条件。<
-
Criteria
小于或等于(Object o)
:使用⇐
算子。 -
Criteria
喜欢(Object o)
:使用LIKE
运算符,无需转义字符处理。 -
Criteria
不(Object o)
:使用!=
算子。 -
Criteria
notIn(Object… o)
:使用NOT IN
varargs 参数的运算符。 -
Criteria
notIn(Collection<?> collection)
:使用NOT IN
运算符。
乐观锁定
Spring Data 支持通过注释为@Version
在聚合根上。
每当 Spring Data 保存具有此类版本属性的聚合时,都会发生两件事:
-
聚合根的 update 语句将包含一个 where 子句,用于检查存储在数据库中的版本是否实际未更改。
-
如果不是这种情况,则
OptimisticLockingFailureException
将被扔出。
此外,在实体和数据库中都会增加 version 属性,因此并发作将注意到更改并抛出OptimisticLockingFailureException
如上所述,如果适用。
此过程也适用于插入新聚合,其中null
或0
version 表示一个新实例,之后增加的实例将该实例标记为不再是新的实例,这使得这在对象构造期间生成 ID 的情况(例如使用 UUID 时)工作得相当好。
在删除期间,版本检查也适用,但不会增加任何版本。