使用Spring Data Cassandra

时间:2016-05-20 17:37:13

标签: java spring-boot cassandra spring-data-cassandra

使用Cassandra,我想使用Spring Boot应用程序动态创建键空间和表。我正在使用基于Java的配置。

我有一个用@Table注释的实体,我希望在应用程序启动之前创建它的模式,因为它具有事先已知的固定字段。

但是,根据登录用户的不同,我还想动态地为这些用户创建附加表,并能够向这些表插入条目。

有人可以引导我使用一些我可以利用的资源,或指出我如何解决这些问题。非常感谢您的帮助!

6 个答案:

答案 0 :(得分:14)

最简单的方法是将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 Cassandra dependency添加到您的应用程序中。

使用 Spring Data Cassandra ,您可以使用CassandraClusterFactoryBean(或更确切地说,子类... CassandraCqlClusterFactoryBean配置应用程序的Keyspace )通过调用setKeyspaceCreations(:Set)方法。

KeyspaceActionSpecification类非常明显。您甚至可以使用KeyspaceActionSpecificationFactoryBean创建一个,将其添加到Set,然后将其传递到setKeyspaceCreations(..)上的CassandraClusterFactoryBean方法。

为了生成应用程序表,您基本上只需要使用SD Cassandra @Table注释来注释您的应用程序域对象(实体),并确保您的域对象/实体可以是在应用程序的CLASSPATH中找到。

具体来说,您可以让应用程序@Configuration类扩展SD Cassandra AbstractClusterConfiguration类。在那里,您将找到可以覆盖的getEntityBasePackages():String[]方法,以提供包含应用程序域对象/实体类的包位置,然后SD Cassandra将scan用于@Table域对象/实体。

在正确识别您的应用@Table域对象/实体的情况下,您可以使用CREATE方法SchemaAction将SD Cassandra setSchemaAction(:SchemaAction)设置为CassandraSessionFactoryBean。这将在您的Keyspace中为扫描期间找到的所有域对象/实体创建表格,为您CassandraSessionFactoryBean提供identified适当的Keyspace。

显然,如果您的应用程序创建/使用多个Keyspace,您需要为每个Keyspace创建一个单独的CassandraSessionFactoryBean,并为属于特定Keyspace的实体设置适当的entityBasePackages配置属性,以便在那个Keyspace中创建相关的表。

现在...

对于&#34;额外&#34;每个用户的表格,这是相当复杂和棘手的。

您可以在此处利用Spring Profiles,但是,配置文件通常仅在启动时应用。如果其他用户登录到已在运行的应用程序,则需要一种方法在运行时向Spring @Configuration提供其他ApplicationContext类。

您的 Spring Boot 应用程序可以注入对AnnotationConfigApplicationContext的引用,然后在登录事件上使用它以编程方式register基于其他@Configuration类登录应用程序的用户。您需要使用register(Class...)跟踪ApplicationContext.refresh()来电。

您还需要妥善处理已存在表格的情况。

SD Cassandra目前不支持此功能,但有关详细信息,请参阅DATACASS-219

从技术上讲,在运行时为所有用户创建应用程序所需的所有可能的表并使用Cassandra的安全设置来限制按角色和分配的权限的个人用户访问将更加简单。

另一种选择可能只是在用户登录应用程序时根据需要创建临时Keyspace和/或表,在用户注销时删除它们。

显然,这里有很多不同的选择,它更多地归结为架构决策,权衡和考虑,然后它具有技术可行性,所以要小心。

希望这有帮助。

干杯!

答案 1 :(得分:8)

在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;
    }

}

答案 2 :(得分:1)

使用@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.propertiesapplication.yml文件:

cassandra:
  keyspace: yout_keyspace_name

使用配置文件而不是硬编码字符串,您可以在例如GitHub上发布代码,而无需发布密码和入口点(.gitignore文件),这可能会带来安全风险。

答案 3 :(得分:0)

以下 cassandra配置 会在不存在的情况下创建密钥空间并运行指定的启动脚本

@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;");
  }

}

答案 4 :(得分:0)

这个答案的灵感来自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开头,则可能必须自定义cassandra.yml,然后使用@ConfigurationProperties("cassandra")

答案 5 :(得分:0)

要创建表,您可以在application.properties文件中使用它

spring.data.cassandra.schema-action=CREATE_IF_NOT_EXISTS