java 使用 Spring Data Cassandra 动态创建键空间、表和生成表

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/37352689/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 02:25:36  来源:igfitidea点击:

Create keyspace, table and generate tables dynamically using Spring Data Cassandra

javaspring-bootcassandraspring-data-cassandra

提问by Anu

Using Cassandra, I want to create keyspace and tables dynamically using Spring Boot application. I am using Java based configuration.

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

I have an entity annotated with @Table whose schema I want to be created before application starts up since it has fixed fields that are known beforehand.

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

However depending on the logged in user, I also want to create additional tables for those user dynamically and be able to insert entries to those tables.

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

Can somebody guide me to some resources that I can make use of or point me in right direction in how to go about solving these issues. Thanks a lot for help!

有人可以指导我找到一些我可以使用的资源,或者为我指明如何解决这些问题的正确方向。非常感谢您的帮助!

回答by John Blum

The easiest thing to do would be to add the Spring Boot Starter Data Cassandradependency to your Spring Bootapplication, like so...

最简单的方法是将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>

In addition, this will add the Spring Data Cassandradependencyto your application.

此外,这会将Spring Data Cassandra依赖项添加到您的应用程序。

With Spring Data Cassandra, you can configure your application's Keyspace(s) using the CassandraClusterFactoryBean(or more precisely, the subclass... CassandraCqlClusterFactoryBean) by calling the setKeyspaceCreations(:Set)method.

使用Spring Data Cassandra,您可以通过调用setKeyspaceCreations(:Set)方法使用CassandraClusterFactoryBean(或更准确地说,子类... CassandraCqlClusterFactoryBean)来配置应用程序的密钥空间

The KeyspaceActionSpecificationclass is pretty self-explanatory. You can even create one with the KeyspaceActionSpecificationFactoryBean, add it to a Setand then pass that to the setKeyspaceCreations(..)method on the CassandraClusterFactoryBean.

KeyspaceActionSpecification类是不言自明。你甚至可以创建一个与KeyspaceActionSpecificationFactoryBean,将其添加到Set,然后传递到setKeyspaceCreations(..)上方法CassandraClusterFactoryBean

For generating the application's Tables, you essentially just need to annotate your application domain object(s) (entities) using the SD Cassandra @Tableannotation, and make sure your domain objects/entities can be found on the application's CLASSPATH.

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

Specifically, you can have your application @Configurationclass extend the SD Cassandra AbstractClusterConfigurationclass. There, you will find the getEntityBasePackages():String[]method that you can override to provide the package locations containing your application domain object/entity classes, which SD Cassandra will then use to scanfor @Tabledomain object/entities.

具体来说,您可以让您的应用程序@Configuration类扩展 SD Cassandra AbstractClusterConfiguration类。在那里,你会发现getEntityBasePackages()的String []的方法,你可以重写提供包含应用程序的域对象/实体类,SD卡珊德拉将使用该包装的位置扫描@Table域对象/实体。

With your application @Tabledomain object/entities properly identified, you set the SD Cassandra SchemaActionto CREATEusing the CassandraSessionFactoryBeanmethod, setSchemaAction(:SchemaAction). This will create Tables in your Keyspace for all domain object/entities found during the scan, providing you identifiedthe proper Keyspace on your CassandraSessionFactoryBeanappropriately.

@Table正确识别您的应用程序域对象/实体后,您将 SD Cassandra SchemaAction设置为CREATE使用CassandraSessionFactoryBean方法setSchemaAction(:SchemaAction)。这将为扫描期间找到的所有域对象/实体在您的密钥空间中创建表,前提是您适当地确定了正确的密钥空间CassandraSessionFactoryBean

Obviously, if your application creates/uses multiple Keyspaces, you will need to create a separate CassandraSessionFactoryBeanfor each Keyspace, with the entityBasePackagesconfiguration property set appropriately for the entities that belong to a particular Keyspace, so that the associated Tables are created in that Keyspace.

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

Now...

现在...

For the "additional" Tables per user, that is quite a bit more complicated and tricky.

对于每个用户的“附加”表,这有点复杂和棘手。

You might be able to leverage Spring Profiles here, however, profiles are generally only applied on startup. If a different user logs into an already running application, you need a way to supply additional @Configurationclasses to the Spring ApplicationContextat runtime.

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

Your Spring Bootapplication could inject a reference to a AnnotationConfigApplicationContext, and then use it on a login event to programmatically registeradditional @Configurationclasses based on the user who logged into the application. You need to follow your register(Class...)call(s) with an ApplicationContext.refresh().

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

You also need to appropriately handle the situation where the Tables already exist.

您还需要适当处理表已经存在的情况。

This is not currently supported in SD Cassandra, but see DATACASS-219for further details.

SD Cassandra 目前不支持此功能,但请参阅DATACASS-219了解更多详细信息。

Technically, it would be far simpler to create all the possible Tables needed by the application for all users at runtime and use Cassandra's security settings to restrict individual user access by role and assigned permissions.

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

Another option might be just to create temporary Keyspaces and/or Tables as needed when a user logs in into the application, drop them when the user logs out.

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

Clearly, there are a lot of different choices here, and it boils down more to architectural decisions, tradeoffs and considerations then it does technical feasibility, so be careful.

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

Hope this helps.

希望这可以帮助。

Cheers!

干杯!

回答by Enes Alt?nkaya

Following spring configuration class creates keyspace and tables if they dont exist.

如果键空间和表不存在,则遵循 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;
    }

}

回答by NotMyFaultSir

Using @Enes Alt?nkaya answer:

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

To define your varaibles use an application.propertiesor application.ymlfile:

要定义您的变量,请使用application.propertiesapplication.yml文件:

cassandra:
  keyspace: yout_keyspace_name

Using config files instead of hardcoded strings you can publish your code on for example GitHub without publishing your passwords and entrypoints (.gitignorefiles) which may be a security risk.

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

回答by abbas

For table's creation you can use this in the application.properties file

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

spring.data.cassandra.schema-action=CREATE_IF_NOT_EXISTS

回答by Viswanath

The following cassandra configurationwill create a keyspace when it does not exist and also run the start-up script specified

下面的cassandra配置会在keyspace不存在时创建一个keyspace并运行指定的启动脚本

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

}

回答by Vishrant

This answer is inspired by Viswanath's answer.

这个答案的灵感来自 Viswanath 的答案。

My cassandra.ymllooks as follows:

我的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' " + "};");

    }
}

You might have to customize @ConfigurationProperties("spring.data.cassandra"), if your configuration starts with cassandrain cassandra.ymlfile then use @ConfigurationProperties("cassandra")

您可能需要定制@ConfigurationProperties("spring.data.cassandra"),如果你的配置开头cassandracassandra.yml文件,然后使用@ConfigurationProperties("cassandra")