準備されたステートメント
複数回実行される CQL ステートメントを準備して PreparedStatement
オブジェクトに保存すると、クエリのパフォーマンスが向上します。ドライバーと Cassandra は両方とも、PreparedStatement
クエリのメタデータへのマッピングを維持します。次の抽象化を通じて準備されたステートメントを使用できます。
準備されたステートメントを有効にすることによる
CassandraTemplate
、AsyncCassandraTemplate
、ReactiveCassandraTemplate
Cassandra リポジトリはテンプレート API 上に構築されています
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 以降、プリペアドステートメントはドライバーレベルでキャッシュされるため、アプリケーションでプリペアドステートメントを追跡する必要がなくなります。
次の例は、パラメーター化されたプリペアドステートメントを使用してクエリを発行する方法を示しています。
命令的
リアクティブ
String lastName = cqlTemplate.queryForObject(
"SELECT last_name FROM t_actor WHERE id = ?",
String.class, 1212L);
Mono<String> lastName = reactiveCqlTemplate.queryForObject(
"SELECT last_name FROM t_actor WHERE id = ?",
String.class, 1212L);
ステートメントの準備とパラメーターのバインドをさらに制御する必要がある場合 (たとえば、名前付きバインディングパラメーターを使用する)、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));
Flux<String> lastNames = reactiveCqlTemplate.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
- 準備されたステートメントに引数をバインドするユーティリティクラス。
CassandraTemplate
を使用する
CassandraTemplate
クラスは CqlTemplate
上に構築され、より高いレベルの抽象化を提供します。準備されたステートメントの使用は、setUsePreparedStatements(false)
および setUsePreparedStatements(true)
をそれぞれ呼び出すことによって、CassandraTemplate
(およびその非同期およびリアクティブなバリアント) 上で直接制御できます。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);
template.setUsePreparedStatements(true);
Mono<Actor> actorByQuery = template.selectOne(query(where("id").is(42)), Actor.class);
Mono<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>)
など) は、API の一部として CQL Statement
オブジェクトも受け入れます。
Statement
を SimpleStatement
オブジェクトで受け入れるメソッドを呼び出すときに、準備されたステートメントに参加することができます。テンプレート API はクエリ文字列とパラメーター (位置パラメーターと名前付きパラメーター) を抽出し、これらを使用してステートメントを準備、バインド、実行します。非 SimpleStatement
オブジェクトは、準備されたステートメントでは使用できません。
プリペアドステートメントのキャッシュ
Cassandra ドライバー 4.0 以降、準備されたステートメントは CqlSession
キャッシュによってキャッシュされるため、同じ文字列を 2 回準備しても問題ありません。以前のバージョンでは、ドライバーの外部で準備されたステートメントをキャッシュする必要がありました。詳細については、プリペアドステートメントに関するドライバードキュメント (英語) も参照してください。