Spring Data Cassandraの紹介

Spring Data Cassandraの概要

1. 概要

この記事は、Spring DataでCassandraを操作するための実用的な入門書です。

基本から始めて構成とコーディングを行い、最終的に完全なSpring Data Cassandraモジュールを構築します。

2. Mavenの依存関係

Mavenを使用して、pom.xmlで依存関係を定義することから始めましょう。


    com.datastax.cassandra
    cassandra-driver-core
    2.1.9

3. Cassandraの構成

この全体を通してJavaスタイルの構成を使用して、Cassandra統合を構成します。

3.1. メイン構成

メインの構成クラスから始めましょう–もちろん、クラスレベル@Configuration annotationを介して駆動されます。

@Configuration
public class CassandraConfig extends AbstractCassandraConfiguration {

    @Override
    protected String getKeyspaceName() {
        return "testKeySpace";
    }

    @Bean
    public CassandraClusterFactoryBean cluster() {
        CassandraClusterFactoryBean cluster =
          new CassandraClusterFactoryBean();
        cluster.setContactPoints("127.0.0.1");
        cluster.setPort(9142);
        return cluster;
    }

    @Bean
    public CassandraMappingContext cassandraMapping()
      throws ClassNotFoundException {
        return new BasicCassandraMappingContext();
    }
}

デフォルトの実装を持つ新しいBean –BasicCassandraMappingContext –に注目してください。 これは、オブジェクトと永続形式の間で永続エンティティをマッピングするために必要です。

また、デフォルトの実装は十分に機能するため、直接使用できます。

3.2. Cassandra接続のプロパティ

Cassandraクライアントの接続をセットアップするために構成する必要がある3つの必須設定があります。

contactPoints. Portとして実行されているCassandraサーバーがサーバーでのリクエストのリスニングポートであるというホスト名を設定する必要があります。 KeyspaceNameは、ノードでのデータレプリケーションを定義する名前空間であり、Cassandra関連の概念に基づいています。

4. Cassandraリポジトリ

データアクセス層にはCassandraRepositoryを使用します。 これは、異なる永続性メカニズムにわたってデータアクセスレイヤーを実装するために必要なコードを抽象化することに焦点を当てたSpring Dataリポジトリの抽象化に従います。

4.1. CassandraRepositoryを作成します

構成で使用するCassandraRepositoryを作成しましょう。

@Repository
public interface BookRepository extends CassandraRepository {
    //
}

4.2. CassandraRepositoryの構成

これで、セクション3.1の構成を拡張し、@EnableCassandraRepositoriesクラスレベルのアノテーションを追加して、セクション4.1で作成したCassandraリポジトリをCassandraConfig:でマークできます。

@Configuration
@EnableCassandraRepositories(
  basePackages = "org.example.spring.data.cassandra.repository")
public class CassandraConfig extends AbstractCassandraConfiguration {
    //
}

5. エンティティ

エンティティ、つまり使用するモデルクラスを簡単に見てみましょう。 クラスには注釈が付けられ、埋め込みモードでのメタデータCassandraデータテーブル作成用の追加パラメーターを定義します。

@Tableアノテーションを使用して、BeanはCassandraデータテーブルに直接マップされます。 また、各プロパティは主キーのタイプまたは単純な列として定義されます。

@Table
public class Book {
    @PrimaryKeyColumn(
      name = "isbn",
      ordinal = 2,
      type = PrimaryKeyType.CLUSTERED,
      ordering = Ordering.DESCENDING)
    private UUID id;
    @PrimaryKeyColumn(
      name = "title", ordinal = 0, type = PrimaryKeyType.PARTITIONED)
    private String title;
    @PrimaryKeyColumn(
      name = "publisher", ordinal = 1, type = PrimaryKeyType.PARTITIONED)
    private String publisher;
    @Column
    private Set tags = new HashSet<>();
    // standard getters and setters
}

6. 組み込みサーバーでのテスト

6.1. Mavenの依存関係

Cassandraを組み込みモードで(別のCassandraサーバーを手動でインストールせずに)実行する場合は、cassandra-unitに関連する依存関係をpom.xmlに追加する必要があります。


    org.cassandraunit
    cassandra-unit-spring
    2.1.9.2
    test
    
        
        org.cassandraunit
        cassandra-unit
        
    


    org.cassandraunit
    cassandra-unit-shaded
    2.1.9.2
    test


    org.hectorclient
    hector-core
    2.0-0

use an embedded Cassandra server to test this applicationすることが可能です。 主な利点は、Cassandraを明示的にインストールしたくないことです。

この組み込みサーバーは、Spring JUnitテストとも互換性があります。 ここでは、組み込みサーバーと一緒に@RunWithアノテーションを使用してSpringJUnit4ClassRunnerを設定できます。 したがって、外部Cassandraサービスを実行しなくても、完全なテストスイートを実装できます。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = CassandraConfig.class)
public class BookRepositoryIntegrationTest {
    //
}

