使用Spring Data Cassandra动态创建Keyspace、Table和生成表格的方法

13
使用Cassandra,我想通过Spring Boot应用程序动态创建keyspace和表。我正在使用基于Java的配置。
我有一个使用@Table注释的实体,其模式需要在应用程序启动之前创建,因为它具有预先知道的固定字段。
但是,根据登录的用户,我还想为那些用户动态创建其他表,并能够向这些表中插入条目。
请问是否有一些资源可以帮助我解决这些问题,或指导我如何解决这些问题?非常感谢您的帮助!
6个回答

18
最简单的方法是将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,您可以通过调用setKeyspaceCreations(:Set)方法来配置应用程序的Keyspace(s),使用CassandraClusterFactoryBean(或更精确地说,是子类...CassandraCqlClusterFactoryBean)。

KeyspaceActionSpecification类相当容易理解。你甚至可以使用KeyspaceActionSpecificationFactoryBean创建一个实例,将其添加到Set中,然后将其传递给CassandraClusterFactoryBean上的setKeyspaceCreations(..)方法。

要生成应用程序的表格,你只需要使用SD Cassandra @Table注释来注释你的应用程序域对象(实体),并确保你的域对象/实体可以在应用程序的CLASSPATH中找到即可。

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

当您正确标识应用程序中的 @Table 领域对象/实体时,您可以使用 CassandraSessionFactoryBean 方法将 SD Cassandra SchemaAction 设置为 CREATEsetSchemaAction(:SchemaAction)。这将为扫描期间发现的所有领域对象/实体在您的Keyspace中创建表,前提是您已经适当地在CassandraSessionFactoryBean标识了 正确的Keyspace。

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

现在...

对于每个用户的“附加”表,这就变得更加复杂和棘手。

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

您的Spring Boot应用程序可以注入对AnnotationConfigApplicationContext的引用,然后在登录事件上使用它,根据登录到应用程序的用户编程式地注册附加的@Configuration类。在您的register(Class...)调用之后,需要跟随ApplicationContext.refresh()

您还需要适当处理已存在表的情况。
SD Cassandra目前不支持此功能,请参见 DATACASS-219以获取更多详细信息。
从技术上讲,为所有用户在运行时创建应用程序所需的所有可能的表,并使用Cassandra的安全设置按角色和分配的权限限制单个用户访问,将更加简单。
另一个选择可能只是在用户登录到应用程序时根据需要创建临时键空间和/或表,在用户注销时删除它们。
显然,这里有很多不同的选择,它更多地涉及架构决策、权衡和考虑因素,而不是技术可行性,因此请小心。
希望能对您有所帮助。
干杯!

10

以下 Spring 配置类将创建 Keyspace 和表(如果它们不存在)。

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

}

1
我已经按照这段代码进行操作,但是在应用程序启动时仍然无法创建Keyspace和表。我是否还遗漏了其他内容?请指导我。 - Milesh

2
使用@Enes Altı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文件),这可能会带来安全风险。


1
以下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;");
  }

}

1

您可以在application.properties文件中使用以下内容来创建表格:

spring.data.cassandra.schema-action=CREATE_IF_NOT_EXISTS

0

这个答案受到了Viswanath的启发。

我的cassandra.yml如下所示:


spring:
  data:
    cassandra:
      cluster-name: 测试集群
      keyspace-name: 键空间
      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' " + "};");
} }

如果你的配置文件以 cassandra 开头,则需要自定义 @ConfigurationProperties("spring.data.cassandra"),并使用 @ConfigurationProperties("cassandra")


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接