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