Persisting Entities

这个类实现了 CassandraOperations 和 ReactiveCassandraOperations 接口,方法以 Cassandra 中可用方法的名称命名,以便对于已经熟悉 Cassandra 的开发人员来说,该 API 是比较熟悉的。例如,你可以找到诸如 select、insert、delete 和 update 等方法。设计目标是尽可能简化在使用基本 Cassandra 驱动程序和使用 [Reactive]CassandraOperations 之间的转换。这两个 API 之间的一个主要区别是,可以向 CassandraOperations 传递域对象,而不是 CQL 和查询对象。

位于 org.springframework.data.cassandra 包中的 CassandraTemplate 类(及其反应式变体 ReactiveCassandraTemplate)是 Spring 的 Cassandra 支持中的中心类,并提供丰富的功能集以与数据库交互。该模板提供便利操作以创建、更新、删除和查询 Cassandra,并在你的域对象和 Cassandra 表格中的行之间提供映射。

The CassandraTemplate class (and its reactive variant ReactiveCassandraTemplate), located in the org.springframework.data.cassandra package, is the central class in Spring’s Cassandra support and provides a rich feature set to interact with the database. The template offers convenience operations to create, update, delete, and query Cassandra, and provides a mapping between your domain objects and rows in Cassandra tables.

进行配置后,模板实例是线程安全的,并且可以在多个实例之间重用。

Once configured, a template instance is thread-safe and can be reused across multiple instances.

行在 Cassandra 和应用程序域类之间的映射通过委托给 CassandraConverter`接口的实现而完成。Spring 提供一个默认实现,即 `MappingCassandraConverter,但是您也可以编写自己的自定义转换器。有关更详细的信息,请参阅 Cassandra conversion 章节。

The mapping between rows in Cassandra and application domain classes is done by delegating to an implementation of the CassandraConverter interface. Spring provides a default implementation, MappingCassandraConverter, but you can also write your own custom converter. See the section on Cassandra conversion for more detailed information.

CassandraTemplate 类实现 CassandraOperations 接口,其反应式变体 ReactiveCassandraTemplate 实现 ReactiveCassandraOperations[Reactive]CassandraOperations 上的方法尽可能以 Cassandra 中可用的方法命名,以使已经熟悉 Cassandra 的开发者熟悉 API。

The CassandraTemplate class implements the CassandraOperations interface and its reactive variant ReactiveCassandraTemplate implements ReactiveCassandraOperations. In as much as possible, the methods on [Reactive]CassandraOperations are named after methods available in Cassandra to make the API familiar to developers who are already familiar with Cassandra.

例如,您可以找到诸如 selectinsertdeleteupdate 的方法。设计目标是在使用基本 Cassandra 驱动程序和 [Reactive]CassandraOperations 之间尽可能轻松地进行切换。两个 API 之间的一个主要区别是,CassandraOperations 可以传递域对象,而不是 CQL 和查询对象。

For example, you can find methods such as select, insert, delete, and update. The design goal was to make it as easy as possible to transition between the use of the base Cassandra driver and [Reactive]CassandraOperations. A major difference between the two APIs is that CassandraOperations can be passed domain objects instead of CQL and query objects.

引用 [Reactive]CassandraTemplate 实例上操作的首选方式是通过 [Reactive]CassandraOperations 接口。

The preferred way to reference operations on a [Reactive]CassandraTemplate instance is through the [Reactive]CassandraOperations interface.

[Reactive]CassandraTemplate 使用的默认转换器实现为 MappingCassandraConverter。虽然 MappingCassandraConverter 可以使用附加元数据来指定对象到行的映射,但它还可以转换不包含任何附加元数据的对象,方法是使用用于映射字段和表名的某些约定。这些约定以及映射注解的使用在 “Mapping” chapter 中进行了说明。

