9.11.准备好的报表
可以将多次执行的 CQL 语句准备好并存储在一个PreparedStatement对象中,以提高查询性能。驱动程序和 Cassandra 都维护着PreparedStatement查询到其元数据的映射。您可以通过以下抽象使用准备好的语句:
- CqlTemplate 通过API的选择
- CassandraTemplate 通过启用准备好的语句
- Cassandra 存储库,因为它们建立在 CassandraTemplate
9.11.1.使用CqlTemplate
的CqlTemplate类(及其异步和反应性变体)提供的各种方法接受静态CQL,Statement对象和PreparedStatementCreator。接受没有附加参数的静态 CQL 的方法通常按原样运行 CQL 语句,无需进一步处理。接受静态 CQL 与参数数组(例如execute(String cql, Object… args)和queryForRows(String cql, Object… args))组合的方法使用准备好的语句。在内部,这些方法创建一个PreparedStatementCreator和PreparedStatementBinder对象来准备语句,然后将值绑定到语句以运行它。Spring Data Cassandra 通常对准备好的语句使用基于索引的参数绑定。
从 Cassandra 驱动程序版本 4 开始,准备好的语句缓存在驱动程序级别,从而无需跟踪应用程序中的准备好的语句。
以下示例显示如何使用参数化的预准备语句发出查询:
代码语言:javascript复制String lastName = cqlTemplate.queryForObject(
"SELECT last_name FROM t_actor WHERE id = ?",
String.class, 1212L);
如果您需要对语句准备和参数绑定进行更多控制(例如,使用命名绑定参数),您可以通过使用PreparedStatementCreator和PreparedStatementBinder参数调用查询方法来完全控制准备好的语句创建和参数绑定:
代码语言:javascript复制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 - 将参数绑定到准备好的语句的实用程序类。
9.11.2.使用CassandraTemplate
该CassandraTemplate班是建立在顶部CqlTemplate,以提供更高的抽象水平。可以CassandraTemplate通过调用setUsePreparedStatements(false)相应的setUsePreparedStatements(true). 请注意,CassandraTemplate默认情况下启用了预准备语句的使用。
以下示例显示了生成和接受 CQL 的方法的使用:
代码语言:javascript复制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);
调用实体绑定方法(例如select(Query, Class<T>)或update(Query, Update, Class<T>)构建 CQL 语句本身)以执行预期操作。某些CassandraTemplate方法(例如select(Statement<?>, Class<T>))还接受 CQLStatement对象作为其 API 的一部分。
在调用接受Statement带有SimpleStatement对象的a 的方法时,可以参与准备好的语句。模板 API 提取查询字符串和参数(位置和命名参数)并使用这些来准备、绑定和运行语句。非SimpleStatement对象不能与准备好的语句一起使用。
9.11.3.缓存准备好的语句
从 Cassandra 驱动程序 4.0 开始,准备好的语句由CqlSession缓存缓存,因此可以准备两次相同的字符串。以前的版本需要在驱动程序之外缓存准备好的语句。另请参阅有关 Prepared Statements的驱动程序文档以获取进一步参考。
10. 响应式 Cassandra 支持
反应式 Cassandra 支持包含广泛的功能:
- Spring 配置支持使用基于 Java 的@Configuration类。
- ReactiveCqlTemplate 通过正确处理常见的 Cassandra 数据访问操作来提高生产力的辅助类。
- ReactiveCassandraTemplate通过ReactiveCassandraOperations以反应方式使用来提高生产力的助手类。它包括表和 POJO 之间的集成对象映射。
- 异常转换为 Spring 的可移植数据访问异常层次结构。
- 与 Spring 的转换服务集成的功能丰富的对象映射。
- 基于 Java 的查询、标准和更新 DSL。
- Repository接口的自动实现,包括对自定义查找器方法的支持。
对于大多数面向数据的任务,您可以使用ReactiveCassandraTemplate或 存储库支持,它使用丰富的对象映射功能。ReactiveCqlTemplate通常用于增加计数器或执行临时 CRUD 操作。ReactiveCqlTemplate还提供了回调方法,可以轻松获取低级 API 对象,例如 com.datastax.oss.driver.api.core.CqlSession,让您可以直接与 Cassandra 通信。Spring Data for Apache Cassandra 对各种 API 中的对象使用与 DataStax Java 驱动程序中的对象一致的命名约定,以便立即熟悉它们,并且您可以将现有知识映射到 Spring API。
10.1.入门
Spring Data for Apache Cassandra 需要 Apache Cassandra 2.1 或更高版本以及 Datastax Java Driver 4.0 或更高版本。快速设置和引导工作环境的一种简单方法是在STS 中创建基于 Spring 的项目或使用Spring Initializer。
首先,您需要设置一个正在运行的 Apache Cassandra 服务器。有关 如何启动 Apache Cassandra 的说明,请参阅 Apache Cassandra 快速入门指南。一旦安装完毕,开始Cassandra是通常运行以下命令即可: CASSANDRA_HOME/bin/cassandra -f。
要在 STS 中创建 Spring 项目,请转到 File → New → Spring Template Project → Simple Spring Utility Project,然后在出现提示时按 Yes。然后输入项目和包名称,例如 org.spring.data.cassandra.example.
然后,您可以将以下依赖项声明添加到 pom.xml 文件的dependencies部分。
代码语言:javascript复制<dependencies>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-cassandra</artifactId>
<version>3.3.0</version>
</dependency>
</dependencies>
此外,您应该将 pom.xml 文件中的 Spring 版本更改为如下:
代码语言:javascript复制<spring.framework.version>5.3.13</spring.framework.version>
如果使用里程碑版本而不是 GA 版本,您还需要将 Maven 的 Spring Milestone 存储库的位置添加到您的 pom.xml 文件中,使其与您的<dependencies/>元素处于同一级别,如下所示:
代码语言:javascript复制<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 中存储和读取域对象。
为此,首先创建一个简单的域对象类来持久化,如以下示例所示:
代码语言:javascript复制package org.springframework.data.cassandra.example;
import org.springframework.data.cassandra.core.mapping.PrimaryKey;
import org.springframework.data.cassandra.core.mapping.Table;
@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());
}
}
接下来,创建要运行的主应用程序,如以下示例所示:
接下来,创建要运行的主应用程序,如以下示例所示:
代码语言:javascript复制package org.springframework.data.cassandra.example;
import reactor.core.publisher.Mono;
import java.util.UUID;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.cassandra.core.ReactiveCassandraOperations;
import org.springframework.data.cassandra.core.ReactiveCassandraTemplate;
import org.springframework.data.cassandra.core.cql.session.DefaultBridgedReactiveSession;
import org.springframework.data.cassandra.core.query.Criteria;
import org.springframework.data.cassandra.core.query.Query;
import com.datastax.oss.driver.api.core.CqlSession;
public class ReactiveCassandraApplication {
private static final Logger LOGGER = LoggerFactory.getLogger(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 -> LOGGER.info(it.toString()))
.then(template.truncate(Person.class))
.block();
cqlSession.close();
}
}
即使在这个简单的例子中,也有一些值得注意的地方需要指出:
- 完全同步的流程不会从反应式基础设施中受益,因为反应式编程模型需要同步。
- 您可以ReactiveCassandraTemplate使用 Cassandra创建一个实例CqlSession。
- 您必须将 POJO 注释为 Cassandra@Table并注释@PrimaryKey. 或者,您可以覆盖这些映射名称以匹配您的 Cassandra 数据库表和列名称。
- 您可以使用原始 CQL 或 DataStax QueryBuilderAPI 来构建您的查询。
10.2.示例库
一个Github上库包含了几个例子,您可以下载和玩得到如何图书馆工作的感觉。
10.3.使用 Spring 连接到 Cassandra
在 Spring 中使用 Apache Cassandra 时的首要任务之一是 com.datastax.oss.driver.api.core.CqlSession使用 Spring IoC 容器创建对象。您可以通过使用基于 Java 的 bean 元数据或使用基于 XML 的 bean 元数据来实现。这些将在以下各节中讨论。
对于那些不熟悉如何配置使用基于Java bean的元数据,而不是基于XML的元数据Spring容器,请参阅参考文档的高级介绍 这里 还有详细的文档在这里。