永続化エンティティ
org.springframework.data.cassandra パッケージにある CassandraTemplate クラス (およびそのリアクティブ版 ReactiveCassandraTemplate) は、Spring の Cassandra サポートの中心クラスであり、データベースと対話するための豊富な機能セットを提供します。このテンプレートは、Cassandra を作成、更新、削除、クエリするための便利な操作を提供し、ドメインオブジェクトと Cassandra テーブル内の行との間のマッピングを提供します。
| 構成が完了すると、テンプレートインスタンスはスレッドセーフになり、複数のインスタンス間で再利用できます。 |
Cassandra の行とアプリケーションドメインクラス間のマッピングは、CassandraConverter インターフェースの実装に委譲することによって行われます。Spring はデフォルトの実装である MappingCassandraConverter を提供しますが、独自のカスタムコンバーターを作成することもできます。詳細については、Cassandra 変換のセクションを参照してください。
CassandraTemplate クラスは CassandraOperations インターフェースを実装し、そのリアクティブバリアント ReactiveCassandraTemplate は ReactiveCassandraOperations を実装します。[Reactive]CassandraOperations のメソッドは、Cassandra にすでに精通している開発者にとって API が親しみやすいものとなるよう、可能な限り Cassandra で利用可能なメソッドにちなんで命名されています。
例: select、insert、delete、update などのメソッドが見つかります。設計ゴールは、ベース Cassandra ドライバーと [Reactive]CassandraOperations の使用の間での移行をできるだけ簡単にすることでした。2 つの API の主な違いは、CassandraOperations には CQL オブジェクトやクエリオブジェクトの代わりにドメインオブジェクトを渡すことができることです。
[Reactive]CassandraTemplate インスタンスの操作を参照するための推奨される方法は、[Reactive]CassandraOperations インターフェースを使用することです。 |
[Reactive]CassandraTemplate で使用されるデフォルトのコンバーター実装は MappingCassandraConverter です。MappingCassandraConverter は追加のメタデータを使用してオブジェクトの行へのマッピングを指定できますが、フィールドとテーブル名のマッピングの規則を使用して、追加のメタデータを含まないオブジェクトを変換することもできます。これらの規則とマッピングアノテーションの使用については、「マッピング」の章で説明されています。
[Reactive]CassandraTemplate のもう 1 つの中心的な機能は、Cassandra Java ドライバーでスローされた例外を Spring の移植可能なデータアクセス例外階層に変換することです。詳細については、例外変換に関するセクションを参照してください。
テンプレート API にはさまざまな実行モデルのフレーバーがあります。基本的な CassandraTemplate は、ブロッキング (命令型同期) 実行モデルを使用します。非同期実行および CompletableFuture インスタンスとの同期には AsyncCassandraTemplate を使用でき、リアクティブ実行には ReactiveCassandraTemplate を使用できます。 |
CassandraTemplate のインスタンス化
CassandraTemplate は常に Spring Bean として構成する必要がありますが、直接インスタンス化できる例を前に示しました。ただし、Spring モジュールを作成するコンテキストを想定しているため、Spring コンテナーの存在を前提としています。
Spring ApplicationContext をロードする方法に応じて、CassandraTemplate を取得するには 2 つの方法があります。
オートワイヤー
次の例に示すように、[Reactive]CassandraOperations をプロジェクトにオートワイヤーできます。
命令的
リアクティブ
@Autowired
private CassandraOperations cassandraOperations;
@Autowired
private ReactiveCassandraOperations reactiveCassandraOperations;
すべての Spring オートワイヤーと同様に、これは ApplicationContext 内に型 [Reactive]CassandraOperations の Bean が 1 つだけ存在することを前提としています。複数の [Reactive]CassandraTemplate Bean がある場合 (同じプロジェクト内で複数のキースペースを操作する場合がこれに該当します)、@Qualifier アノテーションを使用して、自動接続する Bean を指定できます。
命令的
リアクティブ
@Autowired
@Qualifier("keyspaceOneTemplateBeanId")
private CassandraOperations cassandraOperations;
@Autowired
@Qualifier("keyspaceOneTemplateBeanId")
private ReactiveCassandraOperations reactiveCassandraOperations;
Bean ApplicationContext による検索
次の例に示すように、ApplicationContext から [Reactive]CassandraTemplate Bean を検索することもできます。
命令的
リアクティブ
CassandraOperations cassandraOperations = applicationContext.getBean("cassandraTemplate", CassandraOperations.class);
ReactiveCassandraOperations cassandraOperations = applicationContext.getBean("ReactiveCassandraOperations", ReactiveCassandraOperations.class);
行のクエリ
Query および Criteria クラスを使用してクエリを表現できます。これらのクラスには、lt、lte、is などのネイティブ Cassandra 述語演算子名を反映するメソッド名が付いています。
Query クラスと Criteria クラスは流れるような API スタイルに従っているため、理解しやすいコードを使用しながら、複数のメソッド条件とクエリを簡単に チェーンで組み合わせることができます。静的インポートは、Java で Query および Criteria インスタンスを作成するときに読みやすさを向上させるために使用されます。
テーブル内の行のクエリ
前のセクションでは、[Reactive]CassandraTemplate で selectOneById メソッドを使用して単一のオブジェクトを取得する方法を説明しました。そうすると、単一のドメインオブジェクトが返されます。ドメインオブジェクトのリストとして返される行のコレクションをクエリすることもできます。名前と年齢の値がテーブルの行として格納された多数の Person オブジェクトがあり、各個人が口座残高を持っていると仮定すると、次のコードを使用してクエリを実行できます。
[Reactive]CassandraTemplate を使用した行のクエリ 命令的
リアクティブ
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 には静的インポートを使用することをお勧めします。
このクエリは、指定された条件を満たす Person オブジェクトのリストを返します。Criteria クラスには、Apache Cassandra で提供される演算子に対応する次のメソッドがあります。
Criteria クラスのメソッド
CriteriaDefinitiongt(Object value):>演算子を使用して基準を作成します。CriteriaDefinitiongte(Object value):>=演算子を使用して基準を作成します。CriteriaDefinitionin(Object… values): varargs 引数にIN演算子を使用して、基準を作成します。CriteriaDefinitionin(Collection<?> collection): コレクションを使用してIN演算子を使用して、基準を作成します。CriteriaDefinitionis(Object value): フィールドマッチング (column = value) を使用して基準を作成します。CriteriaDefinitionlt(Object value):<演算子を使用して基準を作成します。CriteriaDefinitionlte(Object value):⇐演算子を使用して基準を作成します。CriteriaDefinitionlike(Object value):LIKE演算子を使用して基準を作成します。CriteriaDefinitioncontains(Object value):CONTAINS演算子を使用して基準を作成します。CriteriaDefinitioncontainsKey(Object key):CONTAINS KEY演算子を使用して基準を作成します。
Criteria は、一度作成されると不変になります。
Query クラスのメソッド
Query クラスには、クエリのオプションを提供するために使用できる追加のメソッドがいくつかあります。
Queryby(CriteriaDefinition… criteria):Queryオブジェクトの作成に使用されます。Queryand(CriteriaDefinition criteria): クエリに追加の条件を追加するために使用されます。Querycolumns(Columns columns): クエリ結果に含める列を定義するために使用されます。Querylimit(Limit limit): 返される結果のサイズを指定された制限に制限するために使用されます (SELECT制限を使用)。Querylimit(long limit): 返される結果のサイズを指定された制限に制限するために使用されます (SELECT制限を使用)。QuerypageRequest(Pageable pageRequest):Sort、PagingState、fetchSizeをクエリに関連付けるために使用されます (ページングに使用されます)。QuerypagingState(CassandraScrollPosition pagingState):CassandraScrollPositionをクエリに関連付けるために使用されます (ページングに使用されます)。QuerypagingState(ByteBuffer pagingState): 生のByteBufferをクエリに関連付けるために使用されます (ページングに使用されます)。QueryqueryOptions(QueryOptions queryOptions):QueryOptionsをクエリに関連付けるために使用されます。Querysort(Sort sort): 結果の並べ替え定義を提供するために使用されます。QuerywithAllowFiltering():ALLOW FILTERINGクエリをレンダリングするために使用されます。
Query は、一度作成されると不変になります。メソッドを呼び出すと、新しい不変 (中間) Query オブジェクトが作成されます。
行をクエリするためのメソッド
Query クラスには、行を返す次のメソッドがあります。
List<T>select(Query query, Class<T> entityClass): テーブルから型Tのオブジェクトのリストをクエリします。TselectOne(Query query, Class<T> entityClass): テーブルから型Tの単一オブジェクトをクエリします。Slice<T>slice(Query query, Class<T> entityClass): テーブルから型TのオブジェクトのSliceをクエリすることによって、ページングを開始または継続します。Stream<T>stream(Query query, Class<T> entityClass): テーブルから型Tのオブジェクトのストリームをクエリします。List<T>select(String cql, Class<T> entityClass): CQL ステートメントを指定して、テーブルからT型のオブジェクトのリストを取得するアドホッククエリ。TselectOne(String cql, Class<T> entityClass): CQL ステートメントを指定して、テーブルからT型の単一オブジェクトに対するアドホッククエリを実行します。Stream<T>stream(String cql, Class<T> entityClass): CQL ステートメントを指定して、テーブルから型Tのオブジェクトのストリームに対するアドホッククエリを実行します。
クエリメソッドでは、返されるターゲット型 T を指定する必要があります。
列射影
Query.colums(…) を指定しない場合は、すべての列が選択され (SELECT * FROM … )、@Value(…) を介してエンティティから使用可能なすべての列にアクセスできるようになります。また、オープン射影を使用するときにもアクセスできるようになります。
クエリにさらに情報を提供する場合 (たとえば、閉じた DTO または Fluent テンプレート API を介したインターフェース射影を使用する場合)、列の選択が制限されます。
デフォルトの列選択に影響を与えるために、各 CassandraTemplate インスタンスの StatementFactory 上のデフォルトの ProjectionFunction を設定できます。
CassandraTemplate template = …;
template.getStatementFactory().setProjectionFunction(ProjectionFunction.mappedProperties());ProjectionFunctions.mappedProperties() で明示的に列を指定すると、選択範囲はエンティティ型のマッピングされたプロパティに限定されますが、明示的な性質上、クエリ実行時にエンティティマッピングに対してクエリが検証され、望ましくないスキーマ変更は例外を通じて表示されます。マッピングされていないプロパティは @Value(…) では利用できないことに注意してください。
Query.columns(…) による明示的な列選択を使用すると、射影関数からの Columns 計算がバイパスされます。
Fluent テンプレート API
[Reactive]CassandraOperations インターフェースは、Apache Cassandra とのより低レベルのインタラクションに関して中心的なコンポーネントの 1 つです。幅広いメソッドを提供します。各メソッドには複数のオーバーロードがあります。そのほとんどは、API のオプション (null 可能) 部分をカバーします。
FluentCassandraOperations とそのリアクティブバリアント ReactiveFluentCassandraOperations は、[Reactive]CassandraOperations の一般的なメソッドに対してより狭いインターフェースを提供し、より読みやすく流れるような API を提供します。エントリポイント (query(…)、insert(…)、update(…)、delete(…)) は、実行する操作に基づいた自然な命名スキームに従います。エントリポイントから先に進むと、API は、実際の [Reactive]CassandraOperations を呼び出す終了メソッドに開発者を導くコンテキスト依存のメソッドのみを提供するように設計されています。次の例は、流れるような API を示しています。
命令的
リアクティブ
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 のテーブルにさまざまな型のエンティティ ( SWCharacters のテーブル内の Jedi など) が保持されている場合、さまざまな型を使用してクエリ結果をマップできます。as(Class<?> targetType) を使用して結果を別のターゲット型にマップできますが、query(Class<?> entityType) は引き続きクエリとテーブル名に適用されます。次の例では、query メソッドと as メソッドを使用します。
命令的
リアクティブ
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 Template API メソッド(query(…)、insert(…)、update(…)、delete(…))は、CQL 文を作成するために、実質的にスレッドセーフなサポートオブジェクトを使用します。ただし、様々な CQL 文の構成要素に final フィールドを使用し、変更に基づいて構築する設計になっているため、若い世代の JVM ヒープのオーバーヘッドが増加するというデメリットがあります。ループ内など、多数のオブジェクトを挿入または削除する必要がある場合は注意が必要です。 |
ベクトル検索クエリ
射影は、エンティティとは異なる形式で返されるデータをクエリするための基盤です。Cassandra の主なユースケースはキーバリューモデル(取得したデータを保存する)ですが、ベクトル検索は異なります。ベクトル検索クエリを実行すると、通常、集計またはレポートのような結果セットが返されます。典型的なクエリでは、何らかの形式のコンテンツ(text 列など)と、そのスコア(または実際のベクトルまでの距離)が返されます。
次のドメインモデルを検討してください。
@Table
class Comments {
@Id UUID id;
String comment;
@VectorType(dimensions = 5)
@SaiIndexed Vector vector;
}
class CommentSearch {
String comment;
float similarity;
}Comments は、ベクトル列と comment 列を定義するドメイン型です。
ベクトル検索を実行するには、ANN ソートを使用する必要があり、通常は、指定されたベクトルからの距離を決定するための類似度関数を定義します。
Columns columns = Columns.from("comment") (1)
.select("vector", builder -> builder.similarity(vector)
.cosine().as("similarity")); (2)
Query query = Query.select(columns)
.limit(3)
.sort(VectorSort.ann("vector", vector)); (3)
template.query(Comments.class)
.as(CommentSearch.class) (4)
.matching(query)
.all();
| 1 | クエリする列を選択します。 |
| 2 | similarity_cosine(vector, [ … ]) への関数呼び出しを含めます。Columns.select(…) はセレクタービルダーカスタマイザーを使用して実際の選択を設定します。結果のマッピングでは列名が使用されるため、結果を CommentSearch.similarity にマッピングするためのエイリアスを必ず宣言してください。 |
| 3 | VectorSort.ann(…) を使用して、指定されたベクトルと比較してソート順序を定義します。 |
| 4 | 結果をマッピングするターゲット型を定義します。CommentSearch 型は、結果をマッピングする列を定義する結果射影型です。 |
行の保存、更新、削除
[Reactive]CassandraTemplate は、ドメインオブジェクトを保存、更新、削除し、それらのオブジェクトを Cassandra で管理されるテーブルにマップするための簡単なメソッドを提供します。
型マッピング
Apache Cassandra 用の Spring Data は、型のサポートを保証するために DataStax Java ドライバーの CodecRegistry に依存しています。型が追加または変更されても、Apache Cassandra 用の Spring Data モジュールは変更を必要とせずに機能し続けます。現在の型マッピングマトリックスについては、CQL データ型 (英語) および "データマッピングと型変換" を参照してください。
行を挿入および更新するメソッド
[Reactive]CassandraTemplate には、オブジェクトを保存および挿入するための便利な方法がいくつかあります。変換プロセスをよりきめ細かく制御するには、Spring Converter インスタンスを MappingCassandraConverter (たとえば、Converter<Row, Person>) に登録できます。
挿入操作と更新操作の違いは、INSERT 操作では null 値が挿入されないことです。 |
INSERT 操作を使用する簡単な例は、POJO を保存することです。この場合、テーブル名は (完全修飾クラス名ではなく) 単純なクラス名によって決まります。オブジェクトを格納するテーブルは、マッピングメタデータを使用してオーバーライドできます。
挿入または更新する場合は、id プロパティを設定する必要があります。Apache Cassandra には ID を生成する手段がありません。
次の例では、保存操作を使用してその内容を取得します。
[Reactive]CassandraTemplate を使用したオブジェクトの挿入と取得 命令的
リアクティブ
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);
次の操作を使用して挿入および保存できます。
voidinsert(Object objectToSave): Apache Cassandra テーブルにオブジェクトを挿入します。WriteResultinsert(Object objectToSave, InsertOptions options): Apache Cassandra テーブルにオブジェクトを挿入し、InsertOptionsを適用します。
次の更新操作を使用できます。
voidupdate(Object objectToSave): Apache Cassandra テーブル内のオブジェクトを更新します。WriteResultupdate(Object objectToSave, UpdateOptions options): Apache Cassandra テーブル内のオブジェクトを更新し、UpdateOptionsを適用します。
次の例に示すように、昔ながらの方法を使用して独自の CQL ステートメントを作成することもできます。
命令的
リアクティブ
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);
InsertOptions および UpdateOptions を使用する場合は、TTL、整合性レベル、軽量トランザクションなどの追加オプションを構成することもできます。
行はどのテーブルに挿入されますか ?
テーブルの操作に使用されるテーブル名は 2 つの方法で管理できます。デフォルトのテーブル名は、小文字で始まるように変更された単純なクラス名です。com.example.Person クラスのインスタンスは person テーブルに格納されます。2 番目の方法は、@Table アノテーションでテーブル名を指定することです。
バッチ内の個々のオブジェクトの挿入、更新、削除
Cassandra プロトコルは、バッチを使用した 1 回の操作で行のコレクションを挿入することをサポートしています。
[Reactive]CassandraTemplate インターフェースの次のメソッドは、この機能をサポートしています。
batchOps: 新しい[Reactive]CassandraBatchOperationsを作成してバッチに追加します。
[Reactive]CassandraBatchOperations
insert: 単一のオブジェクト、配列 (var-args)、またはオブジェクトのIterableを挿入して受け取ります。update: 単一のオブジェクト、配列 (var-args)、またはオブジェクトのIterableを更新対象として受け取ります。delete: 単一のオブジェクト、配列 (var-args)、または削除するオブジェクトのIterableを受け取ります。withTimestamp: TTL をバッチに適用します。execute: バッチを実行します。
テーブル内の行を更新する
更新の場合、複数の行を更新することを選択できます。
次の例は、+ 割り当てを使用して残高に 1 回限りの $50.00 ボーナスを追加することによって、単一のアカウントオブジェクトを更新することを示しています。
[Reactive]CasandraTemplate を使用した行の更新 命令的
リアクティブ
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 で使用可能な更新割り当てに一致するメソッドがあります。
ほとんどのメソッドは Update オブジェクトを返し、コードスタイルの目的で流れるような API を提供します。
行の更新を実行するメソッド
update メソッドは次のように行を更新できます。
booleanupdate(Query query, Update update, Class<?> entityClass): Apache Cassandra テーブル内のオブジェクトの選択を更新します。
Update クラスのメソッド
Update クラスは、そのメソッドが連鎖することを目的としているため、少しの「構文糖」を加えて使用できます。また、静的メソッド public static Update update(String key, Object value) と静的インポートを使用して、新しい Update インスタンスの作成を開始することもできます。
Update クラスには次のメソッドがあります。
AddToBuilderaddTo(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)の更新:+更新割り当てを使用して、すべてのマップエントリをマップに追加します。
Updateremove(String columnName, Object value):-更新割り当てを使用して、コレクションから値を削除します。Updateclear(String columnName): コレクションをクリアします。Updateincrement(String columnName, Number delta):+更新割り当てを使用して更新します。Updatedecrement(String columnName, Number delta):-更新割り当てを使用して更新します。Updateset(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 オブジェクトが作成されます。
行を削除する方法
次のオーバーロードされたメソッドを使用して、データベースからオブジェクトを削除できます。
booleandelete(Query query, Class<?> entityClass):Queryで選択したオブジェクトを削除します。Tdelete(T entity): 指定されたオブジェクトを削除します。Tdelete(T entity, QueryOptions queryOptions):QueryOptionsを適用して指定されたオブジェクトを削除します。booleandeleteById(Object id, Class<?> entityClass): 指定された ID を使用してオブジェクトを削除します。
楽観的ロック
@Version アノテーションは、Cassandra のコンテキストにおける JPA と同様の構文を提供し、バージョンが一致する行にのみ更新が適用されるようにします。オプティミスティックロックは、Cassandra の軽量トランザクションを利用して、条件付きで行を挿入、更新、削除します。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 | version = 0 でドキュメントを更新します。lastname を設定し、version を 1 にバンプします。 |
| 4 | version = 0 がまだある、以前にロードされたドキュメントを更新してみてください。現在の version は 1 であるため、操作は OptimisticLockingFailureException で失敗します。 |
| オプティミスティックロックは単一エンティティ操作でのみサポートされ、バッチ操作ではサポートされません。 |