The default converter implementation used by [Reactive]CassandraTemplate is MappingCassandraConverter. While MappingCassandraConverter can use additional metadata to specify the mapping of objects to rows, it can also convert objects that contain no additional metadata by using some conventions for the mapping of fields and table names. These conventions, as well as the use of mapping annotations, are explained in the “Mapping” chapter.

`[Reactive]CassandraTemplate`的另一个核心特性是将 Cassandra Java 驱动程序中抛出的异常转换为 Spring 的可移植数据访问异常层次结构。有关详细信息,请参见exception translation部分。

Another central feature of [Reactive]CassandraTemplate is exception translation of exceptions thrown in the Cassandra Java driver into Spring’s portable Data Access Exception hierarchy. See the section on exception translation for more information.

模板 API 具有不同的执行模型风格。基本的 CassandraTemplate 使用阻塞(命令式同步)执行模型。您可以对异步执行使用 AsyncCassandraTemplate,并与 ListenableFuture 实例或对响应式执行使用 ReactiveCassandraTemplate 进行同步。

The Template API has different execution model flavors. The basic CassandraTemplate uses a blocking (imperative-synchronous) execution model. You can use AsyncCassandraTemplate for asynchronous execution and synchronization with ListenableFuture instances or ReactiveCassandraTemplate for reactive execution.

Instantiating CassandraTemplate

虽然我们在前面展示了一个直接示例化 CassandraTemplate 的示例,但 CassandraTemplate 总是应当配置为 Spring bean。但是,由于我们假定正在构建一个 Spring 模块,因此我们假设存在 Spring 容器。

CassandraTemplate should always be configured as a Spring bean, although we show an example earlier where you can instantiate it directly. However, because we are assuming the context of making a Spring module, we assume the presence of the Spring container.

有两种方法可以获取一个 CassandraTemplate,具体取决于你如何加载 Spring ApplicationContext

There are two ways to get a CassandraTemplate, depending on how you load you Spring ApplicationContext:

Autowiring

您可以根据项目将 [Reactive]CassandraOperations 注入到项目中,如以下示例所示:

You can autowire a [Reactive]CassandraOperations into your project, as the following example shows:

  • Imperative

  • Reactive

@Autowired
private CassandraOperations cassandraOperations;
@Autowired
private ReactiveCassandraOperations reactiveCassandraOperations;

与所有 Spring 注入一样,这假定 ApplicationContext 中只有类型为 [Reactive]CassandraOperations 的一个 Bean。如果有多个 [Reactive]CassandraTemplate Bean(当您在同一项目中使用多个键空间时会出现这种情况),那么可以使用 @Qualifier 注解来指定您想要注入的 Bean。

As with all Spring autowiring, this assumes there is only one bean of type [Reactive]CassandraOperations in the ApplicationContext. If you have multiple [Reactive]CassandraTemplate beans (which is the case if you work with multiple keyspaces in the same project), then you can use the @Qualifier annotation to designate the bean you want to autowire.

  • Imperative

  • Reactive

@Autowired
@Qualifier("keyspaceOneTemplateBeanId")
private CassandraOperations cassandraOperations;
@Autowired
@Qualifier("keyspaceOneTemplateBeanId")
private ReactiveCassandraOperations reactiveCassandraOperations;
Bean Lookup with ApplicationContext

您还可以从 ApplicationContext 中查找 [Reactive]CassandraTemplate Bean,如以下示例所示:

You can also look up the [Reactive]CassandraTemplate bean from the ApplicationContext, as shown in the following example:

  • Imperative

  • Reactive

CassandraOperations cassandraOperations = applicationContext.getBean("cassandraTemplate", CassandraOperations.class);
ReactiveCassandraOperations cassandraOperations = applicationContext.getBean("ReactiveCassandraOperations", ReactiveCassandraOperations.class);

Querying Rows

你可以通过使用 QueryCriteria 类来表示你的查询,这些类具有反映本地 Cassandra 谓词运算符名称的方法名称,例如 ltlteis 等。

