8. 简介
参考文档的这一部分解释了 Spring Data for Apache Cassandra 提供的核心功能。
Cassandra Support 引入了 Cassandra模块功能集。
反应式 Cassandra 支持解释了反应式 Cassandra 的细节。
Cassandra存储库引入了对 Cassandra 的存储库支持。
8.1. Apache Cassandra 模块的 Spring CQL 和 Spring Data
Apache Cassandra 的 Spring Data 允许在 CQL 和实体级别进行交互。
Spring Data 为 Apache Cassandra 抽象提供的价值可能最好地通过下表中概述的操作序列来显示。 该表显示了 Spring 会处理哪些操作,哪些操作是您(应用程序开发人员)的责任。
表 2.Apache Cassandra 的 Spring Data (CQL Core) - 谁做什么?
行动 | 春天 | 你 |
定义连接参数。 | X | |
打开连接。 | X | |
指定 CQL 语句。 | X | |
声明参数并提供参数值 | X | |
准备并运行语句。 | X | |
设置循环以循环访问结果(如果有)。 | X | |
完成每次迭代的工作。 | X | |
处理任何异常。 | X | |
关闭会话。 | X |
核心 CQL 支持负责所有低级细节,这些细节可能使 Cassandra 和 CQL 成为如此繁琐的开发 API。 使用映射的实体对象允许架构生成、对象映射和存储库支持。
8.1.1. 选择 Cassandra 数据库访问的方法
您可以在几种方法中进行选择,以用作访问 Cassandra 数据库的基础。 Spring对Apache Cassandra的支持有不同的风格。 开始使用其中一种方法后,您仍然可以混合搭配以包含来自不同方法的功能。 以下方法效果很好:
- CqlTemplate和ReactiveCqlTemplate是经典的 Spring CQL 方法,也是最流行的。 这是“最低级别”的方法。 请注意,组件喜欢在引擎盖下使用。CassandraTemplateCqlTemplate
- CassandraTemplate包装 ato 提供查询结果到对象的映射和使用 ,,, 和方法,而不是编写 CQL 语句。 这种方法提供了更好的文档和易用性。CqlTemplateSELECTINSERTUPDATEDELETE
- ReactiveCassandraTemplate包装 ato 提供查询结果到对象的映射和使用 ,,, 和方法,而不是编写 CQL 语句。 这种方法提供了更好的文档和易用性。
ReactiveCqlTemplate
SELECT
INSERT
UPDATE
DELETE
- 存储库抽象允许您在数据访问层中创建存储库声明。 Spring Data 存储库抽象的目标是显着减少为各种持久性存储实现数据访问层所需的样板代码量。
9. 升级弹簧数据
有关如何从早期版本的 Spring 数据升级的说明在项目wiki 上提供。 按照发行说明部分中的链接查找要升级到的版本。
升级说明始终是发行说明中的第一项。如果您落后多个版本,请确保您还查看了您跳转的版本的发行说明。
9.1. 接下来要读什么
决定升级应用程序后,可以在文档的其余部分找到有关特定功能的详细信息。 您可以在本文档末尾找到特定于主要版本迁移的迁移指南。
Spring Data 的文档特定于该版本,因此您在此处找到的任何信息都将包含该版本中的最新更改。
10. 卡桑德拉支持
Spring Data 对 Apache Cassandra 的支持包含广泛的功能:
- Spring 配置支持基于 Java 的类或 XML 命名空间。
@Configuration
- 通过正确处理常见的 Cassandra 数据访问操作来提高工作效率的帮助程序类。
CqlTemplate
- 在 CQL 表和 POJO 之间提供对象映射的帮助程序类。
CassandraTemplate
- 将异常转换为 Spring 的可移植数据访问异常层次结构。
- 功能丰富的对象映射与 Spring 的转换服务集成。
- 可扩展以支持其他元数据格式的基于批注的映射元数据。
- 基于 Java 的查询、条件和更新 DSL。
- 自动实现接口,包括对自定义查找器方法的支持。
Repository
对于大多数面向数据的任务,您可以使用理论或支持,这两者都使用丰富的对象映射 functionality.is 通常用于递增计数器或执行即席 CRUD 操作。还提供了回调方法,可以轻松获取低级 API 对象,例如,允许您直接与 Cassandra 通信。 Spring Data for Apache Cassandra 对各种 API 中的对象使用与 DataStax Java 驱动程序中一致的命名约定,以便它们熟悉,以便您可以将现有知识映射到 Spring API 上。CassandraTemplate
Repository
CqlTemplate
CqlTemplate
com.datastax.oss.driver.api.core.CqlSession
10.1. 入门
Spring Data for Apache Cassandra 需要 Apache Cassandra 2.1 或更高版本和 Datastax Java Driver 4.0 或更高版本。 快速设置和引导工作环境的一种简单方法是在STS中创建基于 Spring 的项目或使用Spring 初始值设定项。
首先,您需要设置一个正在运行的 Apache Cassandra 服务器。 请参阅 Apache Cassandra快速入门指南,了解如何启动 Apache Cassandra的说明。 安装后,启动 Cassandra 通常是执行以下命令的问题:CASSANDRA_HOME/bin/cassandra -f
要在 STS 中创建 Spring 项目,请转到“新建→ Spring 模板项目→文件”→“简单 Spring 实用程序项目”,并在出现提示时按“是”。 然后输入项目和包名称,例如。org.spring.data.cassandra.example
然后,您可以将以下依赖项声明添加到pom.xml文件的部分中。dependencies
<dependencies>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-cassandra</artifactId>
<version>4.0.0</version>
</dependency>
</dependencies>
另外,您应该将pom.xml文件中的Spring版本更改为如下:
<spring.framework.version>6.0.0</spring.framework.version>
如果使用里程碑版本而不是 GA 版本,您还需要将 Maven 的 Spring 里程碑存储库的位置添加到您的 pom.xml 文件中,以便它与 yourelement 处于同一级别,如下所示:<dependencies/>
<repositories>
<repository>
<id>spring-milestone</id>
<name>Spring Maven MILESTONE Repository</name>
<url>https://repo.spring.io/libs-milestone</url>
</repository>
</repositories>
存储库也可以在此处浏览。
您还可以在此处浏览所有 Spring 存储库。
现在,您可以创建一个简单的 Java 应用程序,用于存储和读取 Cassandra 的域对象。
为此,请首先创建一个要保留的简单域对象类,如以下示例所示:
package org.springframework.data.cassandra.example;
@Table
public class Person {
@PrimaryKey private final String id;
private final String name;
private final int age;
public Person(String id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
public String getId() {
return id;
}
private String getName() {
return name;
}
private int getAge() {
return age;
}
@Override
public String toString() {
return String.format("{ @type = %1$s, id = %2$s, name = %3$s, age = %4$d }", getClass().getName(), getId(),
getName(), getAge());
}
}
接下来,创建要运行的主应用程序,如以下示例所示:
package org.springframework.data.cassandra.example;
public class CassandraApplication {
private static final Log LOG = LogFactory.getLog(CassandraApplication.class);
private static Person newPerson(String name, int age) {
return new Person(UUID.randomUUID().toString(), name, age);
}
public static void main(String[] args) {
CqlSession cqlSession = CqlSession.builder().withKeyspace("mykeyspace").build();
CassandraOperations template = new CassandraTemplate(cqlSession);
Person jonDoe = template.insert(newPerson("Jon Doe", 40));
LOG.info(template.selectOne(Query.query(Criteria.where("id").is(jonDoe.getId())), Person.class).getId());
template.truncate(Person.class);
cqlSession.close();
}
}
即使在这个简单的例子中,也有一些值得注意的事情需要指出:
- 您可以创建 的实例 与 Cassandra。
CassandraTemplate
CqlSession
- 您必须将 POJO 注释为 Cassandraentity,并对其进行注释。 (可选)您可以覆盖这些映射名称以匹配 Cassandra 数据库表名和列名。
@Table
@PrimaryKey
- 可以使用原始 CQL 或 DataStaxAPI 来构造查询。
QueryBuilder
10.2. 示例存储库
要了解库的工作原理,您可以下载并试用几个示例。 .
10.3. 用弹簧连接到卡桑德拉
将Apache Cassandra与Spring一起使用时,首要任务之一是使用Spring IoC容器创建对象。 您可以通过使用基于 Java 的 Bean 元数据或使用基于 XML 的 Bean 元数据来执行此操作。 以下各节将讨论这些内容。com.datastax.oss.driver.api.core.CqlSession
对于那些不熟悉如何使用基于 Java 的 Bean 元数据而不是基于 XML 的元数据来配置 Spring 容器的人,请参阅此处参考文档中的高级介绍以及此处的详细文档。 |
10.3.1. 使用基于 Java 的元数据注册会话实例
以下示例演示如何使用基于 Java 的 Bean 元数据来注册 的实例:com.datastax.oss.driver.api.core.CqlSession
例 52。使用基于 Java 的 Bean 元数据注册对象com.datastax.oss.driver.api.core.CqlSession
@Configuration
public class AppConfig {
/*
* Use the standard Cassandra driver API to create a com.datastax.oss.driver.api.core.CqlSession instance.
*/
public @Bean CqlSession session() {
return CqlSession.builder().withKeyspace("mykeyspace").build();
}
}
此方法允许您使用您可能已经知道的标准 API。com.datastax.oss.driver.api.core.CqlSession
另一种方法是使用 Spring 的容器注册一个实例。 与直接实例化实例相比,该方法还有一个额外的优势,即还为容器提供了一个实现,可以将 Cassandra 异常转换为 Spring 可移植层次结构中的异常。 这种层次结构和用法在Spring 的 DAO 支持功能中进行了描述。com.datastax.oss.driver.api.core.CqlSession
CqlSessionFactoryBean
com.datastax.oss.driver.api.core.CqlSession
FactoryBean
ExceptionTranslator
DataAccessException
@Repository
以下示例显示了基于 Java 的工厂类用法:
例 53。使用 Spring 的注册 com.datastax.oss.driver.api.core.CqlSession 对象:CqlSessionFactoryBean
@Configuration
public class FactoryBeanAppConfig {
/*
* Factory bean that creates the com.datastax.oss.driver.api.core.CqlSession instance
*/
@Bean
public CqlSessionFactoryBean session() {
CqlSessionFactoryBean session = new CqlSessionFactoryBean();
session.setContactPoints("localhost");
session.setKeyspaceName("mykeyspace");
return session;
}
}
使用对象映射和存储库支持需要,,,并启用存储库支持。CassandraTemplate
CassandraTemplate
CassandraMappingContext
CassandraConverter
以下示例演示如何注册组件以配置对象映射和存储库支持:
例 54。注册组件以配置对象映射和存储库支持
@Configuration
@EnableCassandraRepositories(basePackages = { "org.springframework.data.cassandra.example" })
public class CassandraConfig {
@Bean
public CqlSessionFactoryBean session() {
CqlSessionFactoryBean session = new CqlSessionFactoryBean();
session.setContactPoints("localhost");
session.setKeyspaceName("mykeyspace");
return session;
}
@Bean
public SessionFactoryFactoryBean sessionFactory(CqlSession session, CassandraConverter converter) {
SessionFactoryFactoryBean sessionFactory = new SessionFactoryFactoryBean();
sessionFactory.setSession(session);
sessionFactory.setConverter(converter);
sessionFactory.setSchemaAction(SchemaAction.NONE);
return sessionFactory;
}
@Bean
public CassandraMappingContext mappingContext(CqlSession cqlSession) {
CassandraMappingContext mappingContext = new CassandraMappingContext();
mappingContext.setUserTypeResolver(new SimpleUserTypeResolver(cqlSession));
return mappingContext;
}
@Bean
public CassandraConverter converter(CassandraMappingContext mappingContext) {
return new MappingCassandraConverter(mappingContext);
}
@Bean
public CassandraOperations cassandraTemplate(SessionFactory sessionFactory, CassandraConverter converter) {
return new CassandraTemplate(sessionFactory, converter);
}
}
创建为 Apache Cassandra 组件注册 Spring 数据的配置类可能是一个令人筋疲力尽的挑战,因此 Spring Data for Apache Cassandra 附带了一个预构建的配置支持类。 从 Spring Data 的 Register bean 扩展的类 用于 Apache Cassandra 使用。允许您提供各种配置选项,例如初始实体、默认查询选项、池化选项、套接字选项等等。还支持基于初始实体(如果有)生成模式。 扩展自要求您至少通过实现方法提供密钥空间名称。 下面的示例演示如何使用以下命令注册 Bean:AbstractCassandraConfiguration
AbstractCassandraConfiguration
AbstractCassandraConfiguration
AbstractCassandraConfiguration
getKeyspaceName
AbstractCassandraConfiguration
例 55。使用 注册 Apache Cassandra 豆的春季数据AbstractCassandraConfiguration
@Configuration
public class CassandraConfiguration extends AbstractCassandraConfiguration {
/*
* Provide a contact point to the configuration.
*/
public String getContactPoints() {
return "localhost";
}
/*
* Provide a keyspace name to the configuration.
*/
public String getKeyspaceName() {
return "mykeyspace";
}
}
10.3.2.XML 配置
本节介绍如何使用 XML 配置 Spring Data Cassandra。
外部化连接属性
若要外部化连接属性,应首先创建一个属性文件,其中包含连接到 Cassandra.和必填字段所需的信息。contactpoints
keyspace
以下示例显示了我们的属性文件,称为:cassandra.properties
cassandra.contactpoints=10.1.55.80:9042,10.1.55.81:9042
cassandra.keyspace=showcase
在接下来的两个示例中,我们使用 Spring 将这些属性加载到 Spring 上下文中。
使用基于 XML 的元数据注册会话实例
虽然您可以使用 Spring 的传统 XML 命名空间来注册容器的实例,但 XML 可能非常冗长,因为它是通用的。 XML 命名空间是配置常用对象(如实例)的更好替代方法。 命名空间允许您创建一个实例。<beans/>
com.datastax.oss.driver.api.core.CqlSession
CqlSession
cassandra
CqlSession
以下示例演示如何配置命名空间:cassandra
例 56。使用命名空间配置 Cassandra 的 XML 架构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">
<!-- Default bean name is 'cassandraSession' -->
<cassandra:session contact-points="localhost" port="9042">
<cassandra:keyspace action="CREATE_DROP" name="mykeyspace" />
</cassandra:session>
<cassandra:session-factory>
<cassandra:script
location="classpath:/org/springframework/data/cassandra/config/schema.cql"/>
</cassandra:session-factory>
</beans>
更高级的 Cassandra 配置的 XML 配置元素如下所示。 这些元素都使用缺省 Bean 名称来保持配置代码干净且可读。
虽然前面的例子显示了配置 Spring 以连接到 Cassandra 是多么容易,但还有许多其他选项。 基本上,DataStax Java Driver 提供的任何选项也可以在 Spring Data for Apache Cassandra 配置中使用。 这包括但不限于身份验证、负载平衡策略、重试策略和池选项。 Apache Cassandra 方法名称和 XML 元素的所有 Spring 数据都像驱动程序上的配置选项一样精确(或尽可能接近)命名,因此映射任何现有的驱动程序配置应该是直接的。 下面的示例演示如何使用 XML 配置 Spring 数据组件
例 57。使用 XML 配置 Spring 数据组件
<!-- Loads the properties into the Spring Context and uses them to fill
in placeholders in the bean definitions -->
<context:property-placeholder location="classpath:cassandra.properties" />
<!-- REQUIRED: The Cassandra Session -->
<cassandra:session contact-points="${cassandra.contactpoints}" keyspace-name="${cassandra.keyspace}" />
<!-- REQUIRED: The default Cassandra mapping context used by `CassandraConverter` -->
<cassandra:mapping>
<cassandra:user-type-resolver keyspace-name="${cassandra.keyspace}" />
</cassandra:mapping>
<!-- REQUIRED: The default Cassandra converter used by `CassandraTemplate` -->
<cassandra:converter />
<!-- REQUIRED: The Cassandra template is the foundation of all Spring
Data Cassandra -->
<cassandra:template id="cassandraTemplate" />
<!-- OPTIONAL: If you use Spring Data for Apache Cassandra repositories, add
your base packages to scan here -->
<cassandra:repositories base-package="org.spring.cassandra.example.repo" />
10.4. 模式管理
Apache Cassandra 是一个数据存储,在任何数据交互之前都需要架构定义。 Spring Data for Apache Cassandra 可以支持您创建模式。
10.4.1. 密钥空间和生命周期脚本
首先要开始的是Cassandra密钥空间。 键空间是共享相同复制因子和复制策略的表的逻辑分组。 密钥空间管理位于配置中,它具有启动和关闭CQL脚本执行。CqlSession
KeyspaceSpecification
使用规范声明密钥空间允许创建和删除密钥空间。 它从规范派生 CQL,因此您无需自己编写 CQL。 下面的示例使用 XML 指定 Cassadra 密钥空间:
例 58。指定 Cassandra 密钥空间
爪哇岛
.XML
@Configuration
public class CreateKeyspaceConfiguration extends AbstractCassandraConfiguration implements BeanClassLoaderAware {
@Override
protected List<CreateKeyspaceSpecification> getKeyspaceCreations() {
CreateKeyspaceSpecification specification = CreateKeyspaceSpecification.createKeyspace("my_keyspace")
.with(KeyspaceOption.DURABLE_WRITES, true)
.withNetworkReplication(DataCenterReplication.of("foo", 1), DataCenterReplication.of("bar", 2));
return Arrays.asList(specification);
}
@Override
protected List<DropKeyspaceSpecification> getKeyspaceDrops() {
return Arrays.asList(DropKeyspaceSpecification.dropKeyspace("my_keyspace"));
}
// ...
}
密钥空间创建允许快速引导,而无需外部密钥空间管理。 这对于某些方案可能很有用,但应谨慎使用。 在应用程序关闭时删除密钥空间会从密钥空间中的表中删除密钥空间和所有数据。 |
10.4.2. 初始化SessionFactory
该包支持初始化现有。 有时可能需要初始化在某处服务器上运行的密钥空间。org.springframework.data.cassandra.core.cql.session.init
SessionFactory
初始化密钥空间
您可以在配置的密钥空间中提供在初始化和关闭时执行的任意 CQL,如以下 Java 配置示例所示:CqlSession
爪哇岛
.XML
@Configuration
public class KeyspacePopulatorConfiguration extends AbstractCassandraConfiguration {
@Nullable
@Override
protected KeyspacePopulator keyspacePopulator() {
return new ResourceKeyspacePopulator(new ClassPathResource("com/foo/cql/db-schema.cql"),
new ClassPathResource("com/foo/cql/db-test-data.cql"));
}
@Nullable
@Override
protected KeyspacePopulator keyspaceCleaner() {
return new ResourceKeyspacePopulator(scriptOf("DROP TABLE my_table;"));
}
// ...
}
前面的示例针对密钥空间运行两个指定的脚本。 第一个脚本创建架构,第二个脚本使用测试数据集填充表。 脚本位置也可以是带有通配符的模式,通常用于 Spring 中的资源(例如,)。 如果使用模式,脚本将按其 URL 或文件名的词法顺序运行。classpath*:/com/foo/**/cql/*-data.cql
密钥空间初始值设定项的默认行为是无条件运行提供的脚本。 这可能并不总是您想要的 — 例如,如果您针对已包含测试数据的密钥空间运行脚本。 通过遵循先创建表然后插入数据的常见模式(如前所示),可以降低意外删除数据的可能性。 如果表已存在,第一步将失败。
但是,为了更好地控制现有数据的创建和删除,XML 命名空间提供了一些其他选项。 第一个是用于打开和关闭初始化的标志。 您可以根据环境进行设置(例如,从系统属性或环境 Bean 中提取布尔值)。 下面的示例从系统属性中获取值:
<cassandra:initialize-keyspace session-factory-ref="cassandraSessionFactory"
enabled="#{systemProperties.INITIALIZE_KEYSPACE}">
<cassandra:script location="..."/>
</cassandra:initialize-database>
从调用的系统属性中获取值。 |
控制现有数据发生的情况的第二个选项是更容忍故障。 为此,可以控制初始值设定项忽略它从脚本执行的 CQL 中的某些错误的能力,如以下示例所示:
爪哇岛
.XML
@Configuration
public class KeyspacePopulatorFailureConfiguration extends AbstractCassandraConfiguration {
@Nullable
@Override
protected KeyspacePopulator keyspacePopulator() {
ResourceKeyspacePopulator populator = new ResourceKeyspacePopulator(
new ClassPathResource("com/foo/cql/db-schema.cql"));
populator.setIgnoreFailedDrops(true);
return populator;
}
// ...
}
在前面的示例中,我们说我们期望有时脚本针对空键空间运行,因此脚本中的某些语句会失败。 因此,失败的 CQL 语句将被忽略,但其他失败将导致异常。 如果您不想使用 tu 使用支持(或类似),但希望在重新创建之前无条件删除所有测试数据,这将非常有用。 在这种情况下,第一个脚本通常是一组语句,后跟一组语句。DROP
DROP
DROP … IF EXISTS
DROP
CREATE
该选项可以设置为(默认值)、(忽略失败的丢弃)或(忽略所有失败)。ignore-failures
NONE
DROPS
ALL
如果脚本中根本不存在字符,则应用新行分隔每个语句或换行符。 您可以全局控制它,也可以逐个脚本进行控制,如以下示例所示:;
;
爪哇岛
.XML
@Configuration
public class SessionFactoryInitializerConfiguration extends AbstractCassandraConfiguration {
@Bean
SessionFactoryInitializer sessionFactoryInitializer(SessionFactory sessionFactory) {
SessionFactoryInitializer initializer = new SessionFactoryInitializer();
initializer.setSessionFactory(sessionFactory);
ResourceKeyspacePopulator populator1 = new ResourceKeyspacePopulator();
populator1.setSeparator(";");
populator1.setScripts(new ClassPathResource("com/myapp/cql/db-schema.cql"));
ResourceKeyspacePopulator populator2 = new ResourceKeyspacePopulator();
populator2.setSeparator("@@");
populator2.setScripts(new ClassPathResource("classpath:com/myapp/cql/db-test-data-1.cql"), //
new ClassPathResource("classpath:com/myapp/cql/db-test-data-2.cql"));
initializer.setKeyspacePopulator(new CompositeKeyspacePopulator(populator1, populator2));
return initializer;
}
// ...
}
在此示例中,twoscripts 使用 as 语句分隔符,并且仅使用theuses。 此配置指定默认分隔符 isand 覆盖脚本的默认值。test-data
@@
db-schema.cql
;
@@
db-schema
如果您需要比从 XML 命名空间获得的更多的控制,则可以直接使用并将其定义为应用程序中的组件。SessionFactoryInitializer
依赖于密钥空间的其他组件的初始化
一大类应用程序(那些在 Spring 上下文启动之前不使用数据库的应用程序)可以使用数据库初始值设定项,而不会进一步复杂化。 如果您的应用程序不是其中之一,则可能需要阅读本节的其余部分。
数据库初始值设定项依赖于 ainstance 并运行其初始化回调中提供的脚本(类似于 XML Bean 定义中的 an、组件中的方法或实现组件中的方法)。 如果其他 Bean 依赖于相同的数据源并在初始化回调中使用会话工厂,则可能存在问题,因为数据尚未初始化。 一个常见的示例是缓存,它在应用程序启动时急切地初始化并从数据库加载数据。SessionFactory
init-method
@PostConstruct
afterPropertiesSet()
InitializingBean
若要解决此问题,有两个选择:将缓存初始化策略更改为稍后阶段,或者确保首先初始化密钥空间初始值设定项。
如果应用程序由您控制,则更改缓存初始化策略可能很容易,否则就不然。 有关如何实现此目的的一些建议包括:
- 使缓存在首次使用时延迟初始化,从而缩短应用程序启动时间。
- 具有缓存或初始化缓存实现器的单独组件。 当应用程序上下文启动时,可以通过设置 itsflag 自动启动 a,也可以通过调用封闭上下文来手动启动 a。
Lifecycle
SmartLifecycle
SmartLifecycle
autoStartup
Lifecycle
ConfigurableApplicationContext.start()
- 使用 Springor 类似的自定义观察器机制来触发缓存 initialization.is 上下文在准备好使用时(在所有 bean 都初始化后)始终发布缓存,因此这通常是一个有用的钩子(这就是默认情况下的工作方式)。
ApplicationEvent
ContextRefreshedEvent
SmartLifecycle
确保首先初始化密钥空间初始值设定项也很容易。 关于如何实现这一点的一些建议包括:
- 依靠 Spring 的默认行为,即按注册顺序初始化 bean。 通过采用 XML 配置中一组元素的常见做法,对应用程序模块进行排序,并确保首先列出数据库和数据库初始化,您可以轻松安排这一点。
BeanFactory
<import/>
- 将使用它的业务组件分开,并通过将它们放在单独的实例中来控制它们的启动顺序(例如,父上下文包含 ,子上下文包含业务组件)。 这种结构在Spring Web应用程序中很常见,但可以更普遍地应用。
SessionFactory
ApplicationContext
SessionFactory
- 使用表和用户定义类型的模式管理,使用 Spring Data Cassandra 的内置模式生成器初始化密钥空间。
10.4.3. 表和用户定义类型
Spring Data for Apache Cassandra 使用适合您的数据模型的映射实体类进行数据访问。 可以使用这些实体类创建 Cassandra 表规范和用户类型定义。
架构创建与初始化绑定。 支持以下操作:CqlSession
SchemaAction
-
SchemaAction.NONE
:不会创建或删除任何表或类型。 这是默认设置。 -
SchemaAction.CREATE
:从带批注的实体和带批注的类型创建表、索引和用户定义类型。 如果尝试创建现有表或类型,则会导致错误。@Table
@UserDefinedType
-
SchemaAction.CREATE_IF_NOT_EXISTS
:喜欢但扣留。 现有表或类型不会导致任何错误,但可能会保持过时状态。SchemaAction.CREATE
IF NOT EXISTS
-
SchemaAction.RECREATE
:删除并重新创建已知使用的现有表和类型。 不会删除应用程序中未配置的表和类型。 -
SchemaAction.RECREATE_DROP_UNUSED
:删除所有表和类型,仅重新创建已知的表和类型。
|
为架构管理启用表和用户定义类型
基于元数据的映射解释了使用约定和注释进行的对象映射。 为了防止将不需要的类创建为表或类型,架构管理仅对用批注的实体和用批注的用户定义类型处于活动状态。 通过扫描类路径来发现实体。 实体扫描需要一个或多个基本包。 使用的元组类型列不提供任何键入详细信息。 因此,必须对此类列属性进行批注以指定所需的列类型。@Table
@UserDefinedType
TupleValue
@CassandraType(type = TUPLE, typeArguments = …)
下面的示例演示如何在 XML 配置中指定实体基础包:
例 59。指定实体基础包
爪哇岛
.XML
@Configuration
public class EntityBasePackagesConfiguration extends AbstractCassandraConfiguration {
@Override
public String[] getEntityBasePackages() {
return new String[] { "com.foo", "com.bar" };
}
// ...
}
10.5. CqlTemplate
类是核心 CQL 包中的中心类。 它处理资源的创建和释放。 它执行核心 CQL 工作流的基本任务,例如语句创建和执行,并保留应用程序代码以提供 CQL 和提取结果。 该类执行 CQL 查询和更新语句,执行迭代覆盖实例和提取返回的参数值。 它还捕获 CQL 异常,并将其转换为包中定义的通用、信息量更大的异常层次结构。CqlTemplate
CqlTemplate
ResultSet
org.springframework.dao
当您使用 for 代码时,您只需要实现具有明确定义的协定的回调接口。 给定 a,回调接口使用提供的 CQL 和任何必要的参数参数创建预准备语句。 接口从 a 的每一行中提取值。CqlTemplate
Connection
PreparedStatementCreator
RowCallbackHandler
ResultSet
可以通过引用的直接实例化在DAO实现中使用,也可以在Spring容器中配置,并作为Bean提供给DAO,reference.isCassandraTemplate的基础构建块。CqlTemplate
SessionFactory
CqlTemplate
此类发出的所有 CQL 都记录在与模板实例的完全限定类名对应的类别下的级别(通常,但如果使用该类的自定义子类,则可能会有所不同)。DEBUG
CqlTemplate
CqlTemplate
您可以通过在 CQL API 实例上配置以下参数来控制提取大小、一致性级别和重试策略默认值:、 和。 如果未设置特定查询选项,则应用默认值。CqlTemplate
AsyncCqlTemplate
ReactiveCqlTemplate
|
10.5.1. 类用法示例CqlTemplate
本节提供了一些操作中的类示例。 这些示例并不是公开的所有功能的详尽列表。 请参阅Javadoc。CqlTemplate
CqlTemplate
查询 (选择) 使用CqlTemplate
以下查询获取表中的行数:
int rowCount = cqlTemplate.queryForObject("SELECT COUNT(*) FROM t_actor", Integer.class);
以下查询使用绑定变量:
int countOfActorsNamedJoe = cqlTemplate.queryForObject(
"SELECT COUNT(*) FROM t_actor WHERE first_name = ?", Integer.class, "Joe");
以下示例查询:String
String lastName = cqlTemplate.queryForObject(
"SELECT last_name FROM t_actor WHERE id = ?",
String.class, 1212L);
以下示例查询并填充单个域对象:
Actor actor = cqlTemplate.queryForObject("SELECT first_name, last_name FROM t_actor WHERE id = ?",
new RowMapper<Actor>() {
public Actor mapRow(Row row, int rowNum) {
Actor actor = new Actor();
actor.setFirstName(row.getString("first_name"));
actor.setLastName(row.getString("last_name"));
return actor;
}
}, 1212L);
以下示例查询并填充多个域对象:
List<Actor> actors = cqlTemplate.query(
"SELECT first_name, last_name FROM t_actor",
new RowMapper<Actor>() {
public Actor mapRow(Row row, int rowNum) {
Actor actor = new Actor();
actor.setFirstName(row.getString("first_name"));
actor.setLastName(row.getString("last_name"));
return actor;
}
});
如果最后两个代码片段确实存在于同一个应用程序中,那么删除两个匿名内部类中存在的重复项并将它们提取到单个类(通常是嵌套类)中,然后可以通过 DAO 方法引用。RowMapper
static
例如,最好按如下方式编写最后一个代码片段:
List<Actor> findAllActors() {
return cqlTemplate.query("SELECT first_name, last_name FROM t_actor", ActorMapper.INSTANCE);
}
enum ActorMapper implements RowMapper<Actor> {
INSTANCE;
public Actor mapRow(Row row, int rowNum) {
Actor actor = new Actor();
actor.setFirstName(row.getString("first_name"));
actor.setLastName(row.getString("last_name"));
return actor;
}
}
INSERT
,,和UPDATE
DELETE
CqlTemplate
您可以使用该方法执行、和操作。 参数值通常作为变量参数提供,或者作为对象数组提供。execute(…)
INSERT
UPDATE
DELETE
以下示例演示如何使用以下命令执行操作:INSERT
CqlTemplate
cqlTemplate.execute(
"INSERT INTO t_actor (first_name, last_name) VALUES (?, ?)",
"Leonor", "Watling");
以下示例演示如何使用以下命令执行操作:UPDATE
CqlTemplate
cqlTemplate.execute(
"UPDATE t_actor SET last_name = ? WHERE id = ?",
"Banjo", 5276L);
以下示例演示如何使用以下命令执行操作:DELETE
CqlTemplate
cqlTemplate.execute(
"DELETE FROM t_actor WHERE id = ?",
5276L);
其他操作CqlTemplate
可以使用该方法执行任意 CQL。因此,该方法通常用于 DDL 语句。 它被采用回调接口、绑定变量数组等的变体严重重载。execute(..)
以下示例演示如何使用全部传递给方法的不同 API 对象来创建和删除表:execute()
cqlTemplate.execute("CREATE TABLE test_table (id uuid primary key, event text)");
DropTableSpecification dropper = DropTableSpecification.dropTable("test_table");
String cql = DropTableCqlGenerator.toCql(dropper);
cqlTemplate.execute(cql);
10.6. 异常翻译
Spring 框架为各种数据库和映射技术提供了异常转换。 这传统上是针对JDBC和JPA的。Spring Data for Apache Cassandra 通过提供接口的实现将此功能扩展到 Apache Cassandra。org.springframework.dao.support.PersistenceExceptionTranslator
映射到 Spring 一致的数据访问异常层次结构背后的动机是让您编写可移植和描述性的异常处理代码,而无需针对特定的 Cassandra 异常进行编码和处理。 Spring 的所有数据访问异常都是从类继承而来的,因此您可以确保可以在单个 try-catch 块中捕获所有与数据库相关的异常。DataAccessException
10.7. 控制卡桑德拉连接
应用程序通过使用对象连接到Apache Cassandra。 Cassandra保留跟踪到各个节点的多个连接,并被设计为线程安全、长期存在的对象。 通常,您可以对整个应用程序使用单个。CqlSession
CqlSession
CqlSession
Spring 为 Apache Cassandra 收购了 Cassandrathrough a.is Spring 数据的一部分,是一个通用的连接工厂。 它允许容器或框架从应用程序代码中隐藏连接处理和路由问题。CqlSession
SessionFactory
SessionFactory
以下示例演示如何配置默认值:SessionFactory
Session session = … // get a Cassandra Session
CqlTemplate template = new CqlTemplate();
template.setSessionFactory(new DefaultSessionFactory(session));
CqlTemplate
和其他模板 API 实现为每个操作获取 a。 由于其长期存在的性质,会话在调用所需操作后不会关闭。 正确处置资源的责任在于使用会话的容器或框架。CqlSession
您可以在包中找到各种实现。SessionFactory
org.springframework.data.cassandra.core.cql.session
10.8. 简介CassandraTemplate
Theclass位于软件包中,是Spring的Cassandra支持中的中心类,并提供了丰富的功能集来与数据库进行交互。 该模板提供了创建、更新、删除和查询 Cassandra 的便捷操作,并提供域对象与 Cassandra 表中行之间的映射。CassandraTemplate
org.springframework.data.cassandra
配置完成后,是线程安全的,可以在多个实例中重用。 |
Cassandra 中的行和应用程序域类之间的映射是通过委托给接口的实现来完成的。 Spring 提供了一个默认的实现,但你也可以编写自己的自定义转换器。 有关更多详细信息,请参阅有关Cassandra转换的部分。CassandraConverter
MappingCassandraConverter
该类实现接口。 这些方法尽可能以 Cassandra 中可用的方法命名,以使已经熟悉 Cassandra 的开发人员熟悉 API。CassandraTemplate
CassandraOperations
CassandraOperations
例如,您可以找到,,,和等方法。 设计目标是尽可能轻松地在使用基本Cassandra驱动程序和之间转换。 这两个 API 之间的主要区别在于可以传递域对象,而不是 CQL 和查询对象。select
insert
delete
update
CassandraOperations
CassandraOperations
在实例上引用操作的首选方法是通过接口。 |
默认转换器实现由 使用。 虽然可以使用其他元数据来指定对象到行的映射,但它也可以通过使用某些约定来转换不包含其他元数据的对象,以映射字段和表名。 这些约定以及映射注释的使用在“映射”一章中进行了说明。CassandraTemplate
MappingCassandraConverter
MappingCassandraConverter
另一个核心功能是将Cassandra Java驱动程序中抛出的异常异常转换为Spring的可移植数据访问异常层次结构。 有关详细信息,请参阅异常转换部分。CassandraTemplate
模板 API 具有不同的执行模型风格。 基本使用阻塞(命令式同步)执行模型。 您可以使用异步执行和与实例同步,也可以用于反应式执行的ReactiveCassandraTemplate。 |
10.8.1. 实例化卡桑德拉模板
CassandraTemplate
应始终配置为 Spring Bean,尽管我们前面展示了一个可以直接实例化它的示例。 但是,由于我们假设了制作 Spring 模块的上下文,因此我们假设存在 Spring 容器。
有两种方法可以获取 a,具体取决于您加载 Spring 的方式:CassandraTemplate
ApplicationContext
- 自动布线
- Bean 查找与应用程序上下文
自动布线
您可以自动连接到您的项目中,如以下示例所示:CassandraOperations
@Autowired
private CassandraOperations cassandraOperations;
与所有 Spring 自动接线一样,这假设只有一个 bean 的类型。 如果您有多个 bean(如果您在同一项目中使用多个键空间,则会出现这种情况),那么您可以使用注释来指定要自动连线的 bean。CassandraOperations
ApplicationContext
CassandraTemplate
@Qualifier
@Autowired
@Qualifier("keyspaceOneTemplateBeanId")
private CassandraOperations cassandraOperations;
豆查找与ApplicationContext
您还可以从中查找 bean,如以下示例所示:CassandraTemplate
ApplicationContext
CassandraOperations cassandraOperations = applicationContext.getBean("cassandraTemplate", CassandraOperations.class);
10.9. 保存、更新和删除行
CassandraTemplate
为您提供了一种保存、更新和删除域对象的简单方法,并将这些对象映射到 Cassandra 中管理的表。
10.9.1. 类型映射
Spring Data for Apache Cassandra 依赖于 DataStax Java 驱动程序来确保类型支持。 随着类型的添加或更改,Spring Data for Apache Cassandra 模块将继续运行,而无需更改。 有关当前类型映射矩阵,请参阅CQL 数据类型和“数据映射和类型转换”。CodecRegistry
10.9.2. 插入和更新行的方法
CassandraTemplate
有几种方便的方法来保存和插入对象。 为了对转换过程进行更精细的控制,您可以使用(例如,)注册 Springinstances。Converter
MappingCassandraConverter
Converter<Row, Person>
插入操作和更新操作之间的区别在于操作不插入值。 |
使用操作的简单情况是保存POJO。在这种情况下,表名由简单类名(而不是完全限定的类名)确定。 可以使用映射元数据覆盖用于存储对象的表。INSERT
插入或更新时,必须设置属性。 Apache Cassandra无法生成ID。id
下面的示例使用保存操作并检索其内容:
例 60。通过使用插入和检索对象CassandraTemplate
…
Person bob = new Person("Bob", 33);
cassandraTemplate.insert(bob);
Person queriedBob = cassandraTemplate.selectOneById(query(where("age").is(33)), Person.class);
您可以使用以下操作进行插入和保存:
-
void
insert:在 Apache Cassandra 表中插入对象。(Object objectToSave)
-
WriteResult
insert:在 Apache Cassandra 表中插入对象并应用。(Object objectToSave, InsertOptions options)
InsertOptions
您可以使用以下更新操作:
-
void
update:更新 Apache Cassandra 表中的对象。(Object objectToSave)
-
WriteResult
update:更新 Apache Cassandra 表中的对象并应用。(Object objectToSave, UpdateOptions options)
UpdateOptions
还可以使用老式方式编写自己的 CQL 语句,如以下示例所示:
String cql = "INSERT INTO person (age, name) VALUES (39, 'Bob')";
cassandraTemplate().getCqlOperations().execute(cql);
您还可以在使用和时配置其他选项,例如 TTL、一致性级别和轻量级事务。InsertOptions
UpdateOptions
我的行插入到哪个表中?
您可以通过两种方式管理用于对表进行操作的表名。 默认表名是更改为以小写字母开头的简单类名。 因此,类的实例将存储在表中。 第二种方法是在注释中指定表名。com.example.Person
person
@Table
在批处理中插入、更新和删除单个对象
Cassandra 协议支持使用批处理在一个操作中插入行集合。
接口中的以下方法支持此功能:CassandraTemplate
-
batchOps
:创建一个新填充批处理。CassandraBatchOperations
CassandraBatchOperations
-
insert
:插入单个对象、数组 (var-args) 或 anof 对象。Iterable
-
update
:更新单个对象、数组 (var-args) 或 anof 对象。Iterable
-
delete
:需要删除单个对象、数组 (var-args) 或 anof 对象。Iterable
-
withTimestamp
:将 TTL 应用于批处理。 -
execute
:执行批处理。
10.9.3. 更新表中的行
对于更新,您可以选择更新多个行。
以下示例显示如何通过使用分配将一次性 $50.00 奖金添加到余额中来更新单个帐户对象:+
例 61。使用 更新行CasandraTemplate
…
boolean applied = cassandraTemplate.update(Query.query(where("id").is("foo")),
Update.create().increment("balance", 50.00), Account.class);
除了前面讨论的之外,我们还使用 anobject 提供了更新定义。 该类具有与可用于 Apache Cassandra 的更新分配匹配的方法。Query
Update
Update
大多数方法返回对象以提供用于代码样式目的的流畅 API。Update
执行行更新的方法
update 方法可以更新行,如下所示:
-
boolean
update:更新 Apache Cassandra 表中的选定对象。(Query query, Update update, Class<?> entityClass)
更新类的方法
Theclass可以与一点“语法糖”一起使用,因为它的方法意味着链接在一起。 此外,您可以使用静态方法和静态导入来启动新实例的创建。Update
Update
public static Update update(String key, Object value)
该类具有以下方法:Update
AddToBuilder
添加到入口点:(String columnName)
AddToBuilder
- 更新:使用更新分配将集合值附加到现有集合。
prepend(Object value)
+
- 更新:使用更新分配将所有集合值附加到现有集合。
prependAll(Object… values)
+
- 更新:使用更新分配将集合值追加到现有集合。
append(Object value)
+
- 更新:使用更新分配将所有集合值追加到现有集合。
append(Object… values)
+
- 更新:使用更新分配添加地图条目。
entry(Object key, Object value)
+
- 更新:使用更新分配将所有地图条目添加到地图中。
addAll(Map<? extends Object, ? extends Object> map)
+
-
Update
删除:使用更新赋值从集合中删除值。(String columnName, Object value)
-
-
Update
清除:清除集合。(String columnName)
-
Update
增量:使用更新分配进行更新。(String columnName, Number delta)
+
-
Update
递减:使用更新分配进行更新。(String columnName, Number delta)
-
-
Update
设置:使用更新分配进行更新。(String columnName, Object value)
=
SetBuilder
设置入口点:(String columnName)
SetBuilder
- 更新:使用更新赋值将给定索引处的集合设置为值。
atIndex(int index).to(Object value)
=
- 更新:将给定键处的映射条目设置为值更新赋值。
atKey(String object).to(Object value)
=
以下清单显示了一些更新示例:
// UPDATE … SET key = 'Spring Data';
Update.update("key", "Spring Data")
// UPDATE … SET key[5] = 'Spring Data';
Update.empty().set("key").atIndex(5).to("Spring Data");
// UPDATE … SET key = key + ['Spring', 'DATA'];
Update.empty().addTo("key").appendAll("Spring", "Data");
请注意,一旦创建,它就不可变。 调用方法会创建新的不可变(中间)对象。Update
Update
10.9.4. 删除行的方法
可以使用以下重载方法从数据库中删除对象:
-
boolean
删除:删除所选对象。(Query query, Class<?> entityClass)
Query
-
T
删除:删除给定对象。(T entity)
-
T
删除:删除应用的给定对象。(T entity, QueryOptions queryOptions)
QueryOptions
-
boolean
deleteById:使用给定的 ID 删除对象。(Object id, Class<?> entityClass)
10.9.5. 乐观锁定
Theannotation 提供的语法类似于 Cassandra 上下文中的 JPA,并确保更新仅应用于具有匹配版本的行。 乐观锁定利用 Cassandra 的轻量级事务有条件地插入、更新和删除行。 因此,语句是使用条件执行的。 对于更新和删除,版本属性的实际值将添加到条件中,以便如果同时另一个操作更改了行,则修改不会产生任何影响。 在这种情况下,茴香扔了。 以下示例显示了这些功能:@Version
INSERT
IF NOT EXISTS
UPDATE
OptimisticLockingFailureException
@Table
class Person {
@Id String id;
String firstname;
String lastname;
@Version Long version;
}
Person daenerys = template.insert(new Person("Daenerys"));
Person tmp = template.findOne(query(where("id").is(daenerys.getId())), Person.class);
daenerys.setLastname("Targaryen");
template.save(daenerys);
template.save(tmp); // throws OptimisticLockingFailureException
插入 document.is 设置为。 |
加载刚刚插入的 document.is。 |
更新文档。 设置和碰撞。 |
尝试更新以前加载的文档。 操作失败,并显示 ,因为电流是。 |
乐观锁定仅支持单实体操作,不支持批处理操作。 |
10.10. 查询行
您可以使用 theandclasses 来表达查询,这些类具有反映本机 Cassandra 谓词运算符名称的方法名称,例如,,, 等。Query
Criteria
lt
lte
is
Theandclasses 遵循流畅的 API 风格,因此您可以轻松地将多个方法条件和查询链接在一起,同时具有易于理解的代码。 在 Java 中创建实例时使用静态导入以提高可读性。Query
Criteria
Query
Criteria
10.10.1. 查询表中的行
在前面的部分中,我们看到了如何使用方法检索单个对象。 这样做将返回单个域对象。 我们还可以查询要作为域对象列表返回的行集合。 假设我们有许多对象,其名称和年龄值以行的形式存储在表中,并且每个人都有帐户余额,我们现在可以使用以下代码运行查询:selectOneById
CassandraTemplate
Person
例 62。使用 查询行CassandraTemplate
…
List<Person> result = cassandraTemplate.select(query(where("age").is(50))
.and(where("balance").gt(1000.00d)).withAllowFiltering(), Person.class);
、 和方法将对象作为参数。 此对象定义用于执行查询的条件和选项。 条件是通过使用具有名为实例化新对象的静态工厂方法的对象来指定的。 我们建议使用 forand 的静态导入,以使查询更具可读性。select
selectOne
stream
Query
Criteria
where
Criteria
org.springframework.data.cassandra.core.query.Criteria.where
Query.query
此查询应返回满足指定条件的对象列表。 Theclass 具有以下方法,这些方法对应于 Apache Cassandra 中提供的运算符:Person
Criteria
条件类的方法
-
CriteriaDefinition
gt:使用运算符创建条件。(Object value)
>
-
CriteriaDefinition
gte:使用运算符创建条件。(Object value)
>=
-
CriteriaDefinition
in:通过使用 varargs 参数的运算符创建条件。(Object… values)
IN
-
CriteriaDefinition
in:通过使用集合的运算符创建条件。(Collection<?> collection)
IN
-
CriteriaDefinition
is:使用字段匹配 () 创建条件。(Object value)
column = value
-
CriteriaDefinition
lt:使用运算符创建条件。(Object value)
<
-
CriteriaDefinition
lte:使用运算符创建条件。(Object value)
⇐
-
CriteriaDefinition
like:使用运算符创建条件。(Object value)
LIKE
-
CriteriaDefinition
包含:使用运算符创建条件。(Object value)
CONTAINS
-
CriteriaDefinition
包含键:使用运算符创建条件。(Object key)
CONTAINS KEY
Criteria
创建后是不可变的。
查询类的方法
该类具有一些可用于提供查询选项的其他方法:Query
-
Query
by:用于创建对象。(CriteriaDefinition… criteria)
Query
-
Query
和:用于向查询添加其他条件。(CriteriaDefinition criteria)
-
Query
列:用于定义要包含在查询结果中的列。(Columns columns)
-
Query
limit:用于将返回结果的大小限制为提供的限制(用于分页)。(long limit)
-
Query
pageRequest:用于关联、和查询(用于分页)。(Pageable pageRequest)
Sort
PagingState
fetchSize
-
Query
分页状态:用于与查询关联(用于分页)。(ByteBuffer pagingState)
ByteBuffer
-
Query
查询选项:用于与查询关联。(QueryOptions queryOptions)
QueryOptions
-
Query
sort:用于为结果提供排序定义。(Sort sort)
-
Query
withAllowFiltering:用于呈现查询。()
ALLOW FILTERING
Query
创建后是不可变的。 调用方法会创建新的不可变(中间)对象。Query
10.10.2. 查询行的方法
该类具有以下返回行的方法:Query
-
List<T>
select:查询表中类型的对象列表。(Query query, Class<T> entityClass)
T
-
T
selectOne:从表中查询单个类型对象。(Query query, Class<T> entityClass)
T
-
Slice<T>
slice:通过从表中查询类型的 aof 对象来启动或继续分页。(Query query, Class<T> entityClass)
Slice
T
-
Stream<T>
stream:从表中查询类型的对象流。(Query query, Class<T> entityClass)
T
-
List<T>
select:通过提供 CQL 语句从表中对类型的对象列表进行即席查询。(String cql, Class<T> entityClass)
T
-
T
selectOne:通过提供 CQL 语句从表中对单个类型对象进行即席查询。(String cql, Class<T> entityClass)
T
-
Stream<T>
stream:通过提供 CQL 语句从表中对类型对象流进行即席查询。(String cql, Class<T> entityClass)
T
查询方法必须指定返回的目标类型。T
10.10.3. 流畅的模板接口
当涉及到与Apache Cassandra进行更多低级交互时,接口是核心组件之一。 它提供了广泛的方法。 您可以找到每种方法的多个重载。 它们中的大多数涵盖 API 的可选(可为空)部分。CassandraOperations
FluentCassandraOperations
为提供更易读、更流畅的 API 的常用方法提供更窄的接口。入口点 (,,, 和) 遵循基于要执行的操作的自然命名方案。 从入口点开始,API 旨在仅提供依赖于上下文的方法,这些方法指导开发人员使用调用实际的终止方法。 以下示例显示了流畅的 API:CassandraOperations
query(…)
insert(…)
update(…)
delete(…)
CassandraOperation
List<SWCharacter> all = ops.query(SWCharacter.class)
.inTable("star_wars")
.all();
如果使用类名作为表名不是问题,则跳过此步骤,如果定义表名withor。 |
如果 Cassandra 中的表包含不同类型的实体(例如在 Table of 中),则可以使用不同的类型来映射查询结果。 您可以使用将结果映射到其他目标类型,同时仍适用于查询和表名称。 以下示例使用 theand 方法:Jedi
SWCharacters
as(Class<?> targetType)
query(Class<?> entityType)
query
as
List<Jedi> all = ops.query(SWCharacter.class)
.as(Jedi.class)
.matching(query(where("jedi").is(true)))
.all();
查询字段将针对类型进行映射。 |
生成的行将映射到。 |
您可以通过仅提供类型通过来直接将投影应用于生成的文档。 |
终止方法(,,, 和)处理检索单个实体和检索多个实体之间的切换 asorand 类似操作。first()
one()
all()
stream()
List
Stream
新的流畅模板 API 方法(即,,,,和)有效地使用线程安全支持对象来编写 CQL 语句。 但是,它以额外的年轻一代 JVM 堆开销为代价,因为设计基于各种 CQL 语句组件的最终字段和突变构造。 在可能插入或删除大量对象(例如循环内部)时,应小心。 |
10.11. 准备好的声明
可以准备多次执行的 CQL 语句并将其存储在对象中,以提高查询性能。 驱动程序和 Cassandra 都维护查询到其元数据的映射。 可以通过以下抽象来使用预准备语句:PreparedStatement
PreparedStatement
-
CqlTemplate
通过选择 API -
CassandraTemplate
通过启用预准备语句 - Cassandra 存储库,因为它们是构建的
CassandraTemplate
10.11.1. 使用CqlTemplate
类(及其异步和反应变体)提供了各种接受静态 CQL、对象和的方法。 接受静态 CQL 而不带其他参数的方法通常按原样运行 CQL 语句,无需进一步处理。 接受静态 CQL 与参数数组(如 and)组合的方法使用预准备语句。 在内部,这些方法创建 aandobjects 来准备语句,然后将值绑定到语句以运行它。 Spring Data Cassandra 通常对预准备语句使用基于索引的参数绑定。CqlTemplate
Statement
PreparedStatementCreator
execute(String cql, Object… args)
queryForRows(String cql, Object… args)
PreparedStatementCreator
PreparedStatementBinder
从 Cassandra 驱动程序版本 4 开始,预准备语句缓存在驱动程序级别,无需在应用程序中跟踪预准备语句。
下面的示例演示如何使用参数化预准备语句发出查询:
String lastName = cqlTemplate.queryForObject(
"SELECT last_name FROM t_actor WHERE id = ?",
String.class, 1212L);
如果需要对语句准备和参数绑定进行更多控制(例如,使用命名绑定参数),可以通过调用查询方法 withandarguments 来完全控制预准备语句的创建和参数绑定:PreparedStatementCreator
PreparedStatementBinder
List<String> lastNames = cqlTemplate.query(
session -> session.prepare("SELECT last_name FROM t_actor WHERE id = ?"),
ps -> ps.bind(1212L),
(row, rowNum) -> row.getString(0));
Spring Data Cassandra 在包中附带了支持该模式的类:cql
-
SimplePreparedStatementCreator
- 用于创建预准备语句的实用程序类。 -
ArgumentPreparedStatementBinder
- 实用程序类,用于将参数绑定到预准备语句。
10.11.2. 使用CassandraTemplate
类建立在提供更高级别的抽象之上。 预准备语句的使用可以通过调用respect直接控制(及其异步和反应变体)。 请注意,默认情况下启用预准备语句 by。CassandraTemplate
CqlTemplate
CassandraTemplate
setUsePreparedStatements(false)
setUsePreparedStatements(true)
CassandraTemplate
下面的示例演示如何使用生成和接受 CQL 的方法:
template.setUsePreparedStatements(true);
Actor actorByQuery = template.selectOne(query(where("id").is(42)), Actor.class);
Actor actorByStatement = template.selectOne(
SimpleStatement.newInstance("SELECT id, name FROM actor WHERE id = ?", 42),
Actor.class);
调用实体绑定方法(如 aorbuild CQL 语句本身)来执行预期的操作。 某些方法(例如)也接受 CQLobjects 作为其 API 的一部分。select(Query, Class<T>)
update(Query, Update, Class<T>)
CassandraTemplate
select(Statement<?>, Class<T>)
Statement
在调用接受 awith aobject 的方法时,可以参与预准备语句。 模板 API 提取查询字符串和参数(位置参数和命名参数),并使用它们来准备、绑定和运行语句。 非对象不能与预准备语句一起使用。Statement
SimpleStatement
SimpleStatement
10.11.3. 缓存预准备语句
从 Cassandra 驱动程序 4.0 开始,准备好的语句由缓存缓存,因此可以准备两次相同的字符串。 以前的版本需要在驱动程序外部缓存预准备语句。 另请参阅有关预准备语句的驱动程序文档以获取进一步参考。CqlSession
10.12. 可观测性
从应用程序组件获取有关其操作、计时以及与应用程序代码的关系的见解对于了解延迟至关重要。 Spring Data Cassandra通过Cassandra驱动程序附带一个千分尺仪器,以收集Cassandra相互作用期间的观测结果。 一旦设置了集成,千分尺将为每个Cassandra语句创建米和跨度(用于分布式跟踪)。
若要启用检测,请将以下配置应用于应用程序:
@Configuration
class ObservabilityConfiguration {
@Bean
public ObservableCqlSessionFactoryBean observableCqlSession(CqlSessionBuilder builder,
ObservationRegistry registry) {
return new ObservableCqlSessionFactoryBean(builder, registry);
}
@Bean
public ObservableReactiveSessionFactoryBean observableReactiveSession(CqlSession session,
ObservationRegistry registry) {
return new ObservableReactiveSessionFactoryBean(session, registry);
}
}
包装 CQL 会话对象以观察 Cassandra 语句的执行。 另外,注册到。 |
包装 CQL 会话对象以观察反应式 Cassandra 语句执行。 |
10.12.1. 可观测性 - 约定
您可以在下面找到该项目声明的alland列表。GlobalObservabilityConventions
ObservabilityConventions
表 3.观察公约的实施
观察约定类名 | 适用的观察上下文类名 |
| |
10.12.2. 可观测性 - 指标
您可以在下面找到此项目声明的所有指标的列表。
卡桑德拉查询观察
创建基于 Cassandra 的查询。
io.micrometer.observation.Observation
指标名称。类型和基本单位。spring.data.cassandra.query
timer
seconds
封闭类的完全限定名称。org.springframework.data.cassandra.observability.CassandraObservation
表 4.低基数键
名字 | 描述 |
| |
| |
| Cassandra 密钥空间的名称。 |
| 数据库操作。 |
| 数据库系统。 |
| 数据库主机的名称。 |
| 逻辑远程端口号。 |
| 卡桑德拉对等地址。 |
| 卡桑德拉对等端口。 |
| 网络传输。 |
| 方法名称 |
| 卡桑德拉会议 |
表 5.高基数键
名字 | 描述 |
| |
| |
| |
| 包含 Cassandra CQL 的键值。 |
| 包含给定节点发生的错误的标记。(由于名称包含最终值将在运行时解析) |
10.12.3. 可观测性 - 跨度
您可以在下面找到该项目声明的所有跨度的列表。
卡桑德拉查询观察跨度
创建基于 Cassandra 的查询。
io.micrometer.observation.Observation
跨度名称。spring.data.cassandra.query
封闭类的完全限定名称。org.springframework.data.cassandra.observability.CassandraObservation
表 6.标签键
名字 | 描述 |
| |
| |
| |
| |
| |
| Cassandra 密钥空间的名称。 |
| The database operation. |
| A key-value containing Cassandra CQL. |
| Database system. |
| Name of the database host. |
| Logical remote port number. |
| Cassandra peer address. |
| Cassandra peer port. |
| Network transport. |
| 方法名称 |
| 包含给定节点发生的错误的标记。(由于名称包含最终值将在运行时解析) |
| 卡桑德拉会议 |
另请参阅开放遥测语义约定以获取进一步参考。
反应式 Cassandra 支持包含广泛的功能:
使用基于 Java 的类的 Spring 配置支持。@Configuration
ReactiveCqlTemplate
帮助程序类,通过正确处理常见的 Cassandra 数据访问操作来提高工作效率。
ReactiveCassandraTemplate
帮助程序类,通过以响应方式使用来提高工作效率。 它包括表和 POJO 之间的集成对象映射。ReactiveCassandraOperations
将异常转换为 Spring 的可移植数据访问异常层次结构。
功能丰富的对象映射与 Spring 的转换服务集成。
基于 Java 的查询、条件和更新 DSL。
自动实现接口,包括对自定义查找器方法的支持。Repository
对于大多数面向数据的任务,您可以使用存储库支持,它使用丰富的对象映射 functionality.is 通常用于递增计数器或执行即席 CRUD 操作。还提供了回调方法,使您可以轻松获取低级 API 对象,例如,允许您直接与 Cassandra 通信。 Spring Data for Apache Cassandra 对各种 API 中的对象使用与 DataStax Java 驱动程序中一致的命名约定,以便立即熟悉它们,以便您可以将现有知识映射到 Spring API 上。ReactiveCassandraTemplate
ReactiveCqlTemplate
ReactiveCqlTemplate
com.datastax.oss.driver.api.core.CqlSession
11.1. 入门
Spring Data for Apache Cassandra 需要 Apache Cassandra 2.1 或更高版本和 Datastax Java Driver 4.0 或更高版本。 快速设置和引导工作环境的一种简单方法是在STS中创建基于 Spring 的项目或使用Spring 初始值设定项。
首先,您需要设置一个正在运行的 Apache Cassandra 服务器。 请参阅 Apache Cassandra快速入门指南,了解如何启动 Apache Cassandra的说明。 安装后,启动 Cassandra 通常是运行以下命令的问题:CASSANDRA_HOME/bin/cassandra -f
要在 STS 中创建 Spring 项目,请转到“新建→ Spring 模板项目→文件”→“简单 Spring 实用程序项目”,并在出现提示时按“是”。 然后输入项目和包名称,例如。org.spring.data.cassandra.example
然后,您可以将以下依赖项声明添加到pom.xml文件的部分中。dependencies
<dependencies>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-cassandra</artifactId>
<version>4.0.0</version>
</dependency>
</dependencies>
另外,您应该将pom.xml文件中的Spring版本更改为如下:
<spring.framework.version>6.0.0</spring.framework.version>
如果使用里程碑版本而不是 GA 版本,您还需要将 Maven 的 Spring 里程碑存储库的位置添加到您的 pom.xml 文件中,以便它与 yourelement 处于同一级别,如下所示:<dependencies/>
<repositories>
<repository>
<id>spring-milestone</id>
<name>Spring Maven MILESTONE Repository</name>
<url>https://repo.spring.io/libs-milestone</url>
</repository>
</repositories>
存储库也可以在此处浏览。
您还可以在此处浏览所有 Spring 存储库。
现在,您可以创建一个简单的 Java 应用程序,用于存储和读取 Cassandra 的域对象。
为此,请首先创建一个要保留的简单域对象类,如以下示例所示:
package org.springframework.data.cassandra.example;
@Table
public class Person {
@PrimaryKey private final String id;
private final String name;
private final int age;
public Person(String id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
public String getId() {
return id;
}
private String getName() {
return name;
}
private int getAge() {
return age;
}
@Override
public String toString() {
return String.format("{ @type = %1$s, id = %2$s, name = %3$s, age = %4$d }", getClass().getName(), getId(),
getName(), getAge());
}
}
接下来,创建要运行的主应用程序,如以下示例所示:
package org.springframework.data.cassandra.example;
public class ReactiveCassandraApplication {
private static final Log LOG = LogFactory.getLog(ReactiveCassandraApplication.class);
private static Person newPerson(String name, int age) {
return new Person(UUID.randomUUID().toString(), name, age);
}
public static void main(String[] args) {
CqlSession cqlSession = CqlSession.builder().withKeyspace("mykeyspace").build();
ReactiveCassandraOperations template = new ReactiveCassandraTemplate(new DefaultBridgedReactiveSession(cqlSession));
Mono<Person> jonDoe = template.insert(newPerson("Jon Doe", 40));
jonDoe.flatMap(it -> template.selectOne(Query.query(Criteria.where("id").is(it.getId())), Person.class))
.doOnNext(it -> LOG.info(it.toString()))
.then(template.truncate(Person.class))
.block();
cqlSession.close();
}
}
即使在这个简单的例子中,也有一些值得注意的事情需要指出:
- 完全同步的流不会从反应式基础结构中受益,因为反应式编程模型需要同步。
- 您可以创建 的实例 与 Cassandra。
ReactiveCassandraTemplate
CqlSession
- 您必须将POJO注释为Cassandraand注释。 (可选)您可以覆盖这些映射名称以匹配 Cassandra 数据库表名和列名。
@Table
@PrimaryKey
- 可以使用原始 CQL 或 DataStaxAPI 来构造查询。
QueryBuilder
11.2. 示例存储库
Github存储库包含几个示例,您可以下载并使用这些示例来了解库的工作方式。
11.3. 用弹簧连接到卡桑德拉
将Apache Cassandra与Spring一起使用时,首要任务之一是使用Spring IoC容器创建对象。 您可以通过使用基于 Java 的 Bean 元数据或使用基于 XML 的 Bean 元数据来执行此操作。 以下各节将讨论这些内容。com.datastax.oss.driver.api.core.CqlSession
对于那些不熟悉如何使用基于 Java 的 Bean 元数据而不是基于 XML 的元数据来配置 Spring 容器的人,请参阅此处参考文档中的高级介绍以及此处的详细文档。 |
11.3.1. 使用基于 Java 的元数据注册会话实例
您可以使用Java 配置类来配置反应式 Cassandra 支持。 响应式 Cassandra 支持适应 a,以在异步驱动程序之上提供反应式处理模型。CqlSession
反应式的配置类似于命令式。 我们提供了带有预定义默认值的支持配置类,并且只需要特定于环境的信息来配置 Apache Cassandra 的 Spring 数据。 反应支持的基类是。 此配置类扩展了命令式,因此反应式支持还配置命令式 API 支持。 以下示例演示如何在配置类中注册 Apache Cassandra bean: 反应式应用程序CassandraConfiguration .使用 注册 Apache Cassandra 豆的春季数据CqlSession
CqlSession
AbstractReactiveCassandraConfiguration
AbstractCassandraConfiguration
AbstractReactiveCassandraConfiguration
@Configuration
public class ReactiveCassandraConfiguration extends AbstractReactiveCassandraConfiguration {
/*
* Provide a contact point to the configuration.
*/
public String getContactPoints() {
return "localhost";
}
/*
* Provide a keyspace name to the configuration.
*/
public String getKeyspaceName() {
return "mykeyspace";
}
}
前面示例中的配置类已启用架构管理,可在启动期间创建 CQL 对象。 有关更多详细信息,请参阅架构管理。
11.4. ReactiveCqlTemplate
类是核心 CQL 包中的中心类。 它处理资源的创建和释放。 它执行核心 CQL 工作流的基本任务,例如创建和运行语句,让应用程序代码提供 CQL 和提取结果。 该类运行 CQL 查询和更新语句,并执行迭代覆盖实例和返回参数值的提取。 它还捕获 CQL 异常,并将其转换为包中定义的通用、信息量更大的异常层次结构。ReactiveCqlTemplate
ReactiveCqlTemplate
ResultSet
org.springframework.dao
当你在代码中使用时,你只需要实现回调接口,这些接口有一个明确定义的协定。 给定 a,回调接口使用提供的 CQL 和任何必要的参数参数创建预准备语句。 接口从 a 的每一行中提取值。ReactiveCqlTemplate
Connection
ReactivePreparedStatementCreator
RowCallbackHandler
ReactiveResultSet
可以通过引用的直接实例化在DAO实现中使用,也可以在Spring容器中配置,并作为Bean提供给DAO,reference.isReactiveCassandraTemplate的基础构建块。ReactiveCqlTemplate
ReactiveSessionFactory
ReactiveCqlTemplate
此类发出的所有 CQL 都记录在与模板实例的完全限定类名对应的类别下的级别(通常,但如果使用该类的自定义子类,则可能会有所不同)。DEBUG
ReactiveCqlTemplate
ReactiveCqlTemplate
11.4.1. 类用法示例ReactiveCqlTemplate
本节提供了一些类用法的示例。 这些示例并不是公开的所有功能的详尽列表。 请参阅随之而来的Javadocs了解这一点。ReactiveCqlTemplate
ReactiveCqlTemplate
查询 (选择) 使用ReactiveCqlTemplate
以下查询获取关系中的行数:
Mono<Integer> rowCount = reactiveCqlTemplate.queryForObject("SELECT COUNT(*) FROM t_actor", Integer.class);
以下查询使用绑定变量:
Mono<Integer> countOfActorsNamedJoe = reactiveCqlTemplate.queryForObject(
"SELECT COUNT(*) FROM t_actor WHERE first_name = ?", Integer.class, "Joe");
以下示例查询:String
Mono<String> lastName = reactiveCqlTemplate.queryForObject(
"SELECT last_name FROM t_actor WHERE id = ?",
String.class, 1212L);
以下示例查询并填充单个域对象:
Mono<Actor> actor = reactiveCqlTemplate.queryForObject(
"SELECT first_name, last_name FROM t_actor WHERE id = ?",
new RowMapper<Actor>() {
public Actor mapRow(Row row, int rowNum) {
Actor actor = new Actor();
actor.setFirstName(row.getString("first_name"));
actor.setLastName(row.getString("last_name"));
return actor;
}},
1212L);
以下示例查询并填充多个域对象:
Flux<Actor> actors = reactiveCqlTemplate.query(
"SELECT first_name, last_name FROM t_actor",
new RowMapper<Actor>() {
public Actor mapRow(Row row, int rowNum) {
Actor actor = new Actor();
actor.setFirstName(row.getString("first_name"));
actor.setLastName(row.getString("last_name"));
return actor;
}
});
如果最后两个代码片段确实存在于同一个应用程序中,那么删除两个匿名内部类中存在的重复项并将它们提取到单个类(通常是嵌套类)中是有意义的,然后DAO方法可以根据需要引用该类。RowMapper
static
例如,最好按如下方式编写最后一个代码片段:
Flux<Actor> findAllActors() {
return reactiveCqlTemplate.query("SELECT first_name, last_name FROM t_actor", ActorMapper.INSTANCE);
}
enum ActorMapper implements RowMapper<Actor> {
INSTANCE;
public Actor mapRow(Row row, int rowNum) {
Actor actor = new Actor();
actor.setFirstName(row.getString("first_name"));
actor.setLastName(row.getString("last_name"));
return actor;
}
}
INSERT
,,和UPDATE
DELETE
ReactiveCqlTemplate
您可以使用该方法执行、和操作。 参数值通常作为变量参数提供,或者作为对象数组提供。execute(…)
INSERT
UPDATE
DELETE
以下示例演示如何使用以下命令执行操作:INSERT
ReactiveCqlTemplate
Mono<Boolean> applied = reactiveCqlTemplate.execute(
"INSERT INTO t_actor (first_name, last_name) VALUES (?, ?)",
"Leonor", "Watling");
以下示例演示如何使用以下命令执行操作:UPDATE
ReactiveCqlTemplate
Mono<Boolean> applied = reactiveCqlTemplate.execute(
"UPDATE t_actor SET last_name = ? WHERE id = ?",
"Banjo", 5276L);
以下示例演示如何使用以下命令执行操作:DELETE
ReactiveCqlTemplate
Mono<Boolean> applied = reactiveCqlTemplate.execute(
"DELETE FROM actor WHERE id = ?",
actorId);
11.5. 异常翻译
Spring 框架为各种数据库和映射技术提供了异常转换。 这传统上是针对JDBC和JPA的。Spring Data for Apache Cassandra 通过提供接口的实现将此功能扩展到 Apache Cassandra。org.springframework.dao.support.PersistenceExceptionTranslator
映射到 Spring 一致的数据访问异常层次结构背后的动机是让您编写可移植和描述性的异常处理代码,而无需针对特定的 Cassandra 异常进行编码和处理。 Spring 的所有数据访问异常都是从类继承而来的,因此您可以确保可以在单个 try-catch 块中捕获所有与数据库相关的异常。DataAccessException
ReactiveCqlTemplate
并尽早传播异常。 在处理反应序列期间发生的异常将作为错误信号发出。ReactiveCassandraTemplate
11.6. 简介ReactiveCassandraTemplate
Theclass,位于包中,是Spring Data的Cassandra支持中的中心类。 它提供了丰富的功能集来与数据库进行交互。 该模板提供了方便的数据访问操作来创建、更新、删除和查询 Cassandra,并提供域对象和 Cassandra 表行之间的映射。ReactiveCassandraTemplate
org.springframework.data.cassandra
配置完成后,是线程安全的,可以在多个实例中重用。 |
Cassandra 表中的行和域类之间的映射是通过委托给接口的实现来完成的。 Spring 提供了一个默认的实现,但你也可以编写自己的自定义转换器。 有关更多详细信息,请参阅“映射”。CassandraConverter
MappingCassandraConverter
该类实现接口。 尽可能多地,方法名称与 Cassandra 中的名称匹配,以使熟悉 Cassandra 的开发人员熟悉 API。ReactiveCassandraTemplate
ReactiveCassandraOperations
ReactiveCassandraOperations
例如,您可以找到,,,和等方法。 设计目标是尽可能轻松地在使用基本Cassandra驱动程序和之间转换。 这两个 API 之间的主要区别在于可以传递域对象,而不是 CQL 和查询对象。select
insert
delete
update
ReactiveCassandraOperations
ReactiveCassandraOperations
在实例上引用操作的首选方法是通过其接口。 |
默认转换器实现 foris。 虽然可以使用其他元数据来指定对象到行的映射,但它也可以通过使用字段和表名映射的约定来转换不包含其他元数据的对象。 这些约定以及映射注释的使用在“映射”中进行了解释。ReactiveCassandraTemplate
MappingCassandraConverter
MappingCassandraConverter
另一个核心功能是异常翻译。 Cassandra Java 驱动程序抛出的异常被转换为 Spring 的可移植数据访问异常层次结构。 有关详细信息,请参阅“异常转换”。CassandraTemplate
11.6.1. 实例化ReactiveCassandraTemplate
ReactiveCassandraTemplate
应始终配置为 Spring bean,尽管前面的示例演示了如何直接实例化它。 但是,本节假设模板在 Spring 模块中使用,因此它也假设正在使用 Spring 容器。
有两种方法可以获取 a,具体取决于您加载 Spring 的方式:ReactiveCassandraTemplate
ApplicationContext
- 自动布线
- Bean 查找与应用程序上下文
自动布线
您可以自动连接到您的项目中,如以下示例所示:ReactiveCassandraTemplate
@Autowired
private ReactiveCassandraOperations reactiveCassandraOperations;
像所有 Spring 自动接线一样,这假设只有一个类型的 bean。 如果您有多个 bean(如果您在同一项目中使用多个键空间,则可能是这种情况),那么您可以使用注释来指定要自动连线的 bean。ReactiveCassandraOperations
ApplicationContext
ReactiveCassandraTemplate
@Qualifier
@Autowired
@Qualifier("keyspaceTwoTemplateBeanId")
private ReactiveCassandraOperations reactiveCassandraOperations;
豆查找与ApplicationContext
您还可以从中查找 bean,如以下示例所示:ReactiveCassandraTemplate
ApplicationContext
ReactiveCassandraOperations reactiveCassandraOperations = applicationContext.getBean("reactiveCassandraOperations", ReactiveCassandraOper
11.7. 保存、更新和删除行
ReactiveCassandraTemplate
为您提供了一种保存、更新和删除域对象的简单方法,并将这些对象映射到 Cassandra 中管理的表。
11.7.1. 插入和更新行的方法
CassandraTemplate
有几种方便的方法来保存和插入对象。 为了对转换过程进行更精细的控制,您可以使用(例如,)注册 Springinstances。Converter
MappingCassandraConverter
Converter<Row, Person>
插入操作和更新操作之间的区别在于操作不插入值。 |
使用操作的简单情况是保存POJO。在这种情况下,表名由简单类名(而不是完全限定的类名)确定。 可以使用映射元数据覆盖用于存储对象的表。INSERT
插入或更新时,必须设置属性。 Apache Cassandra无法生成ID。id
下面的示例使用保存操作并检索其内容:
例 63。通过使用插入和检索对象CassandraTemplate
…
Person bob = new Person("Bob", 33);
cassandraTemplate.insert(bob);
Mono<Person> queriedBob = reactiveCassandraTemplate.selectOneById(query(where("age").is(33)), Person.class);
您可以使用以下操作进行插入和保存:
-
void
insert:在 Apache Cassandra 表中插入对象。(Object objectToSave)
-
WriteResult
insert:在 Apache Cassandra 表中插入对象并应用。(Object objectToSave, InsertOptions options)
InsertOptions
您可以使用以下更新操作:
-
void
update:更新 Apache Cassandra 表中的对象。(Object objectToSave)
-
WriteResult
update:更新 Apache Cassandra 表中的对象并应用。(Object objectToSave, UpdateOptions options)
UpdateOptions
还可以使用老式方式编写自己的 CQL 语句,如以下示例所示:
String cql = "INSERT INTO person (age, name) VALUES (39, 'Bob')";
Mono<Boolean> applied = reactiveCassandraTemplate.getReactiveCqlOperations().execute(cql);
您还可以在使用和时配置其他选项,例如 TTL、一致性级别和轻量级事务。InsertOptions
UpdateOptions
我的行插入到哪个表中?
您可以通过两种方式管理用于对表进行操作的表名。 默认表名是更改为以小写字母开头的简单类名。 因此,类的实例将存储在表中。 第二种方法是在注释中指定表名。com.example.Person
person
@Table
11.7.2. 更新表中的行
对于更新,您可以选择更新多个行。
以下示例显示如何通过使用分配将一次性 $50.00 奖金添加到余额中来更新单个帐户对象:+
例 64。使用 更新行ReactiveCasandraTemplate
…
Mono<Boolean> wasApplied = reactiveCassandraTemplate.update(Query.query(where("id").is("foo")),
Update.create().increment("balance", 50.00), Account.class);
除了前面讨论的之外,我们还使用 anobject 提供了更新定义。 该类具有与可用于 Apache Cassandra 的更新分配匹配的方法。Query
Update
Update
大多数方法返回对象以提供用于代码样式目的的流畅 API。Update
有关更多详细信息,请参阅“执行行更新的方法”。
12. 卡桑德拉存储库
本章详细介绍了 Spring 数据存储库对 Apache Cassandra 的支持。 Cassandra的存储库支持建立在“使用Spring Data Repository”中解释的核心存储库支持之上。 Cassandra 存储库使用及其 wiredas 基础设施 bean。 在继续之前,您应该了解那里解释的基本概念。CassandraTemplate
CqlTemplate
12.1. 用法
要访问存储在Apache Cassandra中的域实体,您可以使用Spring Data复杂的存储库支持,这大大简化了DAO的实施。 为此,请为存储库创建一个接口,如以下示例所示:
例 65。示例人员实体
@Table
public class Person {
@Id
private String id;
private String firstname;
private String lastname;
// … getters and setters omitted
}
请注意,该实体具有名为 namedof 类型的属性。 中使用的默认序列化机制(支持存储库支持)将名为的属性视为行 ID。id
String
CassandraTemplate
id
以下示例显示了持久化的存储库定义:Person
例 66。持久化的基本存储库接口Person
public interface PersonRepository extends CrudRepository<Person, String> {
// additional custom finder methods go here
}
目前,前面示例中的接口仅用于键入目的,但稍后我们将向其添加其他方法。
接下来,在 Spring 配置中,添加以下内容(如果使用 Java 进行配置):
如果要使用 Java 配置,请使用注释。 注释具有与命名空间元素相同的属性。 如果未配置基本包,基础结构将扫描带批注的配置类的包。 以下示例演示如何使用注释:@EnableCassandraRepositories
@EnableCassandraRepositories
例 67。存储库的配置
爪哇岛
.XML
@Configuration
@EnableCassandraRepositories
class ApplicationConfig extends AbstractCassandraConfiguration {
@Override
protected String getKeyspaceName() {
return "keyspace";
}
public String[] getEntityBasePackages() {
return new String[] { "com.oreilly.springdata.cassandra" };
}
}
命名空间元素导致扫描基本包以查找扩展接口,并为找到的每个接口创建 Spring bean。 默认情况下,存储库使用调用的 aSpring bean 进行连接,因此只有在偏离此约定时才需要显式配置。cassandra:repositories
CrudRepository
CassandraTemplate
cassandraTemplate
cassandra-template-ref
由于我们的域存储库可扩展,因此它为您提供了基本的 CRUD 操作。 使用存储库实例是将存储库作为依赖项注入客户端的问题,如以下示例通过自动布线所做的那样:CrudRepository
PersonRepository
例 68。对个人实体的基本访问权限
@RunWith(SpringRunner.class)
@ContextConfiguration
public class PersonRepositoryTests {
@Autowired PersonRepository repository;
@Test
public void readsPersonTableCorrectly() {
List<Person> persons = repository.findAll();
assertThat(persons.isEmpty()).isFalse();
}
}
Cassandra 存储库支持分页和排序,以便对实体进行分页和排序访问。 Cassandra 分页需要分页状态才能在页面中只进导航。 跟踪当前分页状态,并允许创建 ato 请求下一页。 以下示例演示如何设置对实体的分页访问:Slice
Pageable
Person
例 69。对实体的分页访问Person
@RunWith(SpringRunner.class)
@ContextConfiguration
public class PersonRepositoryTests {
@Autowired PersonRepository repository;
@Test
public void readsPagesCorrectly() {
Slice<Person> firstBatch = repository.findAll(CassandraPageRequest.first(10));
assertThat(firstBatch).hasSize(10);
Page<Person> nextBatch = repository.findAll(firstBatch.nextPageable());
// …
}
}
Cassandra 存储库不扩展,因为使用限制/偏移的经典分页模式不适用于 Cassandra。 |
前面的示例创建了一个具有 Spring 单元测试支持的应用程序上下文,该上下文将基于注释的依赖注入到测试类中。 在测试用例(测试方法)中,我们使用存储库来查询数据存储。 我们调用请求所有实例的存储库查询方法。Person
12.2. 查询方法
您通常在存储库上触发的大多数数据访问操作都会导致对 Apache Cassandra 数据库执行查询。 定义此类查询是在存储库接口上声明方法的问题。 下面的示例演示了许多此类方法声明:
例 70。具有查询方法的人员存储库
public interface PersonRepository extends CrudRepository<Person, String> {
List<Person> findByLastname(String lastname);
Slice<Person> findByFirstname(String firstname, Pageable pageRequest);
List<Person> findByFirstname(String firstname, QueryOptions opts);
List<Person> findByFirstname(String firstname, Sort sort);
Person findByShippingAddress(Address address);
Person findFirstByShippingAddress(Address address);
Stream<Person> findAllBy();
@AllowFiltering
List<Person> findAllByAge(int age);
}
该方法显示所有给定人员的查询。 查询派生自分析约束的方法名称,可以与约束连接。 因此,方法名称导致查询表达式。 |
将分页应用于查询。 您可以为方法签名配备参数,并让方法返回实例,我们会自动相应地对查询进行分页。 |
传递对象会在执行之前将查询选项应用于生成的查询。 |
对查询应用动态排序。 您可以在方法签名中添加参数,Spring Data 会自动将排序应用于查询。 |
显示您可以使用注册的实例基于非基元类型的属性进行查询。 如果找到多个匹配项,则投掷。 |
使用关键字将查询限制为仅第一个结果。 与上述方法不同,如果找到多个匹配项,此方法不会引发异常。 |
使用 Java 8 在迭代流时读取和转换单个元素。 |
显示用 批注的查询方法,以允许服务器端筛选。 |
查询非主键属性需要二级索引。 |
下表显示了可在查询方法中使用的关键字的简短示例:
表 7.查询方法支持的关键字
关键词 | 样本 | 逻辑结果 |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
12.3. 仓库删除查询
上表中的关键字可以与创建删除匹配文档的查询结合使用。delete…By
interface PersonRepository extends Repository<Person, String> {
void deleteWithoutResultByLastname(String lastname);
boolean deleteByLastname(String lastname);
}
删除查询返回查询是否已应用或终止而不返回值使用。void
12.3.1. 预测
Spring 数据查询方法通常返回由存储库管理的聚合根的一个或多个实例。 但是,有时可能需要基于这些类型的某些属性创建投影。 Spring 数据允许对专用返回类型进行建模,以更有选择性地检索托管聚合的部分视图。
假设存储库和聚合根类型,如以下示例所示:
例 71。示例聚合和存储库
class Person {
@Id UUID id;
String firstname, lastname;
Address address;
static class Address {
String zipCode, city, street;
}
}
interface PersonRepository extends Repository<Person, UUID> {
Collection<Person> findByLastname(String lastname);
}
现在假设我们只想检索人员的姓名属性。 Spring Data提供了什么手段来实现这一目标?本章的其余部分将回答这个问题。
基于接口的投影
将查询结果限制为仅 name 属性的最简单方法是声明一个接口,该接口公开要读取的属性的访问器方法,如以下示例所示:
例 72。用于检索属性子集的投影接口
interface NamesOnly {
String getFirstname();
String getLastname();
}
这里重要的一点是,此处定义的属性与聚合根中的属性完全匹配。 这样做可以添加查询方法,如下所示:
例 73。使用基于接口的投影和查询方法的存储库
interface PersonRepository extends Repository<Person, UUID> {
Collection<NamesOnly> findByLastname(String lastname);
}
查询执行引擎在运行时为返回的每个元素创建该接口的代理实例,并将对公开方法的调用转发到目标对象。
在 yourThat 中声明方法会覆盖基方法(例如,声明在、特定于存储的存储库接口或 the)会导致对基方法的调用,而不管声明的返回类型如何。请确保使用兼容的返回类型,因为基方法不能用于投影。某些存储模块支持注释,以将重写的基方法转换为查询方法,然后可用于返回投影。 |
投影可以递归使用。如果还希望包含某些信息,请为其创建一个投影接口,并从声明中返回该接口,如以下示例所示:Address
getAddress()
例 74。用于检索属性子集的投影接口
interface PersonSummary {
String getFirstname();
String getLastname();
AddressSummary getAddress();
interface AddressSummary {
String getCity();
}
}
在方法调用时,将获取目标实例的属性并依次包装到投影代理中。address
封闭式投影
其访问器方法都与目标聚合的属性匹配的投影接口被视为封闭投影。以下示例(我们在本章前面也使用过)是一个封闭投影:
例 75。封闭投影
interface NamesOnly {
String getFirstname();
String getLastname();
}
如果您使用封闭投影,Spring Data 可以优化查询执行,因为我们知道支持投影代理所需的所有属性。 有关这方面的更多详细信息,请参阅参考文档中特定于模块的部分。
开放投影
投影接口中的访问器方法还可用于通过注释来计算新值,如以下示例所示:@Value
例 76。开放式投影
interface NamesOnly {
@Value("#{target.firstname + ' ' + target.lastname}")
String getFullName();
…
}
支持投影的聚合根在变量中可用。 投影接口使用是开放式投影。 在这种情况下,Spring 数据无法应用查询执行优化,因为 SpEL 表达式可以使用聚合根的任何属性。target
@Value
使用的表达式不应该太复杂 — 您希望避免对变量进行编程。 对于非常简单的表达式,一种选择可能是采用默认方法(Java 8 中引入),如以下示例所示:@Value
String
例 77。使用自定义逻辑的默认方法的投影接口
interface NamesOnly {
String getFirstname();
String getLastname();
default String getFullName() {
return getFirstname().concat(" ").concat(getLastname());
}
}
此方法要求您能够完全基于投影接口上公开的其他访问器方法实现逻辑。 第二个更灵活的选项是在 Spring Bean 中实现自定义逻辑,然后从 SpEL 表达式中调用该逻辑,如以下示例所示:
例 78。示例人员对象
@Component
class MyBean {
String getFullName(Person person) {
…
}
}
interface NamesOnly {
@Value("#{@myBean.getFullName(target)}")
String getFullName();
…
}
请注意 SpEL 表达式如何引用和调用该方法,并将投影目标作为方法参数转发。 SpEL 表达式评估支持的方法也可以使用方法参数,然后可以从表达式中引用这些参数。 方法参数可通过名为的数组获得。下面的示例演示如何从数组中获取方法参数:myBean
getFullName(…)
Object
args
args
例 79。示例人员对象
interface NamesOnly {
@Value("#{args[0] + ' ' + target.firstname + '!'}")
String getSalutation(String prefix);
}
同样,对于更复杂的表达式,您应该使用 Spring Bean 并让表达式调用方法,如前所述。
可为空的包装器
投影接口中的 Getter 可以使用可为空的包装器来提高空安全性。目前支持的包装器类型包括:
-
java.util.Optional
-
com.google.common.base.Optional
-
scala.Option
-
io.vavr.control.Option
例 80。使用可为空包装器的投影接口
interface NamesOnly {
Optional<String> getFirstname();
}
如果基础投影值不是,则使用包装器的当前表示形式返回值。 如果支持值为 ,则 getter 方法返回所用包装类型的空表示形式。null
null
基于类的投影 (DTO)
定义投影的另一种方法是使用值类型 DTO(数据传输对象),用于保存应检索的字段的属性。 这些 DTO 类型的使用方式与投影接口的使用方式完全相同,只是不会发生代理,并且不能应用嵌套投影。
如果存储通过限制要加载的字段来优化查询执行,则要加载的字段由公开的构造函数的参数名称确定。
以下示例显示了一个投影 DTO:
例 81。一个突出的DTO
class NamesOnly {
private final String firstname, lastname;
NamesOnly(String firstname, String lastname) {
this.firstname = firstname;
this.lastname = lastname;
}
String getFirstname() {
return this.firstname;
}
String getLastname() {
return this.lastname;
}
// equals(…) and hashCode() implementations
}
避免投影 DTO 的样板代码 你可以通过使用ProjectLombok来大大简化DTO的代码,它提供了anannotation(不要与前面的接口示例中所示的Spring'sannotation混淆)。 如果您使用龙目岛项目的注释,前面显示的示例 DTO 将变为以下内容: @Value 字段是默认的,该类公开一个构造函数,该构造函数采用所有字段并自动获取实现的 sand方法。 |
动态投影
到目前为止,我们已经使用投影类型作为集合的返回类型或元素类型。 但是,您可能希望选择要在调用时使用的类型(这使其成为动态的)。 若要应用动态投影,请使用查询方法,如以下示例所示:
例 82。使用动态投影参数的存储库
interface PersonRepository extends Repository<Person, UUID> {
<T> Collection<T> findByLastname(String lastname, Class<T> type);
}
这样,该方法可用于按原样获取聚合或应用投影,如以下示例所示:
例 83。使用具有动态投影的存储库
void someMethod(PersonRepository people) {
Collection<Person> aggregates =
people.findByLastname("Matthews", Person.class);
Collection<NamesOnly> aggregates =
people.findByLastname("Matthews", NamesOnly.class);
}
检查类型的查询参数是否符合动态投影参数的条件。 如果查询的实际返回类型等于参数的泛型参数类型,则匹配参数不可用于查询或 SpEL 表达式。 如果要使用 aparameter 作为查询参数,请确保使用其他泛型参数,例如。 |
12.3.2. 查询选项
可以通过传递对象来指定查询方法的查询选项。 这些选项适用于实际查询之前的查询 execution.is 被视为非查询参数,并且不被视为查询参数值。 查询选项适用于派生方法和字符串存储库方法。QueryOptions
QueryOptions
@Query
若要静态设置一致性级别,请在查询方法上使用注释。 声明的一致性级别在每次执行查询时应用于查询。 以下示例将一致性级别设置为:@Consistency
ConsistencyLevel.LOCAL_ONE
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 实例上配置以下参数来控制提取大小、一致性级别和重试策略默认值:、 和。 如果未设置特定查询选项,则应用默认值。 |
12.3.3. CDI 集成
存储库接口的实例通常由容器创建,在处理 Spring 数据时,Spring 容器是最自然的选择。 Spring Data for Apache Cassandra 附带了一个自定义的 CDI 扩展,允许在 CDI 环境中使用存储库抽象。 扩展是 JAR 的一部分。要激活它,请将 Apache Cassandra JAR 的 Spring 数据放入您的类路径中。 现在,您可以通过实现 CDI 生产者来设置基础结构,如以下 examlpe 所示:CassandraTemplate
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();
}
}
Apache Cassandra CDI 扩展的 Spring Data 作为 CDI bean 选取,并在容器请求存储库类型的 Bean 时为 Spring Data 存储库创建代理。 因此,获取 Spring 数据存储库的实例是声明注入属性的问题,如以下示例所示:CassandraOperations
class RepositoryClient {标签:String,示例,Spring,查询,使用,Apache,Data,Cassandra From: https://blog.51cto.com/u_15326439/5878234
@Inject PersonRepository repository;
public void businessMethod() {
List<Person> people = repository.findAll();
}
}