Spring中国教育管理中心-Apache Cassandra 的 Spring 数据教程九

2021-12-15 15:14:03 浏览数 (1)

11.3.2.查询选项

您可以通过传递QueryOptions对象来为查询方法指定查询选项。这些选项在实际查询执行之前应用于查询。 QueryOptions被视为非查询参数,不被视为查询参数值。查询选项适用于派生和字符串@Query存储库方法。

要静态设置一致性级别,请@Consistency在查询方法上使用注释。每次执行查询时都会应用声明的一致性级别。以下示例将一致性级别设置为 ConsistencyLevel.LOCAL_ONE:

代码语言:javascript复制
public interface PersonRepository extends CrudRepository<Person, String> {

    @Consistency(ConsistencyLevel.LOCAL_ONE)
    List<Person> findByLastname(String lastname);

    List<Person> findByFirstname(String firstname, QueryOptions options);
}

DataStax Cassandra 文档对可用的一致性级别进行了很好的讨论。

您可以控制在CQL API实例配置以下参数提取大小,一致性水平,重试策略的默认值:CqlTemplate,AsyncCqlTemplate,和ReactiveCqlTemplate。如果未设置特定查询选项,则应用默认值。

11.3.3.CDI集成

存储库接口的实例通常由容器创建,在使用 Spring Data 时,Spring 容器是最自然的选择。Spring Data for Apache Cassandra 附带一个自定义 CDI 扩展,允许在 CDI 环境中使用存储库抽象。该扩展是 JAR 的一部分。要激活它,请将 Spring Data for Apache Cassandra JAR 放入您的类路径中。您现在可以通过为 实现 CDI Producer 来设置基础结构 CassandraTemplate,如下面的示例所示:

代码语言:javascript复制
class CassandraTemplateProducer {

  @Produces
  @Singleton
  public CqlSession createSession() {
    return CqlSession.builder().withKeyspace("my-keyspace").build();
  }

  @Produces
  @ApplicationScoped
  public CassandraOperations createCassandraOperations(CqlSession session) throws Exception {

    CassandraMappingContext mappingContext = new CassandraMappingContext();
    mappingContext.setUserTypeResolver(new SimpleUserTypeResolver(session));
    mappingContext.afterPropertiesSet();

    MappingCassandraConverter cassandraConverter = new MappingCassandraConverter(mappingContext);
    cassandraConverter.afterPropertiesSet();

    return new CassandraAdminTemplate(session, cassandraConverter);
  }

  public void close(@Disposes CqlSession session) {
    session.close();
  }
}

Spring Data for Apache Cassandra CDI 扩展将CassandraOperations作为 CDI bean获取,并在容器请求存储库类型的 bean 时为 Spring Data 存储库创建代理。因此,获取 Spring Data 存储库的实例是声明注入属性的问题,如以下示例所示:

代码语言:javascript复制
class RepositoryClient {

  @Inject PersonRepository repository;

  public void businessMethod() {
    List<Person> people = repository.findAll();
  }
}

12. 反应式 Cassandra 存储库

本章概述了 Apache Cassandra 的反应式存储库支持所处理的特性。它建立在Cassandra Repositories 中解释的核心存储库基础设施之上,因此您应该对那里解释的基本概念有很好的理解。

Cassandra 存储库将ReactiveCassandraTemplate其ReactiveCqlTemplate用作基础设施 bean。

反应式使用分为两个阶段:组合和执行。

调用存储库方法可让您通过获取Publisher实例和应用运算符来组成反应式序列。在您订阅之前不会发生 I/O。将反应序列传递给反应执行基础设施,例如Spring WebFlux 或Vert.x),订阅发布者并启动实际执行。有关更多详细信息,请参阅项目反应器文档。

12.1.反应性组合物库

反应空间提供各种反应组合库。最常见的库是 RxJava和Project Reactor。

Spring Data for Apache Cassandra 建立在DataStax Cassandra Driver之上。驱动程序不是响应式的,但异步功能允许我们采用和公开PublisherAPI,通过依赖响应式流计划来提供最大的互操作性。静态 API,例如 ReactiveCassandraOperations,是通过使用 Project ReactorFlux和Mono类型提供的。工程反应堆提供各种适配器转换反应包装类(Flux以Observable和背面),但转换可以很容易搞乱你的代码。

Spring Data 的存储库抽象是一个动态 API,主要由您和您在声明查询方法时的需求定义。通过从特定于库的存储库接口之一进行扩展,可以使用 RxJava 或 Project Reactor 包装器类型来实现反应式 Cassandra 存储库:

  • ReactiveCrudRepository
  • ReactiveSortingRepository
  • RxJava2CrudRepository
  • RxJava2SortingRepository