You can express your queries by using the Query and Criteria classes, which have method names that reflect the native Cassandra predicate operator names, such as lt, lte, is, and others.

QueryCriteria 类遵循流利 API 样式,这样你可以在具有易于理解的代码的情况下,轻松地将多个方法条件和查询链接到一起。在创建 QueryCriteria 实例时会在 Java 中使用静态导入以提高可读性。

The Query and Criteria classes follow a fluent API style so that you can easily chain together multiple method criteria and queries while having easy-to-understand code. Static imports are used in Java when creating Query and Criteria instances to improve readability.

Querying Rows in a Table

在前面的几个章节中,我们看到了如何使用 [Reactive]CassandraTemplate 上的 selectOneById 方法来检索单个对象。这样做可返回单个域对象。我们还可以查询一组行,并将它们作为域对象列表返回。假设我们有一些 Person 对象,其中名称和年龄值存储在表中的行中,并且每个人都有一个帐户余额,那么我们现在可以通过使用以下代码来运行查询:

In earlier sections, we saw how to retrieve a single object by using the selectOneById method on [Reactive]CassandraTemplate. Doing so returns a single domain object. We can also query for a collection of rows to be returned as a list of domain objects. Assuming we have a number of Person objects with name and age values stored as rows in a table and that each person has an account balance, we can now run a query by using the following code:

Querying for rows using [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);

selectselectOnestream 方法将 Query 对象作为参数。此对象定义用于执行该查询的条件和选项。该条件通过使用静态工厂方法 where 来指定,后者实例化一个新的 Criteria 对象。我们建议对 org.springframework.data.cassandra.core.query.Criteria.whereQuery.query 进行静态导入,以使查询更具可读性。

The select, selectOne, and stream methods take a Query object as a parameter. This object defines the criteria and options used to perform the query. The criteria is specified by using a Criteria object that has a static factory method named where that instantiates a new Criteria object. We recommend using a static import for org.springframework.data.cassandra.core.query.Criteria.where and Query.query, to make the query more readable.

此查询应返回满足指定条件的一列 Person 对象,Criteria 类具有以下方法,这些方法与 Apache Cassandra 中提供的运算符相对应:

This query should return a list of Person objects that meet the specified criteria. The Criteria class has the following methods that correspond to the operators provided in Apache Cassandra:

Methods for the Criteria class

  • CriteriaDefinition gt (Object value): Creates a criterion by using the > operator.

  • CriteriaDefinition gte (Object value): Creates a criterion by using the >= operator.

  • CriteriaDefinition in (Object…​ values): Creates a criterion by using the IN operator for a varargs argument.

  • CriteriaDefinition in (Collection<?> collection): Creates a criterion by using the IN operator using a collection.

  • CriteriaDefinition is (Object value): Creates a criterion by using field matching (column = value).

  • CriteriaDefinition lt (Object value): Creates a criterion by using the < operator.

  • CriteriaDefinition lte (Object value): Creates a criterion by using the operator.

  • CriteriaDefinition like (Object value): Creates a criterion by using the LIKE operator.

  • CriteriaDefinition contains (Object value): Creates a criterion by using the CONTAINS operator.

  • CriteriaDefinition containsKey (Object key): Creates a criterion by using the CONTAINS KEY operator.

创建后,Criteria します。

Criteria is immutable once created.

Methods for the Query class

Query 类有一些附加方法,您可以使用它们为查询提供选项:

