|
对于最新的稳定版本,请使用 Spring Data Cassandra 5.0.4! |
Cassandra 仓库
要访问存储在 Apache Cassandra 中的领域实体,您可以使用 Spring Data 提供的强大仓库支持,这将大大简化 DAO 的实现。 为此,请为您的仓库创建一个接口,如下例所示:
@Table
public class Person {
@Id
private String id;
private String firstname;
private String lastname;
// … getters and setters omitted
}
请注意,该实体有一个名为 id、类型为 String 的属性。
MappingCassandraConverter(为仓库支持提供底层实现)中使用的默认转换机制将名为 id 的属性视为行 ID。
以下示例展示了一个用于持久化 Person 实体的仓库定义:
Person 实体的基本仓库接口-
Imperative
-
Reactive
interface PersonRepository extends CrudRepository<Person, String> {
// additional custom finder methods go here
}
interface PersonRepository extends ReactiveCrudRepository<Person, String> {
// additional custom finder methods go here
}
目前,前面示例中的接口仅用于类型定义,但我们稍后会向其中添加更多方法。
接下来,在您的 Spring 配置中添加以下内容(如果您使用 Java 进行配置):
如果你想使用 Java 配置,请使用 @EnableCassandraRepositories 或相应的 @EnableReactiveCassandraRepositories 注解。
该注解所携带的属性与命名空间元素相同。
如果没有配置基础包,基础设施将扫描被注解的配置类所在的包。
以下示例展示了如何使用不同的配置方法:
-
Imperative Java Configuration
-
XML
-
Reactive Java Configuration
@Configuration
@EnableCassandraRepositories
class ApplicationConfig extends AbstractCassandraConfiguration {
@Override
protected String getKeyspaceName() {
return "keyspace";
}
public String[] getEntityBasePackages() {
return new String[] { "com.oreilly.springdata.cassandra" };
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:cassandra="http://www.springframework.org/schema/data/cassandra"
xsi:schemaLocation="
http://www.springframework.org/schema/data/cassandra
https://www.springframework.org/schema/data/cassandra/spring-cassandra.xsd
http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<cassandra:session port="9042" keyspace-name="keyspaceName"/>
<cassandra:mapping
entity-base-packages="com.acme..entities">
</cassandra:mapping>
<cassandra:converter/>
<cassandra:template/>
<cassandra:repositories base-package="com.acme..entities"/>
</beans>
@Configuration
@EnableReactiveCassandraRepositories
class ApplicationConfig extends AbstractReactiveCassandraConfiguration {
@Override
protected String getKeyspaceName() {
return "keyspace";
}
public String[] getEntityBasePackages() {
return new String[] { "com.oreilly.springdata.cassandra" };
}
}
cassandra:repositories 命名空间元素会扫描基础包中继承了 CrudRepository 的接口,并为每个找到的接口创建 Spring Bean。
默认情况下,这些仓库会与名为 CassandraTemplate 的 cassandraTemplate Spring Bean 进行装配,因此只有在不遵循此约定时,才需要显式配置
cassandra-template-ref。
由于我们的领域仓库分别扩展了 CrudRepository 或 ReactiveCrudRepository,因此它为您提供了基本的 CRUD 操作。
使用仓库实例只需将该仓库作为依赖项注入到客户端中,如下例所示,通过自动装配(autowiring)PersonRepository 来实现:
-
Imperative
-
Reactive
@ExtendWith(SpringExtension.class)
class PersonRepositoryTests {
@Autowired PersonRepository repository;
@Test
void readsPersonTableCorrectly() {
List<Person> persons = repository.findAll();
assertThat(persons.isEmpty()).isFalse();
}
}
public class PersonRepositoryTests {
@Autowired ReactivePersonRepository repository;
@Test
public void sortsElementsCorrectly() {
Flux<Person> people = repository.findAll(Sort.by(new Order(ASC, "lastname")));
}
}
Cassandra 仓库支持分页和排序,以实现对实体的分页和排序访问。
Cassandra 分页需要一个分页状态(paging state),以便仅能向前导航遍历各个页面。
Slice 会跟踪当前的分页状态,并允许创建一个 Pageable 来请求下一页。
以下示例展示了如何为 Person 实体设置分页访问:
Person 实体的分页访问-
Imperative
-
Reactive
@ExtendWith(SpringExtension.class)
class PersonRepositoryTests {
@Autowired PersonRepository repository;
@Test
void readsPagesCorrectly() {
Slice<Person> firstBatch = repository.findAll(CassandraPageRequest.first(10));
assertThat(firstBatch).hasSize(10);
Slice<Person> nextBatch = repository.findAll(firstBatch.nextPageable());
// …
}
}
@ExtendWith(SpringExtension.class)
class PersonRepositoryTests {
@Autowired PersonRepository repository;
@Test
void readsPagesCorrectly() {
Mono<Slice<Person>> firstBatch = repository.findAll(CassandraPageRequest.first(10));
Mono<Slice<Person>> nextBatch = firstBatch.flatMap(it -> repository.findAll(it.nextPageable()));
// …
}
}}
Cassandra 仓库不继承 PagingAndSortingRepository,因为在 Cassandra 中,使用 limit/offset 的经典分页模式并不适用。 |
前面的示例使用 Spring 的单元测试支持创建了一个应用上下文,该上下文会将基于注解的依赖注入到测试类中。
在测试用例(即测试方法)内部,我们使用仓库来查询数据存储。
我们调用了仓库的查询方法,该方法用于获取所有 Person 实例。
响应式存储库
Spring Data 的仓库抽象是一种动态 API,主要由您根据自身需求在声明查询方法时进行定义。 响应式 Cassandra 仓库可以通过扩展某个特定于库的仓库接口,并使用 RxJava 或 Project Reactor 的包装类型来实现:
-
ReactiveCrudRepository -
ReactiveSortingRepository -
RxJava3CrudRepository -
RxJava3SortingRepository
Spring Data 在后台自动转换响应式包装类型,使您可以继续使用您喜欢的组合库。