1. 概要

Apache Cassandraは、スケーラブルなNoSQLデータベースです。 単一障害点のない継続的な可用性を提供します。 さらに、Cassandraは、並外れたパフォーマンスで大量のデータを処理できます。

このチュートリアルでは、Spring DataとDockerを使用してCassandraに接続する方法を見ていきます。 さらに、Spring Dataリポジトリの抽象化を利用して、Cassandraのデータレイヤーを操作します。

CassandraでさまざまなJava日付値を保存する方法を説明します。 最後に、これらの日付値がCassandraタイプにどのようにマップされるかを調査します。

2. カサンドラの春のデータ

Apache CassandraのSpringデータは、Spring開発者にCassandraを操作するための使い慣れたインターフェイスを提供します。 このプロジェクトは、Cassandraデータストレージを使用したソリューションの開発にSpringのコアコンセプトを適用します。

Spring Dataを使用すると、一般的なSpringインターフェイスに基づいてリポジトリを作成できます。 また、 QueryBuilders を使用して、Cassandraクエリ言語(CQL)を学習する必要がなくなります。 プロジェクトは、リッチオブジェクトマッピングを可能にする単純な注釈を提供します。

2つの重要なヘルパークラスがあります。

  • CqlTemplateは一般的なデータアクセス操作を処理します
  • CassandraTemplateはオブジェクトマッピングを提供します

このプロジェクトには、SpringのコアJDBCサポートとの顕著な類似点があります。

3. テスト環境のセットアップ

開始するには、Cassandraインスタンスへの接続を設定する必要があります。

代わりに、ApacheCassandra上に構築されたクラウドベースのデータベースであるAstraDBデータベースに接続することもできます。

このガイドでは、その方法を説明します DatastaxAstraDBに接続します.

3.1. カサンドラコンテナ

Testcontainersライブラリを使用してCassandraを構成して起動しましょう。 まず、Cassandraコンテナを定義し、それを特定のポートに公開します。

@Container
public static final CassandraContainer cassandra = (CassandraContainer) new CassandraContainer("cassandra:3.11.2")
    .withExposedPorts(9042);

次に、Spring DataがCassandraコンテナとの接続を確立できるようにするために、テストプロパティをオーバーライドする必要があります。

TestPropertyValues.of(
    "spring.data.cassandra.keyspace-name=" + KEYSPACE_NAME,
    "spring.data.cassandra.contact-points=" + cassandra.getContainerIpAddress(),
    "spring.data.cassandra.port=" + cassandra.getMappedPort(9042)
).applyTo(configurableApplicationContext.getEnvironment());

最後に、オブジェクト/テーブルを作成する前に、キースペースを作成する必要があります。

session.execute("CREATE KEYSPACE IF NOT EXISTS " + KEYSPACE_NAME + " WITH replication = {'class':'SimpleStrategy','replication_factor':'1'};");

キースペースは、Cassandraの単なるデータコンテナです。 実際、これはRDBMSのデータベースと非常によく似ています。

3.2. Cassandraリポジトリ

Spring Dataのリポジトリのサポートにより、DAOの実装が大幅に容易になります。 簡単なDAOを作成することから始めましょう。

org.springframework.data.cassandra.core.mappingパッケージで提供される@Tableアノテーションにより、ドメインオブジェクトのマッピングが可能になります。

@Table
public class Person {

    @PrimaryKey
    private UUID id;
    private String firstName;
    private String lastName;

    public Person(UUID id, String firstName, String lastName) {
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
    }

    //getters, setters, equals and hash code

}

次に、 CassandraRepository インターフェイスを拡張して、DAOのSpring Dataリポジトリを定義します。

@Repository
public interface PersonRepository extends CassandraRepository<Person, UUID> {}

最後に、統合テストの作成を開始する前に、2つの追加のプロパティを定義する必要があります。

spring.data.cassandra.schema-action=create_if_not_exists
spring.data.cassandra.local-datacenter=datacenter1

最初のプロパティは、SpringDataが自動的に注釈付きテーブルを作成することを保証します。

この設定は実稼働システムには推奨されないことに注意してください。

4. 日付値の使用

ApacheCassandraのSpringDataの最新バージョンでは、日付値の操作は非常に簡単です。 Spring Dataは、Javaの日付タイプがApacheCassandra表現との間で正しくマップされることを自動的に保証します

4.1. LocalDateタイプ

タイプLocalDateの新しいフィールドbirthDatePersonDAOに追加しましょう。