The Query class has some additional methods that you can use to provide options for the query:

  • Query by (CriteriaDefinition…​ criteria): Used to create a Query object.

  • Query and (CriteriaDefinition criteria): Used to add additional criteria to the query.

  • Query columns (Columns columns): Used to define columns to be included in the query results.

  • Query limit (Limit limit): Used to limit the size of the returned results to the provided limit (used SELECT limiting).

  • Query limit (long limit): Used to limit the size of the returned results to the provided limit (used SELECT limiting).

  • Query pageRequest (Pageable pageRequest): Used to associate Sort, PagingState, and fetchSize with the query (used for paging).

  • Query pagingState (ByteBuffer pagingState): Used to associate a ByteBuffer with the query (used for paging).

  • Query queryOptions (QueryOptions queryOptions): Used to associate QueryOptions with the query.

  • Query sort (Sort sort): Used to provide a sort definition for the results.

  • Query withAllowFiltering (): Used to render ALLOW FILTERING queries.

创建后,Query します。调用方法会创建新的不可变(中间)Query 对象。

Query is immutable once created. Invoking methods creates new immutable (intermediate) Query objects.

Methods for Querying for Rows

Query 类具有以下返回行的各项方法:

The Query class has the following methods that return rows:

  • List<T> select (Query query, Class<T> entityClass): Query for a list of objects of type T from the table.

  • T selectOne (Query query, Class<T> entityClass): Query for a single object of type T from the table.

  • Slice<T> slice (Query query, Class<T> entityClass): Starts or continues paging by querying for a Slice of objects of type T from the table.

  • Stream<T> stream (Query query, Class<T> entityClass): Query for a stream of objects of type T from the table.

  • List<T> select (String cql, Class<T> entityClass): Ad-hoc query for a list of objects of type T from the table by providing a CQL statement.

  • T selectOne (String cql, Class<T> entityClass): Ad-hoc query for a single object of type T from the table by providing a CQL statement.

  • Stream<T> stream (String cql, Class<T> entityClass): Ad-hoc query for a stream of objects of type T from the table by providing a CQL statement.

查询方法必须指定要返回的目标类型 T

The query methods must specify the target type T that is returned.

Fluent Template API

[Reactive]CassandraOperations 接口在与 Apache Cassandra 进行更低级别的交互时是核心组件之一。它提供了多种方法。您可以找到每个方法的多个重载。它们大多数涵盖了 API 的可选(可为 null)部分。

The [Reactive]CassandraOperations interface is one of the central components when it comes to more low-level interaction with Apache Cassandra. It offers a wide range of methods. You can find multiple overloads for every method. Most of them cover optional (nullable) parts of the API.

FluentCassandraOperations 及其反应式变体 ReactiveFluentCassandraOperations[Reactive]CassandraOperations 的常用方法提供一个更窄的接口,它提供了一个更易读的、流畅的 API。入口点 (query(…)insert(…)update(…)delete(…)) 遵循一个基于要执行的操作的自然命名方案。从入口点开始,该 API 被设计为仅提供上下文相关的帮助开发者通向调用实际 [Reactive]CassandraOperations 的终止方法的方法。以下示例展示了流畅 API:

FluentCassandraOperations and its reactive variant ReactiveFluentCassandraOperations provide a more narrow interface for common methods of [Reactive]CassandraOperations providing a more readable, fluent API. The entry points (query(…), insert(…), update(…), and delete(…)) follow a natural naming scheme based on the operation to execute. Moving on from the entry point, the API is designed to offer only context-dependent methods that guide the developer towards a terminating method that invokes the actual [Reactive]CassandraOperations. The following example shows the fluent API:

Imperative
List<SWCharacter> all = ops.query(SWCharacter.class)
  .inTable("star_wars")                        1
  .all();
1 Skip this step if SWCharacter defines the table name with @Table or if using the class name as the table name is not a problem
Reactive
Flux<SWCharacter> all = ops.query(SWCharacter.class)
  .inTable("star_wars")                        1
  .all();
2 Skip this step if SWCharacter defines the table name with @Table or if using the class name as the table name is not a problem

如果 Cassandra 中的表存储不同类型的实体,例如 SWCharacters 表中的 Jedi,则可以使用不同的类型映射查询结果。您可以使用 as(Class<?> targetType) 将结果映射到不同的目标类型,而 query(Class<?> entityType) 仍应用于查询和表名。以下示例使用了 queryas 方法:

