Spring DataのCrudRepository
, ReactiveCrudRepository
は汎用的な作りになっていて、CassandraのTTL機能を使うインターフェースがありません。
検索してみて日本語の情報が見当たらなかったので、Cassandraに書き込む時にTTLを指定する方法を書き残しておきます。
以下のバージョンで確認しています。
新しいバージョンでは事情が変わっているかもしれません。
- Cassandra 3.11
- Spring Boot 2.5.5
- Spring Data for Apache Cassandra 3.2.5
例として、ユーザー情報を扱う UserRepository
を作成していきます。
具体的には、以下のような構成でインターフェース、クラスを作成します。
(グレーのインターフェース, クラスはSpring Dataのクラスです)
CREATE TABLE users (
id text,
first_name text,
last_name text,
PRIMARY KEY (id)
);
書き込み時にTTLを設定するカスタムインターフェース UserTtlRepository
を追加します。
動作確認のため、TTLの値を見るメソッドも追加しています。
public interface UserTtlRepository {
/**
* UserエンティティをTTL付きで保存する
*
* @param user ユーザー
* @param ttl TTL
* @return ユーザーのMono
*/
Mono<User> save(User user, Duration ttl);
/**
* firstNameカラムのTTLを取得する
*
* @param id ユーザーID
* @return TTLのMono
*/
Mono<Duration> findFirstNameTtlById(String id);
/**
* lastNameカラムのTTLを取得する
*
* @param id ユーザーID
* @return TTLのMono
*/
Mono<Duration> findLastNameTtlById(String id);
}
UserRepositoy
インターフェースを ReactiveCrudRepository
だけでなく UserTtlRepository
も継承させます。
@Repository
public interface UserRepository extends ReactiveCrudRepository<User, String>, UserTtlRepository {
}
カスタムインターフェースの実装クラス UserTtlRepositoryImpl
を作成します。
実装クラスの名前は (カスタムインターフェース名) + Impl
でないといけません。(repository-impl-postfix
の設定で変えられるそうです)
public class UserTtlRepositoryImpl implements UserTtlRepository {
private final ReactiveCassandraOperations reactiveCassandraOperations;
public UserTtlRepositoryImpl(final ReactiveCassandraOperations reactiveCassandraOperations) {
this.reactiveCassandraOperations = reactiveCassandraOperations;
}
@Override
public Mono<User> save(final User user, final Duration ttl) {
InsertOptions insertOptions = InsertOptions.builder().ttl(ttl).build();
return reactiveCassandraOperations.insert(user, insertOptions)
.map(EntityWriteResult::getEntity);
}
@Override
public Mono<Duration> findFirstNameTtlById(final String id) {
return findColumnTtlByIdAndColumnName(id, User.FIRST_NAME_COLUMN_NAME);
}
@Override
public Mono<Duration> findLastNameTtlById(final String id) {
return findColumnTtlByIdAndColumnName(id, User.LAST_NAME_COLUMN_NAME);
}
private Mono<Duration> findColumnTtlByIdAndColumnName(final String id, final String columnName) {
SimpleStatement statement = QueryBuilder.selectFrom(User.TABLE_NAME)
.ttl(columnName)
.whereColumn(User.ID_COLUMN_NAME)
.isEqualTo(literal(id))
.build();
return reactiveCassandraOperations.selectOne(statement, Integer.class)
.map(Duration::ofSeconds);
}
}
以上で UserRepository
に TTL を操作するインターフェースを追加できました。
Springが UserRepository
の実装を生成する時に UserTtlRepositoryImpl
も組み込んでくれます。
このページで作ったコードは以下に置いてあります。
(動作確認のため結合テストもしてます)
https://github.com/massakai/spring-data-cassandra-example