web-dev-qa-db-ja.com

キースペース、テーブルを作成し、Spring Dataを使用してテーブルを動的に生成するCassandra

Cassandraを使用して、Spring Bootアプリケーションを使用して動的にキースペースとテーブルを作成します。 Javaベースの構成を使用しています。

@Tableアノテーションが付けられたエンティティがあり、そのスキーマは、事前にわかっている固定フィールドがあるため、アプリケーションの起動前に作成する必要があります。

ただし、ログインしているユーザーに応じて、それらのユーザー用に追加のテーブルを動的に作成し、それらのテーブルにエントリを挿入できるようにしたいと考えています。

誰かが私が利用できるいくつかのリソースに私を案内したり、これらの問題を解決する方法に私を正しい方向に向けることができますか?助けてくれてありがとう!

12
Anu

最も簡単なことは、 Spring Boot Starter Data Cassandra 依存関係をSpring Bootアプリケーションに追加することです。 ..

_<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-cassandra</artifactId>
  <version>1.3.5.RELEASE</version>
</dependency>
_

さらに、これによりSpring Data Cassandradependency がアプリケーションに追加されます。

Spring Data Cassandraでは、CassandraClusterFactoryBean(より正確には、サブクラス... CassandraCqlClusterFactoryBean)を使用してアプリケーションのキースペースを構成できます。 setKeyspaceCreations(:Set) メソッド。

KeyspaceActionSpecification クラスは一目瞭然です。 KeyspaceActionSpecificationFactoryBean を使用して作成し、それをSetに追加して、CassandraClusterFactoryBeansetKeyspaceCreations(..)メソッドに渡すこともできます。

アプリケーションのテーブルを生成するには、基本的に、SD Cassandra @ Table アノテーションを使用して、アプリケーションドメインオブジェクト(エンティティ)に注釈を付ける必要があります。ドメインオブジェクト/エンティティは、アプリケーションのCLASSPATHにあります。

具体的には、アプリケーションに_@Configuration_クラスを拡張して、SD Cassandra AbstractClusterConfiguration クラスを拡張できます。そこに、 getEntityBasePackages())があります。 String [] アプリケーションドメインオブジェクト/エンティティクラスを含むパッケージの場所を提供するためにオーバーライドできるメソッド。これは、SD Cassandraが scan for _@Table_ドメインオブジェクト/エンティティ。

アプリケーション_@Table_ドメインオブジェクト/エンティティが適切に識別されたら、CREATEメソッドを使用してSD Cassandra SchemaActionCassandraSessionFactoryBeanに設定します setSchemaAction( :SchemaAction) 。これにより、スキャン中に見つかったすべてのドメインオブジェクト/エンティティのキ​​ースペースにテーブルが作成され、 identifiedCassandraSessionFactoryBeanに適切なキースペースが適切に提供されます。

明らかに、アプリケーションが複数のキースペースを作成/使用する場合は、特定のキースペースに属するエンティティに適切に設定されたCassandraSessionFactoryBean構成プロパティを使用して、キースペースごとに個別のentityBasePackagesを作成し、関連するテーブルがそのキースペースに作成されるようにする必要があります。 。

さて...

ユーザーごとの「追加の」テーブルの場合、これはかなり複雑でトリッキーです。

ここでSpringプロファイルを活用できる場合がありますが、プロファイルは通常、起動時にのみ適用されます。別のユーザーが既に実行中のアプリケーションにログインする場合、実行時にSpring ApplicationContextに追加の_@Configuration_クラスを提供する方法が必要です。

Spring BootアプリケーションがAnnotationConfigApplicationContextへの参照を挿入し、それをログインイベントで使用してプログラムで register 追加_@Configuration_アプリケーションにログインしたユーザーに基づくクラス。 register(Class...)呼び出しの後にApplicationContext.refresh()を付ける必要があります。

また、テーブルがすでに存在する状況にも適切に対処する必要があります。

これは現在SD Cassandraではサポートされていませんが、詳細については DATACASS-219 を参照してください。

技術的には、実行時にアプリケーションがすべてのユーザーに対して必要とする可能性のあるすべてのテーブルを作成し、Cassandraのセキュリティ設定を使用して、役割と割り当てられた権限によって個々のユーザーアクセスを制限する方がはるかに簡単です。

別のオプションは、ユーザーがアプリケーションにログインするときに必要に応じて一時的なキースペースやテーブルを作成し、ユーザーがログアウトするときにそれらを削除することです。

明らかに、ここには多くの異なる選択肢があり、それはアーキテクチャの決定、トレードオフ、および考慮事項に要約され、技術的な実現可能性を実現するため、注意が必要です。

お役に立てれば。

乾杯!

17
John Blum

以下のSpring構成クラスは、存在しない場合にキースペースとテーブルを作成します。

@Configuration
public class CassandraConfig extends AbstractCassandraConfiguration {
    private static final String KEYSPACE = "my_keyspace";
    private static final String USERNAME = "cassandra";
    private static final String PASSWORD = "cassandra";
    private static final String NODES = "127.0.0.1"; // comma seperated nodes