If a table in Cassandra holds entities of different types, such as a Jedi within a Table of SWCharacters, you can use different types to map the query result. You can use as(Class<?> targetType) to map results to a different target type, while query(Class<?> entityType) still applies to the query and table name. The following example uses the query and as methods:

Imperative
List<Jedi> all = ops.query(SWCharacter.class)    1
  .as(Jedi.class)                                2
  .matching(query(where("jedi").is(true)))
  .all();
1 The query fields are mapped against the SWCharacter type.
2 Resulting rows are mapped into Jedi.
Reactive
Flux<Jedi> all = ops.query(SWCharacter.class)    1
  .as(Jedi.class)                                2
  .matching(query(where("jedi").is(true)))
  .all();
3 The query fields are mapped against the SWCharacter type.
4 Resulting rows are mapped into Jedi.

您可以仅通过 as(Class<?>) 提供 interface 类型,直接将 Projections 应用于结果文档。

You can directly apply Projections to resulting documents by providing only the interface type through as(Class<?>).

终止方法(first()one()all()stream())处理在检索单个实体和检索多个实体(作为 ListStream)之间切换之类的操作。

The terminating methods (first(), one(), all(), and stream()) handle switching between retrieving a single entity and retrieving multiple entities as List or Stream and similar operations.

新的利于理解的模板 API 方法(即 query(..)insert(..)update(..)delete(..))有效地使用线程安全支持对象组合 CQL 语句。但是,它带来了额外的新生代 JVM 堆开销,因为设计基于各种 CQL 语句组件的最终字段和在变更中构造。当可能插入或删除大量对象时(例如在循环内),您应小心。

The new fluent template API methods (that is, query(..), insert(..), update(..), and delete(..)) use effectively thread-safe supporting objects to compose the CQL statement. However, it comes at the added cost of additional young-gen JVM heap overhead, since the design is based on final fields for the various CQL statement components and construction on mutation. You should be careful when possibly inserting or deleting a large number of objects (such as inside of a loop, for instance).

Saving, Updating, and Removing Rows

[Reactive]CassandraTemplate 为您提供了保存、更新和删除您的域对象,以及将这些对象映射到 Cassandra 中管理的表的一种简单方法。

[Reactive]CassandraTemplate provides a simple way for you to save, update, and delete your domain objects and map those objects to tables managed in Cassandra.

Type Mapping

Spring Data for Apache Cassandra 依赖于 DataStax Java 驱动程序的`CodecRegistry`以确保类型支持。随着类型的添加或更改,Spring Data for Apache Cassandra 模块继续运行,而不需要进行更改。有关当前类型映射矩阵,请参见 CQL data types和 “Data Mapping and Type Conversion”。

Spring Data for Apache Cassandra relies on the DataStax Java driver’s CodecRegistry to ensure type support. As types are added or changed, the Spring Data for Apache Cassandra module continues to function without requiring changes. See CQL data types and “Data Mapping and Type Conversion” for the current type mapping matrix.

Methods for Inserting and Updating rows

[Reactive]CassandraTemplate 有几个使您能够保存和插入您的对象的便捷方法。为了对转换过程进行更细粒度的控制,您可以向 MappingCassandraConverter 注册 Spring Converter 实例(例如,Converter<Row, Person>)。

[Reactive]CassandraTemplate has several convenient methods for saving and inserting your objects. To have more fine-grained control over the conversion process, you can register Spring Converter instances with the MappingCassandraConverter (for example, Converter<Row, Person>).

插入操作和更新操作之间的区别在于,INSERT 操作不会插入 null 值。

The difference between insert and update operations is that INSERT operations do not insert null values.

使用 INSERT 操作的简单情况是保存 POJO。在这种情况下,表名由简单类名决定(而不是完全限定的类名)。可以通过使用映射元数据来覆盖用于存储对象的表。

