对于最新的稳定版本,请使用 Spring Data Cassandra 4.3.1! |
对于最新的稳定版本,请使用 Spring Data Cassandra 4.3.1! |
该类(及其反应式变体)位于软件包中,是 Spring 的 Cassandra 支持中的核心类,它提供了丰富的功能集来与数据库进行交互。
该模板提供了创建、更新、删除和查询 Cassandra 的便捷操作,并提供域对象与 Cassandra 表中的行之间的映射。CassandraTemplate
ReactiveCassandraTemplate
org.springframework.data.cassandra
配置完成后,模板实例是线程安全的,可以在多个实例之间重复使用。 |
Cassandra 中的行和应用程序域类之间的映射是通过委托给接口的实现来完成的。
Spring 提供了一个默认的实现,但您也可以编写自己的自定义转换器。
有关更多详细信息,请参阅有关 Cassandra 转换的部分。CassandraConverter
MappingCassandraConverter
该类实现接口,其反应式变体实现 。
在尽可能的情况下,这些方法都以 Cassandra 中可用的方法命名,以使已经熟悉 Cassandra 的开发人员熟悉 API。CassandraTemplate
CassandraOperations
ReactiveCassandraTemplate
ReactiveCassandraOperations
[Reactive]CassandraOperations
例如,您可以找到 、 、 和 等方法。
设计目标是尽可能轻松地在基本 Cassandra 驱动程序的使用和 .
这两个 API 之间的主要区别在于可以传递域对象,而不是 CQL 和查询对象。select
insert
delete
update
[Reactive]CassandraOperations
CassandraOperations
引用实例上的操作的首选方法是通过接口。[Reactive]CassandraTemplate [Reactive]CassandraOperations |
使用的默认转换器实现是 。
虽然可以使用其他元数据来指定对象到行的映射,但它也可以通过使用字段和表名映射的一些约定来转换不包含其他元数据的对象。
这些约定以及映射注释的使用在“映射”一章中进行了解释。[Reactive]CassandraTemplate
MappingCassandraConverter
MappingCassandraConverter
另一个核心特性是将 Cassandra Java 驱动程序中抛出的异常转换为 Spring 的可移植数据访问异常层次结构。
有关详细信息,请参阅有关异常翻译的部分。[Reactive]CassandraTemplate
模板 API 具有不同的执行模型风格。
基本使用阻塞(命令式同步)执行模型。
您可以用于异步执行和与实例的同步,也可以用于响应式执行。CassandraTemplate AsyncCassandraTemplate ListenableFuture ReactiveCassandraTemplate |
配置完成后,模板实例是线程安全的,可以在多个实例之间重复使用。 |
引用实例上的操作的首选方法是通过接口。[Reactive]CassandraTemplate [Reactive]CassandraOperations |
模板 API 具有不同的执行模型风格。
基本使用阻塞(命令式同步)执行模型。
您可以用于异步执行和与实例的同步,也可以用于响应式执行。CassandraTemplate AsyncCassandraTemplate ListenableFuture ReactiveCassandraTemplate |
实例化CassandraTemplate
CassandraTemplate
应该始终配置为 Spring Bean,尽管我们之前展示了一个示例,您可以在其中直接实例化它。
但是,由于我们假设了制作 Spring 模块的上下文,因此我们假设存在 Spring 容器。
有两种方法可以获得 ,具体取决于您加载 Spring 的方式:CassandraTemplate
ApplicationContext
自动接线
您可以将 a 自动连接到您的项目中,如以下示例所示:[Reactive]CassandraOperations
-
Imperative
-
Reactive
@Autowired
private CassandraOperations cassandraOperations;
@Autowired
private ReactiveCassandraOperations reactiveCassandraOperations;
与所有 Spring 自动接线一样,这假设 .
如果您有多个 Bean(如果您在同一项目中使用多个键空间,则就是这种情况),那么您可以使用注释来指定要自动连接的 Bean。[Reactive]CassandraOperations
ApplicationContext
[Reactive]CassandraTemplate
@Qualifier
-
Imperative
-
Reactive
@Autowired
@Qualifier("keyspaceOneTemplateBeanId")
private CassandraOperations cassandraOperations;
@Autowired
@Qualifier("keyspaceOneTemplateBeanId")
private ReactiveCassandraOperations reactiveCassandraOperations;
Bean 查找ApplicationContext
您还可以从 中查找 bean,如以下示例所示:[Reactive]CassandraTemplate
ApplicationContext
-
Imperative
-
Reactive
CassandraOperations cassandraOperations = applicationContext.getBean("cassandraTemplate", CassandraOperations.class);
ReactiveCassandraOperations cassandraOperations = applicationContext.getBean("ReactiveCassandraOperations", ReactiveCassandraOperations.class);
查询行
可以使用 和 类来表示查询,这些类具有反映本机 Cassandra 谓词运算符名称的方法名称,例如 、 、 等。Query
Criteria
lt
lte
is
and 类遵循流畅的 API 样式,因此您可以轻松地将多个方法条件和查询链接在一起,同时具有易于理解的代码。
Java 在创建和实例时使用静态导入以提高可读性。Query
Criteria
Query
Criteria
查询表中的行
在前面的章节中,我们了解了如何使用 on 上的方法检索单个对象。
这样做将返回单个域对象。
我们还可以查询要作为域对象列表返回的行集合。
假设我们有许多对象,其名称和年龄值存储在表中的行中,并且每个人都有一个帐户余额,我们现在可以使用以下代码运行查询:selectOneById
[Reactive]CassandraTemplate
Person
[Reactive]CassandraTemplate
-
Imperative
-
Reactive
import static org.springframework.data.cassandra.core.query.Criteria.where;
import static org.springframework.data.cassandra.core.query.Query.query;
…
List<Person> result = cassandraTemplate.select(query(where("age").is(50))
.and(where("balance").gt(1000.00d)).withAllowFiltering(), Person.class);
import static org.springframework.data.cassandra.core.query.Criteria.where;
import static org.springframework.data.cassandra.core.query.Query.query;
…
Flux<Person> result = reactiveCassandraTemplate.select(query(where("age").is(50))
.and(where("balance").gt(1000.00d)).withAllowFiltering(), Person.class);
、 和 方法将对象作为参数。
此对象定义用于执行查询的条件和选项。
该条件是通过使用具有名为实例化新对象的静态工厂方法的对象指定的。
建议对 和 使用静态导入,以使查询更具可读性。select
selectOne
stream
Query
Criteria
where
Criteria
org.springframework.data.cassandra.core.query.Criteria.where
Query.query
此查询应返回满足指定条件的对象列表。
该类具有以下方法,这些方法对应于 Apache Cassandra 中提供的运算符:Person
Criteria
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
contains :使用运算符创建条件。(Object value)
CONTAINS
-
CriteriaDefinition
containsKey :使用运算符创建条件。(Object key)
CONTAINS KEY
Criteria
创建后不可变。
Query 类的方法
该类具有一些可用于提供查询选项的其他方法:Query
-
Query
by :用于创建对象。(CriteriaDefinition… criteria)
Query
-
Query
和 :用于向查询添加其他条件。(CriteriaDefinition criteria)
-
Query
columns :用于定义要包含在查询结果中的列。(Columns columns)
-
Query
limit :用于将返回结果的大小限制在规定的限制范围内(用于限制)。(Limit limit)
SELECT
-
Query
limit :用于将返回结果的大小限制在规定的限制范围内(用于限制)。(long limit)
SELECT
-
Query
pageRequest:用于将 、 和 与查询关联(用于分页)。(Pageable pageRequest)
Sort
PagingState
fetchSize
-
Query
pagingState :用于将 a 与查询关联(用于分页)。(ByteBuffer pagingState)
ByteBuffer
-
Query
queryOptions :用于与查询关联。(QueryOptions queryOptions)
QueryOptions
-
Query
sort :用于为结果提供排序定义。(Sort sort)
-
Query
withAllowFiltering :用于呈现查询。()
ALLOW FILTERING
Query
创建后不可变。
调用方法会创建新的不可变(中间)对象。Query
查询行的方法
该类具有以下返回行的方法:Query
-
List<T>
select :从表中查询对象类型的列表。(Query query, Class<T> entityClass)
T
-
T
selectOne :从表中查询单个类型的对象。(Query query, Class<T> entityClass)
T
-
Slice<T>
slice :通过从表中查询 of 类型的对象来启动或继续分页。(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
Fluent 模板 API
当涉及到与 Apache Cassandra 的更多低级交互时,接口是核心组件之一。
它提供了广泛的方法。
您可以为每种方法找到多个重载。
它们中的大多数都涵盖了 API 的可选(可为 null)部分。[Reactive]CassandraOperations
FluentCassandraOperations
其反应式变体为提供更易读、更流畅的 API 的常用方法提供了更窄的接口。
入口点 (、 、 和 ) 遵循基于要执行的操作的自然命名方案。
从入口点开始,API 旨在仅提供与上下文相关的方法,这些方法引导开发人员使用调用实际 .
以下示例显示了 Fluent API:ReactiveFluentCassandraOperations
[Reactive]CassandraOperations
query(…)
insert(…)
update(…)
delete(…)
[Reactive]CassandraOperations
-
Imperative
-
Reactive
List<SWCharacter> all = ops.query(SWCharacter.class)
.inTable("star_wars") (1)
.all();
1 | 如果使用定义表名或使用类名作为表名不是问题,请跳过此步骤SWCharacter @Table |
Flux<SWCharacter> all = ops.query(SWCharacter.class)
.inTable("star_wars") (1)
.all();
1 | 如果使用定义表名或使用类名作为表名不是问题,请跳过此步骤SWCharacter @Table |
如果 Cassandra 中的表包含不同类型的实体,例如 的 表内的实体,则可以使用不同的类型来映射查询结果。
您可以使用将结果映射到不同的目标类型,同时仍适用于查询和表名。
下面的示例使用 and 方法:Jedi
SWCharacters
as(Class<?> targetType)
query(Class<?> entityType)
query
as
-
Imperative
-
Reactive
List<Jedi> all = ops.query(SWCharacter.class) (1)
.as(Jedi.class) (2)
.matching(query(where("jedi").is(true)))
.all();
1 | 查询字段将针对类型进行映射。SWCharacter |
2 | 生成的行将映射到 .Jedi |
Flux<Jedi> all = ops.query(SWCharacter.class) (1)
.as(Jedi.class) (2)
.matching(query(where("jedi").is(true)))
.all();
1 | 查询字段将针对类型进行映射。SWCharacter |
2 | 生成的行将映射到 .Jedi |
通过仅提供 类型 到 ,可以直接将投影应用于生成的文档。interface as(Class<?>) |
终止方法 (、 、 和 ) 处理检索单个实体和检索多个实体作为 或 和类似操作之间的切换。first()
one()
all()
stream()
List
Stream
新的 Fluent 模板 API 方法(即 、 、 和 )有效地使用线程安全支持对象来编写 CQL 语句。
但是,它以额外的年轻一代 JVM 堆开销为代价,因为设计基于各种 CQL 语句组件的最终字段和基于突变的构造。
在可能插入或删除大量对象(例如,在循环内部)时,您应该小心。query(..) insert(..) update(..) delete(..) |
1 | 如果使用定义表名或使用类名作为表名不是问题,请跳过此步骤SWCharacter @Table |
1 | 如果使用定义表名或使用类名作为表名不是问题,请跳过此步骤SWCharacter @Table |
1 | 查询字段将针对类型进行映射。SWCharacter |
2 | 生成的行将映射到 .Jedi |
1 | 查询字段将针对类型进行映射。SWCharacter |
2 | 生成的行将映射到 .Jedi |
通过仅提供 类型 到 ,可以直接将投影应用于生成的文档。interface as(Class<?>) |
新的 Fluent 模板 API 方法(即 、 、 和 )有效地使用线程安全支持对象来编写 CQL 语句。
但是,它以额外的年轻一代 JVM 堆开销为代价,因为设计基于各种 CQL 语句组件的最终字段和基于突变的构造。
在可能插入或删除大量对象(例如,在循环内部)时,您应该小心。query(..) insert(..) update(..) delete(..) |
保存、更新和删除行
[Reactive]CassandraTemplate
提供了一种保存、更新和删除域对象并将这些对象映射到 Cassandra 中管理的表的简单方法。
插入和更新行的方法
[Reactive]CassandraTemplate
有几种方便的方法来保存和插入对象。
为了对转换过程进行更精细的控制,您可以将 Spring 实例注册到 (例如,)。Converter
MappingCassandraConverter
Converter<Row, Person>
插入操作和更新操作之间的区别在于,操作不插入值。INSERT null |
使用该操作的简单情况是保存 POJO。
在这种情况下,表名由简单类名(而不是完全限定的类名)确定。
可以使用映射元数据覆盖用于存储对象的表。INSERT
插入或更新时,必须设置该属性。
Apache Cassandra 无法生成 ID。id
以下示例使用 save 操作并检索其内容:
[Reactive]CassandraTemplate
-
Imperative
-
Reactive
import static org.springframework.data.cassandra.core.query.Criteria.where;
import static org.springframework.data.cassandra.core.query.Query.query;
…
Person bob = new Person("Bob", 33);
cassandraTemplate.insert(bob);
Person queriedBob = cassandraTemplate.selectOneById(query(where("age").is(33)), Person.class);
import static org.springframework.data.cassandra.core.query.Criteria.where;
import static org.springframework.data.cassandra.core.query.Query.query;
…
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 语句,如以下示例所示:
-
Imperative
-
Reactive
String cql = "INSERT INTO person (age, name) VALUES (39, 'Bob')";
cassandraTemplate().getCqlOperations().execute(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
在批处理中插入、更新和删除单个对象
Cassandra 协议支持使用批处理在一个操作中插入行集合。
接口中的以下方法支持此功能:[Reactive]CassandraTemplate
-
batchOps
:创建一个新文件来填充批处理。[Reactive]CassandraBatchOperations
[Reactive]CassandraBatchOperations
-
insert
:接受单个对象、数组 (var-args) 或要插入的对象。Iterable
-
update
:采用单个对象、数组 (var-args) 或要更新的对象。Iterable
-
delete
:获取要删除的单个对象、数组 (var-args) 或 of 对象。Iterable
-
withTimestamp
:将 TTL 应用于批处理。 -
execute
:执行批处理。
更新表中的行
对于更新,您可以选择更新多行。
以下示例演示如何通过向分配余额添加一次性 50.00 美元的奖金来更新单个帐户对象:+
[Reactive]CasandraTemplate
-
Imperative
-
Reactive
import static org.springframework.data.cassandra.core.query.Criteria.where;
import org.springframework.data.cassandra.core.query.Query;
import org.springframework.data.cassandra.core.query.Update;
…
boolean applied = cassandraTemplate.update(Query.query(where("id").is("foo")),
Update.create().increment("balance", 50.00), Account.class);
import static org.springframework.data.cassandra.core.query.Criteria.where;
import org.springframework.data.cassandra.core.query.Query;
import org.springframework.data.cassandra.core.query.Update;
…
Mono<Boolean> wasApplied = reactiveCassandraTemplate.update(Query.query(where("id").is("foo")),
Update.create().increment("balance", 50.00), Account.class);
除了前面讨论的内容之外,我们还使用对象提供更新定义。
该类具有与可用于 Apache Cassandra 的更新分配匹配的方法。Query
Update
Update
大多数方法返回对象,以提供用于代码样式的流畅 API。Update
执行行更新的方法
update 方法可以更新行,如下所示:
-
boolean
update :更新 Apache Cassandra 表中的一系列对象。(Query query, Update update, Class<?> entityClass)
Update 类的方法
该类可以与一点“语法糖”一起使用,因为它的方法是链接在一起的。
此外,您还可以使用 static 方法和静态导入启动新实例的创建。Update
Update
public static Update update(String key, Object value)
该类具有以下方法:Update
-
AddToBuilder
addTo 入口点:(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
remove :使用更新分配从集合中删除值。(String columnName, Object value)
-
-
Update
clear :清除集合。(String columnName)
-
Update
increment :使用更新分配进行更新。(String columnName, Number delta)
+
-
Update
递减 :使用更新分配进行更新。(String columnName, Number delta)
-
-
Update
set :使用更新分配进行更新。(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
删除行的方法
可以使用以下重载方法从数据库中删除对象:
-
boolean
delete :删除 选择的对象。(Query query, Class<?> entityClass)
Query
-
T
delete :删除给定对象。(T entity)
-
T
delete :删除应用 的给定对象。(T entity, QueryOptions queryOptions)
QueryOptions
-
boolean
deleteById :使用给定的 ID 删除对象。(Object id, Class<?> entityClass)
乐观锁定
注解在 Cassandra 上下文中提供类似于 JPA 的语法,并确保更新仅应用于具有匹配版本的行。
Optimistic Locking 利用 Cassandra 的轻量级事务有条件地插入、更新和删除行。
因此,使用条件执行语句。
对于更新和删除,将 version 属性的实际值添加到条件中,这样,如果其他操作在此期间更改了行,则修改不会产生任何影响。
在这种情况下,将抛出一个。
以下示例显示了这些功能:@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")); (1)
Person tmp = template.findOne(query(where("id").is(daenerys.getId())), Person.class); (2)
daenerys.setLastname("Targaryen");
template.save(daenerys); (3)
template.save(tmp); // throws OptimisticLockingFailureException (4)
1 | 插入文档。 设置为 。version 0 |
2 | 加载刚刚插入的文档。 还是.version 0 |
3 | 使用 更新文档。
将 和 bump 设置为 。version = 0 lastname version 1 |
4 | 尝试更新之前加载的文档,该文档仍然具有 .
操作失败,并显示 ,因为电流为 。version = 0 OptimisticLockingFailureException version 1 |
乐观锁定仅支持单实体操作,不支持批处理操作。 |
插入操作和更新操作之间的区别在于,操作不插入值。INSERT null |
1 | 插入文档。 设置为 。version 0 |
2 | 加载刚刚插入的文档。 还是.version 0 |
3 | 使用 更新文档。
将 和 bump 设置为 。version = 0 lastname version 1 |
4 | 尝试更新之前加载的文档,该文档仍然具有 .
操作失败,并显示 ,因为电流为 。version = 0 OptimisticLockingFailureException version 1 |
乐观锁定仅支持单实体操作,不支持批处理操作。 |