    @Bean
    @Override
    public CassandraCqlClusterFactoryBean cluster() {
        CassandraCqlClusterFactoryBean bean = new CassandraCqlClusterFactoryBean();
        bean.setKeyspaceCreations(getKeyspaceCreations());
        bean.setContactPoints(NODES);
        bean.setUsername(USERNAME);
        bean.setPassword(PASSWORD);
        return bean;
    }

    @Override
    public SchemaAction getSchemaAction() {
        return SchemaAction.CREATE_IF_NOT_EXISTS;
    }

    @Override
    protected String getKeyspaceName() {
        return KEYSPACE;
    }

    @Override
    public String[] getEntityBasePackages() {
        return new String[]{"com.panda"};
    }


    protected List<CreateKeyspaceSpecification> getKeyspaceCreations() {
        List<CreateKeyspaceSpecification> createKeyspaceSpecifications = new ArrayList<>();
        createKeyspaceSpecifications.add(getKeySpaceSpecification());
        return createKeyspaceSpecifications;
    }

    // Below method creates "my_keyspace" if it doesnt exist.
    private CreateKeyspaceSpecification getKeySpaceSpecification() {
        CreateKeyspaceSpecification pandaCoopKeyspace = new CreateKeyspaceSpecification();
        DataCenterReplication dcr = new DataCenterReplication("dc1", 3L);
        pandaCoopKeyspace.name(KEYSPACE);
        pandaCoopKeyspace.ifNotExists(true).createKeyspace().withNetworkReplication(dcr);
        return pandaCoopKeyspace;
    }

}
9
Enes Altınkaya

@EnesAltınkayaの回答を使用する:

@Value("${cassandra.keyspace}")
private String keySpace;

@Override
protected List<CreateKeyspaceSpecification> getKeyspaceCreations() {
    return Arrays.asList(
            CreateKeyspaceSpecification.createKeyspace()
                    .name(keySpace)
                    .ifNotExists()
                    .withNetworkReplication(new DataCenterReplication("dc1", 3L)));
}

変数を定義するには、application.propertiesまたはapplication.ymlファイルを使用します。

cassandra:
  keyspace: yout_keyspace_name

ハードコードされた文字列の代わりに構成ファイルを使用すると、パスワードやエントリポイント(.gitignoreファイル)を公開せずに、コードをGitHubなどに公開できます。

1
NotMyFaultSir

次のcassandra configurationは、キースペースが存在しない場合に作成し、指定された起動スクリプトも実行します

@Configuration
@PropertySource(value = {"classpath:cassandra.properties"})
@EnableCassandraRepositories
public class CassandraConfig extends AbstractCassandraConfiguration {

  @Value("${cassandra.keyspace}")
  private String cassandraKeyspace;

  @Override
  protected List<CreateKeyspaceSpecification> getKeyspaceCreations() {
    return Collections.singletonList(CreateKeyspaceSpecification.createKeyspace(cassandraKeyspace)
                .ifNotExists()
                .with(KeyspaceOption.DURABLE_WRITES, true)
                .withSimpleReplication());
  }

  @Override
  protected List<String> getStartupScripts() {
    return Collections.singletonList("CREATE TABLE IF NOT EXISTS "+cassandraKeyspace+".test(id UUID PRIMARY KEY, greeting text, occurrence timestamp) WITH default_time_to_live = 600;");
  }

}
0
Viswanath

テーブルの作成には、application.propertiesファイルでこれを使用できます

spring.data.cassandra.schema-action=CREATE_IF_NOT_EXISTS
0
abbas

この答えは、Viswanathの答えに触発されています。

私の_cassandra.yml_は次のようになります:

 _
spring:
  data:
    cassandra:
      cluster-name: Test Cluster
      keyspace-name: keyspace
      port: 9042
      contact-points:
        - 127.0.0.1
_ 
 _
@Configuration
@PropertySource(value = { "classpath:cassandra.yml" })
@ConfigurationProperties("spring.data.cassandra")
@EnableCassandraRepositories(basePackages = "info.vishrantgupta.repository")
public class CassandraConfig extends AbstractCassandraConfiguration {

    @Value("${keyspacename}")
    protected String keyspaceName;

    @Override
    protected String getKeyspaceName() {
        return this.keyspaceName;
    }

    @Override
    protected List getKeyspaceCreations() {
        return Collections.singletonList(CreateKeyspaceSpecification
                .createKeyspace(keyspaceName).ifNotExists()
                .with(KeyspaceOption.DURABLE_WRITES, true)
                .withSimpleReplication());
    }

    @Override
    protected List getStartupScripts() {
        return Collections.singletonList("CREATE KEYSPACE IF NOT EXISTS "
                + keyspaceName + " WITH replication = {"
                + " 'class': 'SimpleStrategy', "
                + " 'replication_factor': '3' " + "};");

    }
}
_ 

@ConfigurationProperties("spring.data.cassandra")をカスタマイズする必要がある場合があります。設定が_cassandra.yml_ファイルのcassandraで始まる場合は、@ConfigurationProperties("cassandra")を使用します

0
Vishrant