The simple case of using the INSERT operation is to save a POJO. In this case, the table name is determined by the simple class name (not the fully qualified class name). The table to store the object can be overridden by using mapping metadata.

插入或更新时,必须设置 id 属性。Apache Cassandra 无法生成 ID。

When inserting or updating, the id property must be set. Apache Cassandra has no means to generate an ID.

以下示例使用了 save 操作并检索其内容:

The following example uses the save operation and retrieves its contents:

Inserting and retrieving objects by using the [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);

您可以使用以下操作进行插入和保存:

You can use the following operations to insert and save:

  • void insert (Object objectToSave): Inserts the object in an Apache Cassandra table.

  • WriteResult insert (Object objectToSave, InsertOptions options): Inserts the object in an Apache Cassandra table and applies InsertOptions.

您可以使用以下更新操作:

You can use the following update operations:

  • void update (Object objectToSave): Updates the object in an Apache Cassandra table.

  • WriteResult update (Object objectToSave, UpdateOptions options): Updates the object in an Apache Cassandra table and applies UpdateOptions.

您还可以使用老式方法编写自己的 CQL 语句,如下面的示例所示:

You can also use the old fashioned way and write your own CQL statements, as the following example shows:

  • 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);

您还可以使用 InsertOptionsUpdateOptions 配置其他选项,例如 TTL、一致性级别和轻量级事务。

You can also configure additional options such as TTL, consistency level, and lightweight transactions when using InsertOptions and UpdateOptions.

Which Table Are My Rows Inserted into?

您可以通过两种方式管理用于操作表的表名。默认的表名是简单类名,将其更改为以小写字母开头。因此,com.example.Person 类的实例将存储在 person 表中。第二种方式是指定 @Table 注解中的表名。

You can manage the table name that is used for operating on the tables in two ways. The default table name is the simple class name changed to start with a lower-case letter. So, an instance of the com.example.Person class would be stored in the person table. The second way is to specify a table name in the @Table annotation.

Inserting, Updating, and Deleting Individual Objects in a Batch

Cassandra 协议支持通过批量使用一次操作插入集合行。

The Cassandra protocol supports inserting a collection of rows in one operation by using a batch.

[Reactive]CassandraTemplate 接口中的以下方法支持此功能:

The following methods in the [Reactive]CassandraTemplate interface support this functionality:

  • batchOps: Creates a new [Reactive]CassandraBatchOperations to populate the batch.

[Reactive]CassandraBatchOperations

  • insert: Takes a single object, an array (var-args), or an Iterable of objects to insert.

  • update: Takes a single object, an array (var-args), or an Iterable of objects to update.

  • delete: Takes a single object, an array (var-args), or an Iterable of objects to delete.

  • withTimestamp: Applies a TTL to the batch.

  • execute: Executes the batch.

Updating Rows in a Table

对于更新,您可以选择更新多行。

For updates, you can select to update a number of rows.

以下示例显示了通过将一次性 50.00 美元的奖励加到余额中来更新单个帐户对象,分配 +

The following example shows updating a single account object by adding a one-time $50.00 bonus to the balance with the + assignment:

Updating rows using [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);

除了前面讨论的 Query 外,我们还使用 Update 对象提供更新定义。Update 类具有与 Apache Cassandra 可用更新分配匹配的方法。

In addition to the Query discussed earlier, we provide the update definition by using an Update object. The Update class has methods that match the update assignments available for Apache Cassandra.

大多数方法返回 Update 对象以提供一种流畅的 API 用于代码样式目的。

Most methods return the Update object to provide a fluent API for code styling purposes.

Methods for Executing Updates for Rows

更新方法可以更新行,如下所示:

The update method can update rows, as follows:

  • boolean update (Query query, Update update, Class<?> entityClass): Updates a selection of objects in the Apache Cassandra table.

