原标题:Spring认证中国教育管理中心-Spring Data R2DBC框架教程二(Spring中国教育管理中心

13.4.R2dbcEntityOperations 数据访问 API

R2dbcEntityTemplate是 Spring Data R2DBC 的中心入口点。它为典型的临时用例(例如查询、插入、更新和删除数据)提供了直接面向实体的方法和更窄、更流畅的接口。

入口点(insert()、select()、update()和其他)遵循基于要运行的操作的自然命名模式。从入口点开始,API 旨在仅提供依赖于上下文的方法,这些方法导致创建和运行 SQL 语句的终止方法。Spring Data R2DBC 使用R2dbcDialect抽象来确定绑定标记、分页支持和底层驱动程序本机支持的数据类型。

所有终端方法总是返回一个Publisher代表所需操作的类型。实际语句在订阅时发送到数据库。

13.4.1.插入和更新实体的方法

有几种方便的方法可R2dbcEntityTemplate用于保存和插入对象。为了对转换过程进行更细粒度的控制,您可以注册 Spring 转换器R2dbcCustomConversions ——例如Converter<Person, OutboundRow>和Converter<Row, Person>。

使用保存操作的简单情况是保存一个 POJO。在这种情况下,表名由类的名称(非完全限定)确定。您还可以使用特定的集合名称调用保存操作。您可以使用映射元数据来覆盖存储对象的集合。

插入或保存时,如果Id未设置该属性,则假设其值将由数据库自动生成。因此,对于自动生成,类中的Id属性或字段的类型必须是Long, 或Integer。

以下示例显示了如何插入一行并检索其内容:

示例 55. 使用 R2dbcEntityTemplate

Person person = new Person("John", "Doe");  Mono<Person> saved = template.insert(person); Mono<Person> loaded = template.selectOne(query(where("firstname").is("John")),     Person.class);

以下插入和更新操作可用:

也可以使用一组类似的插入操作:

  • Mono<T> insert (T objectToSave):将对象插入到默认表中。
  • Mono<T> 更新 (T objectToSave):将对象插入到默认表中。

可以使用 fluent API 自定义表名。

13.4.2.选择数据

的select(…)和selectOne(…)在方法R2dbcEntityTemplate被用来从表中选择的数据。这两种方法都采用一个Query定义字段投影、WHERE子句、ORDER BY子句和限制/偏移分页的对象。无论底层数据库如何,限制/偏移功能对应用程序都是透明的。R2dbcDialect抽象支持此功能以迎合各个 SQL 风格之间的差异。

示例 56. 使用 R2dbcEntityTemplate

Flux<Person> loaded = template.select(query(where("firstname").is("John")),     Person.class);

13.4.3.流利的API

本节解释了 fluent API 的用法。考虑以下简单查询:

Flux<Person> people = template.select(Person.class)      .all(); 

Person与select(…)方法一起使用将表格结果映射到Person结果对象上。

获取all()行返回一个Flux<Person>没有限制的结果。

以下示例声明了一个更复杂的查询,该查询按名称、WHERE条件和ORDER BY子句指定表名:

Mono<Person> first = template.select(Person.class)     .from("other_person")   .matching(query(where("firstname").is("John")          .and("lastname").in("Doe", "White"))     .sort(by(desc("id"))))                             .one();                                     

按名称从表中选择返回使用给定域类型的行结果。

发出的查询WHERE在firstname和lastname列上声明条件以过滤结果。

结果可以按单独的列名排序,从而产生一个ORDER BY子句。

选择一个结果只会获取一行。这种使用行的方式期望查询准确返回单个结果。

如果查询产生多个结果,则Mono发出 a

IncorrectResultSizeDataAccessException。

Spring认证中国教育管理中心-Spring Data R2DBC框架教程二_表名

您可以通过提供目标类型直接将投影应用于结果select(Class<?>)。

您可以通过以下终止方法在检索单个实体和检索多个实体之间切换:

  • first(): 只消费第一行,返回一个Mono. Mono如果查询没有返回结果,则返回完成而不发出对象。
  • one(): 只消耗一行,返回一个Mono. Mono如果查询没有返回结果,则返回完成而不发出对象。如果查询返回多于一行,则Mono异常完成发射IncorrectResultSizeDataAccessException。
  • all():使用所有返回的行返回一个Flux.
  • count():应用计数投影返回Mono<Long>。
  • exists(): 通过返回返回查询是否产生任何行Mono<Boolean>。

您可以使用select()入口点来表达您的SELECT查询。结果SELECT查询支持常用的子句(WHERE和ORDER BY)并支持分页。流畅的 API 风格让您可以将多个方法链接在一起,同时拥有易于理解的代码。为了提高可读性,您可以使用静态导入来避免使用“new”关键字来创建Criteria实例。

Criteria 类的方法

的Criteria类提供了以下的方法,所有这些都对应于SQL操作符:

  • Criteria and (String column) : 将一个Criteria与指定的链接添加property到当前Criteria并返回新创建的一个。
  • Criteria (String column):将Criteria指定的链添加property到当前Criteria并返回新创建的。
  • Criteria GreaterThan (Object o):使用>运算符创建条件。
  • Criteria GreaterThanOrEquals (Object o):使用>=运算符创建条件。
  • Criteria in (Object… o):通过IN对 varargs 参数使用运算符来创建条件。
  • Criteria in (Collection<?> collection):通过使用IN集合的运算符创建条件。
  • Criteria is (Object o):通过使用列匹配 ( property = value)创建一个条件。
  • Criteria isNull ():使用IS NULL运算符创建条件。
  • Criteria isNotNull ():使用IS NOT NULL运算符创建条件。
  • Criteria lessThan (Object o):使用<运算符创建条件。
  • Criteria lessThanOrEquals (Object o):使用⇐运算符创建条件。
  • Criteria like (Object o):通过使用LIKE运算符创建一个条件,而不进行转义字符处理。
  • Criteria not (Object o):使用!=运算符创建条件。
  • Criteria notIn (Object…​ o):通过NOT IN对 varargs 参数使用运算符来创建条件。
  • Criteria notIn (Collection<?> collection):通过使用NOT IN集合的运算符创建条件。

你可以用Criteria与SELECT,UPDATE和DELETE查询。

13.4.4.插入数据

您可以使用insert()入口点插入数据。

考虑以下简单的类型化插入操作:

Mono<Person> insert = template.insert(Person.class)      .using(new Person("John", "Doe")); 

Person与into(…)方法一起使用INTO根据映射元数据设置表。它还准备插入语句以接受Person要插入的对象。

提供一个标量Person对象。或者,您可以提供 aPublisher来运行INSERT语句流。此方法提取所有非null值并插入它们。

13.4.5.更新数据

您可以使用update()入口点来更新行。更新数据首先通过接受Update指定的分配来指定要更新的表。它还接受Query创建WHERE子句。

考虑以下简单的类型化更新操作:

Person modified = …      Mono<Integer> update = template.update(Person.class)           .inTable("other_table")                                    .matching(query(where("firstname").is("John")))            .apply(update("age", 42));                        

Person根据映射元数据更新对象并应用映射。

通过调用inTable(…)方法设置不同的表名。

指定转换为WHERE子句的查询。

应用Update对象。在这种情况下设置age为42并返回受影响的行数。

13.4.6.删除数据

您可以使用delete()入口点删除行。删除数据以要从中删除的表的规范开始,并且可以选择接受 aCriteria来创建WHERE子句。

考虑以下简单的插入操作:

    Mono<Integer> delete = template.delete(Person.class)           .from("other_table")                                       .matching(query(where("firstname").is("John")))            .all();                                           

删除Person对象并根据映射元数据应用映射。

通过调用from(…)方法设置不同的表名。

指定转换为WHERE子句的查询。

应用删除操作并返回受影响的行数。

14. R2DBC 存储库

本章指出了 R2DBC 存储库支持的特点。本章以使用 Spring Data Repositories 中解释的核心存储库支持为基础。在阅读本章之前,您应该对那里解释的基本概念有充分的了解。

14.1.用法

要访问存储在关系数据库中的域实体,您可以使用我们复杂的存储库支持,这大大简化了实施。为此,请为您的存储库创建一个界面。考虑以下Person类:

示例 57. 示例 Person 实体

public class Person {    @Id   private Long id;   private String firstname;   private String lastname;    // … getters and setters omitted }

以下示例显示了上述Person类的存储库接口:

示例 58. 用于持久化 Person 实体的基本存储库接口

public interface PersonRepository extends ReactiveCrudRepository<Person, Long> {    // additional custom query methods go here }

要配置 R2DBC 存储库,您可以使用@EnableR2dbcRepositories注释。如果没有配置基础包,基础设施会扫描带注释的配置类的包。以下示例显示了如何对存储库使用 Java 配置:

示例 59. 存储库的 Java 配置

@Configuration @EnableR2dbcRepositories class ApplicationConfig extends AbstractR2dbcConfiguration {    @Override   public ConnectionFactory connectionFactory() {     return …   } }

因为我们的域存储库扩展了ReactiveCrudRepository,它为您提供了访问实体的反应式 CRUD 操作。除此之外ReactiveCrudRepository,还有ReactiveSortingRepository,它添加了类似于 的附加排序功能

PagingAndSortingRepository。使用存储库实例只是将其依赖注入客户端的问题。因此,您可以Person使用以下代码检索所有对象:

示例 60. 对 Person 实体的分页访问

@ExtendWith(SpringExtension.class) @ContextConfiguration class PersonRepositoryTests {    @Autowired   PersonRepository repository;    @Test   void readsAllEntitiesCorrectly() {      repository.findAll()       .as(StepVerifier::create)       .expectNextCount(1)       .verifyComplete();   }    @Test   void readsEntitiesByNameCorrectly() {      repository.findByFirstname("Hello World")       .as(StepVerifier::create)       .expectNextCount(1)       .verifyComplete();   } }

Spring认证中国教育管理中心-Spring Data R2DBC框架教程二_2d_02

前面的示例使用 Spring 的单元测试支持创建了一个应用程序上下文,它将基于注解的依赖注入到测试用例中。在测试方法中,我们使用存储库来查询数据库。我们StepVerifier用作测试辅助工具来验证我们对结果的期望。