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
Create keyspace, table and generate tables dynamically using Spring 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 Set
and 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 @Configuration
class 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 @Table
domain object/entities.
具体来说,您可以让您的应用程序@Configuration
类扩展 SD Cassandra AbstractClusterConfiguration类。在那里,你会发现getEntityBasePackages()的String []的方法,你可以重写提供包含应用程序的域对象/实体类,SD卡珊德拉将使用该包装的位置扫描的@Table
域对象/实体。
With your application @Table
domain object/entities properly identified, you set the SD Cassandra SchemaActionto CREATE
using the CassandraSessionFactoryBean
method, 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 CassandraSessionFactoryBean
appropriately.
@Table
正确识别您的应用程序域对象/实体后,您将 SD Cassandra SchemaAction设置为CREATE
使用CassandraSessionFactoryBean
方法setSchemaAction(:SchemaAction)。这将为扫描期间找到的所有域对象/实体在您的密钥空间中创建表,前提是您适当地确定了正确的密钥空间CassandraSessionFactoryBean
。
Obviously, if your application creates/uses multiple Keyspaces, you will need to create a separate CassandraSessionFactoryBean
for each Keyspace, with the entityBasePackages
configuration 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 @Configuration
classes to the Spring ApplicationContext
at 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 @Configuration
classes 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.properties
or application.yml
file:
要定义您的变量,请使用application.properties
或application.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 (.gitignore
files) 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.yml
looks 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 cassandra
in cassandra.yml
file then use @ConfigurationProperties("cassandra")
您可能需要定制@ConfigurationProperties("spring.data.cassandra")
,如果你的配置开头cassandra
的cassandra.yml
文件,然后使用@ConfigurationProperties("cassandra")