@Test
public void givenValidPersonUsingLocalDate_whenSavingIt_thenDataIsPersisted() {
    UUID personId = UUIDs.timeBased();
    Person newPerson = new Person(personId, "Luka", "Modric");
    newPerson.setBirthDate(LocalDate.of(1985, 9, 9));
    personRepository.save(newPerson);

    List<Person> savedPersons = personRepository.findAllById(List.of(personId));
    assertThat(savedPersons.get(0)).isEqualTo(newPerson);
}

Spring Dataは、JavaのLocalDateをCassandraの日付型に自動的に変換します。 DAOのLocalDate値は、Cassandraからレコードを保存およびフェッチした後も同じです。

4.2. LocalDateTimeタイプ

タイプLocalDateTimelastVisitedDateという別のフィールドをPersonDAOに追加しましょう。

@Test
public void givenValidPersonUsingLocalDateTime_whenSavingIt_thenDataIsPersisted() {
    UUID personId = UUIDs.timeBased();
    Person newPerson = new Person(personId, "Luka", "Modric");
    newPerson.setLastVisitedDate(LocalDateTime.of(2021, 7, 13, 11, 30));
    personRepository.save(newPerson);

    List<Person> savedPersons = personRepository.findAllById(List.of(personId));
    assertThat(savedPersons.get(0)).isEqualTo(newPerson);
}

Spring Dataは、JavaのLocalDateTimeをCassandraのタイムスタンプタイプに自動的に変換します。 DAOのLocalDateTime値は、Cassandraからレコードを保存およびフェッチした後も同じです。

4.3. レガシー日付タイプ

最後に、レガシータイプDatelastPurchasedDateというフィールドをPersonDAOに追加しましょう。

@Test
public void givenValidPersonUsingLegacyDate_whenSavingIt_thenDataIsPersisted() {
    UUID personId = UUIDs.timeBased();
    Person newPerson = new Person(personId, "Luka", "Modric");
    newPerson.setLastPurchasedDate(new Date(LocalDate.of(2021, 7, 13).toEpochDay()));
    personRepository.save(newPerson);

    List<Person> savedPersons = personRepository.findAllById(List.of(personId));
    assertThat(savedPersons.get(0)).isEqualTo(newPerson);
}

LocalDateTimeと同様に、Spring DataはJavaのjava.util.DateをCassandraのタイムスタンプタイプに変換します。

4.4. マップされたカサンドラタイプ

CQLSHを使用してCassandraに保存されたデータを確認してみましょう。 これは、CQLを介してCassandraと対話するためのコマンドラインシェルです。

テストの実行中にCassandraコンテナに保存されたデータを確認するために、テストにブレークポイントを設定するだけです。 一時停止したテストの実行中に、DockerDesktopアプリケーションを介してDockerコンテナCLIに接続できます。

DockerコンテナCLIに接続した後、最初にキースペースを選択し、次にテーブルを選択する必要があります。

# cqlsh
Connected to Test Cluster at 127.0.0.1:9042.
[cqlsh 5.0.1 | Cassandra 3.11.2 | CQL spec 3.4.4 | Native protocol v4]
Use HELP for help.
cqlsh> USE test;
cqlsh:test> select * from person;

その結果、CQLSHは、テーブルに保存されたデータのフォーマットされた出力を表示します。

 id                                   | birthdate  | firstname | lastname | lastpurchaseddate | lastvisiteddate
--------------------------------------+------------+-----------+----------+-------------------+-----------------
 9abef910-e3fd-11eb-9829-c5149ac796de | 1985-09-09 |      Luka |   Modric |              null |            null

ただし、特定の日付列に使用されているデータ型も確認したいと思います。

cqlsh:test> DESC TABLE person;

出力は、テーブルの作成に使用されたCQLコマンドを返します。 したがって、すべてのデータ型の定義が含まれています。

CREATE TABLE test.person (
    id uuid PRIMARY KEY,
    birthdate date,
    firstname text,
    lastname text,
    lastpurchaseddate timestamp,
    lastvisiteddate timestamp
)

5. 結論

この記事では、ApacheCassandraのSpringDataでさまざまな日付値を操作する方法について説明しました。

例では、 LocalDate LocalDateTime、および従来の DateJavaタイプの操作について説明しました。 Testcontainersを使用してCassandraインスタンスに接続する方法を確認しました。 最後に、Spring Dataリポジトリの抽象化を使用して、Cassandraに格納されているデータを操作しました。

いつものように、ソースコードはGitHubから入手できます。