Methods for the Update class

Update 类可以与少量“语法糖”一起使用,因为它的方法是为了链接在一起的。此外,您可以使用静态方法 public static Update update(String key, Object value) 和静态导入来启动创建新的 Update 实例。

The Update class can be used with a little 'syntax sugar', as its methods are meant to be chained together. Also, you can kick-start the creation of a new Update instance with the static method public static Update update(String key, Object value) and by using static imports.

Update 类具有以下方法:

The Update class has the following methods:

  • AddToBuilder addTo (String columnName) AddToBuilder entry-point:

    • Update prepend(Object value): Prepends a collection value to the existing collection by using the + update assignment.

    • Update prependAll(Object…​ values): Prepends all collection values to the existing collection by using the + update assignment.

    • Update append(Object value): Appends a collection value to the existing collection by using the + update assignment.

    • Update append(Object…​ values): Appends all collection values to the existing collection by using the + update assignment.

    • Update entry(Object key, Object value): Adds a map entry by using the + update assignment.

    • Update addAll(Map<? extends Object, ? extends Object> map): Adds all map entries to the map by using the + update assignment.

  • Update remove (String columnName, Object value): Removes the value from the collection by using the - update assignment.

  • Update clear (String columnName): Clears the collection.

  • Update increment (String columnName, Number delta): Updates by using the + update assignment.

  • Update decrement (String columnName, Number delta): Updates by using the - update assignment.

  • Update set (String columnName, Object value): Updates by using the = update assignment.

  • SetBuilder set (String columnName) SetBuilder entry-point:

    • Update atIndex(int index).to(Object value): Sets a collection at the given index to a value using the = update assignment.

    • Update atKey(String object).to(Object value): Sets a map entry at the given key to a value the = update assignment.

以下清单显示一些更新示例:

The following listing shows a few update examples:

// 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 对象。

Note that Update is immutable once created. Invoking methods creates new immutable (intermediate) Update objects.

Methods for Removing Rows

您可以使用以下重载方法从数据库中删除对象:

You can use the following overloaded methods to remove an object from the database:

  • boolean delete (Query query, Class<?> entityClass): Deletes the objects selected by Query.

  • T delete (T entity): Deletes the given object.

  • T delete (T entity, QueryOptions queryOptions): Deletes the given object applying QueryOptions.

  • boolean deleteById (Object id, Class<?> entityClass): Deletes the object using the given Id.

Optimistic Locking

@Version 注释提供了类似于 Cassandra 上下文中的 JPA 的语法,并确保更新仅应用于具有匹配版本的行。乐观锁利用 Cassandra 的轻量级事务来有条件地插入、更新和删除行。因此,INSERT 语句以 IF NOT EXISTS 条件执行。对于更新和删除,将实际版本属性值添加到 UPDATE 条件中,以便如果另一个操作同时更改行,则修改不会产生任何影响。这种情况会抛出 OptimisticLockingFailureException。以下示例显示了这些功能:

The @Version annotation provides syntax similar to that of JPA in the context of Cassandra and makes sure updates are only applied to rows with a matching version. Optimistic Locking leverages Cassandra’s lightweight transactions to conditionally insert, update and delete rows. Therefore, INSERT statements are executed with the IF NOT EXISTS condition. For updates and deletes, the actual value of the version property is added to the UPDATE condition in such a way that the modification does not have any effect if another operation altered the row in the meantime. In that case, an OptimisticLockingFailureException is thrown. The following example shows these features:

@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 Intially insert document. version is set to 0.
2 Load the just inserted document. version is still 0.
3 Update the document with version = 0. Set the lastname and bump version to 1.
4 Try to update the previously loaded document that still has version = 0. The operation fails with an OptimisticLockingFailureException, as the current version is 1.

乐观锁仅受支持于单实体操作,而不受支持于批处理操作。

Optimistic Locking is only supported with single-entity operations and not for batch operations.