6.2. サーバーの起動と停止

外部Cassandraサーバーを実行している場合、このセクションは無視できます。

テストスイート全体でサーバーを1回起動する必要があるため、サーバーの起動メソッドには@BeforeClassアノテーションが付けられます。

@BeforeClass
public static void startCassandraEmbedded() {
    EmbeddedCassandraServerHelper.startEmbeddedCassandra();
    Cluster cluster = Cluster.builder()
      .addContactPoints("127.0.0.1").withPort(9142).build();
    Session session = cluster.connect();
}

次に、テストスイートの実行の完了後にサーバーが停止していることを確認する必要があります。

@AfterClass
public static void stopCassandraEmbedded() {
    EmbeddedCassandraServerHelper.cleanEmbeddedCassandra();
}

6.3. クリーンなデータテーブル

以前のテスト実行で操作されたデータによる予期しない結果を回避するために、すべてのテスト実行の前にデータテーブルを削除して作成することをお勧めします。

これで、サーバーの起動時にデータテーブルを作成できます。

@Before
public void createTable() {
    adminTemplate.createTable(
      true, CqlIdentifier.cqlId(DATA_TABLE_NAME),
      Book.class, new HashMap());
}

すべてのテストケースの実行後にドロップします。

@After
public void dropTable() {
    adminTemplate.dropTable(CqlIdentifier.cqlId(DATA_TABLE_NAME));
}

7. CassandraRepositoryを使用したデータアクセス

上で作成したBookRepositoryを直接使用して、Cassandraデータベースのデータを永続化、操作、およびフェッチできます。

7.1. 新しい本を保存する

ブックストアに新しい本を保存できます:

Book javaBook = new Book(
  UUIDs.timeBased(), "Head First Java", "O'Reilly Media",
  ImmutableSet.of("Computer", "Software"));
bookRepository.save(ImmutableSet.of(javaBook));

次に、データベースに挿入された本の可用性を確認できます。

Iterable books = bookRepository.findByTitleAndPublisher(
  "Head First Java", "O'Reilly Media");
assertEquals(javaBook.getId(), books.iterator().next().getId());

7.2. 既存の本を更新する

新しい本を挿入することから始めましょう。

Book javaBook = new Book(
  UUIDs.timeBased(), "Head First Java", "O'Reilly Media",
  ImmutableSet.of("Computer", "Software"));
bookRepository.save(ImmutableSet.of(javaBook));

タイトルで本を取得しましょう:

Iterable books = bookRepository.findByTitleAndPublisher(
  "Head First Java", "O'Reilly Media");

次に、本のタイトルを変更しましょう。

javaBook.setTitle("Head First Java Second Edition");
bookRepository.save(ImmutableSet.of(javaBook));

最後に、データベースでタイトルが更新されているかどうかを確認しましょう。

Iterable books = bookRepository.findByTitleAndPublisher(
  "Head First Java Second Edition", "O'Reilly Media");
assertEquals(
  javaBook.getTitle(), updateBooks.iterator().next().getTitle());

7.3. 既存の本を削除する

新しい本を挿入します。

Book javaBook = new Book(
  UUIDs.timeBased(), "Head First Java", "O'Reilly Media",
  ImmutableSet.of("Computer", "Software"));
bookRepository.save(ImmutableSet.of(javaBook));

次に、新しく入力した本を削除します。

bookRepository.delete(javaBook);

これで、削除を確認できます。

Iterable books = bookRepository.findByTitleAndPublisher(
  "Head First Java", "O'Reilly Media");
assertNotEquals(javaBook.getId(), books.iterator().next().getId());

これにより、コードがNoSuchElementExceptionをスローして、ブックが削除されたことを確認します。

7.4. すべての本を探す

最初に新しい本を挿入します。

Book javaBook = new Book(
  UUIDs.timeBased(), "Head First Java", "O'Reilly Media",
  ImmutableSet.of("Computer", "Software"));
Book dPatternBook = new Book(
  UUIDs.timeBased(), "Head Design Patterns","O'Reilly Media",
  ImmutableSet.of("Computer", "Software"));
bookRepository.save(ImmutableSet.of(javaBook));
bookRepository.save(ImmutableSet.of(dPatternBook));

すべての書籍を検索:

Iterable books = bookRepository.findAll();

その後、データベースで利用可能な書籍の数を確認できます。

int bookCount = 0;
for (Book book : books) bookCount++;
assertEquals(bookCount, 2);

8. 結論

CassandraRepositoryデータアクセスメカニズムを使用した最も一般的なアプローチを使用して、Springデータを使用したCassandraの基本的な実践的な紹介を行いました。

上記のコードスニペットと例の実装はmy GitHub projectにあります。これはEclipseベースのプロジェクトであるため、そのままインポートして実行するのは簡単です。