Spring Data 在幕后转换反应式包装器类型,以便您可以坚持使用您最喜欢的组合库。

12.2.用法

要访问存储在 Apache Cassandra 中的域实体,您可以使用 Spring Data 复杂的存储库支持,这大大简化了 DAO 的实现。为此,请为您的存储库创建一个接口,如以下示例所示:

示例 89. 示例 Person 实体

代码语言:javascript复制
@Table
public class Person {

  @Id
  private String id;
  private String firstname;
  private String lastname;

  // … getters and setters omitted
}

请注意,该实体有一个名为idtype的属性String。中使用的默认序列化机制CassandraTemplate(支持存储库支持)将命名的属性id视为行 ID。

以下示例显示了用于持久化Person实体的存储库定义:

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

代码语言:javascript复制
public interface ReactivePersonRepository extends ReactiveSortingRepository<Person, Long> {

  Flux<Person> findByFirstname(String firstname);                                

  Flux<Person> findByFirstname(Publisher<String> firstname);                     

  Mono<Person> findByFirstnameAndLastname(String firstname, String lastname);    

  Mono<Person> findFirstByFirstname(String firstname);                           

  @AllowFiltering
  Flux<Person> findByAge(int age);                                               
}

对所有具有给定firstname. 查询是通过解析约束的方法名称来派生的,它可以与And和连接Or。因此,方法名称导致查询表达式为SELECT * FROM person WHERE firstname = :firstname。

一种给定所有的人查询firstname,一旦firstname从给定的发射Publisher。

查找给定条件的单个实体。以 IncorrectResultSizeDataAccessException非唯一结果完成。

与前面的查询不同,即使查询产生更多的结果行,也总是发出第一个实体。

用 注释的查询方法@AllowFiltering,允许服务器端过滤。

对于 Java 配置,请使用@ EnableReactiveCassandraRepositories注释。注释携带与相应 XML 命名空间元素相同的属性。如果没有配置基础包,基础设施会扫描带注释的配置类的包。以下示例使用了@EnableReactiveCassandraRepositories注释:

示例 91. 存储库的 Java 配置

代码语言:javascript复制
@Configuration
@EnableReactiveCassandraRepositories
class ApplicationConfig extends AbstractReactiveCassandraConfiguration {

  @Override
  protected String getKeyspaceName() {
    return "keyspace";
  }

  public String[] getEntityBasePackages() {
    return new String[] { "com.oreilly.springdata.cassandra" };
  }
}

由于我们的域存储库扩展了ReactiveSortingRepository,它为您提供了 CRUD 操作以及对实体进行排序访问的方法。使用存储库实例是将其依赖注入客户端的问题,如以下示例所示:

示例 92. 对 Person 实体的排序访问

代码语言:javascript复制
public class PersonRepositoryTests {

    @Autowired ReactivePersonRepository repository;

    @Test
    public void sortsElementsCorrectly() {
        Flux<Person> people = repository.findAll(Sort.by(new Order(ASC, "lastname")));
    }
}

Cassandra 存储库支持对实体进行分页和排序访问的分页和排序。Cassandra 分页需要分页状态才能向前浏览页面。ASlice跟踪当前的分页状态并允许创建一个Pageable请求下一页。以下示例显示如何设置对Person实体的分页访问:

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

代码语言:javascript复制
@RunWith(SpringRunner.class)
@ContextConfiguration
public class PersonRepositoryTests {

    @Autowired PersonRepository repository;

    @Test
    public void readsPagesCorrectly() {

      Mono<Slice<Person>> firstBatch = repository.findAll(CassandraPageRequest.first(10));

      Mono<Slice<Person>> nextBatch = firstBatch.flatMap(it -> repository.findAll(it.nextPageable()));

      // …
    }
}

前面的示例使用 Spring 的单元测试支持创建了一个应用程序上下文,它执行基于注解的依赖注入到测试类中。在测试用例(测试方法)中,我们使用存储库来查询数据存储。我们调用请求所有Person实例的存储库查询方法。

12.3.特征

Spring Data 的 Reactive Cassandra 支持与对命令式存储库的支持具有相同的功能集。

它支持以下功能:

  • 使用字符串查询和查询派生的查询方法
  • 预测

查询方法必须返回反应类型。不支持解析类型(Uservs Mono<User>)。

0 人点赞