我有一个使用@Table注释的实体,其模式需要在应用程序启动之前创建,因为它具有预先知道的固定字段。
但是,根据登录的用户,我还想为那些用户动态创建其他表,并能够向这些表中插入条目。
请问是否有一些资源可以帮助我解决这些问题,或指导我如何解决这些问题?非常感谢您的帮助!
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-cassandra</artifactId>
<version>1.3.5.RELEASE</version>
</dependency>
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 设置为 CREATE
,setSchemaAction(:SchemaAction)。这将为扫描期间发现的所有领域对象/实体在您的Keyspace中创建表,前提是您已经适当地在CassandraSessionFactoryBean
上 标识了 正确的Keyspace。
显然,如果您的应用程序创建/使用多个Keyspace,则需要为每个Keyspace创建一个单独的CassandraSessionFactoryBean
,并将entityBasePackages
配置属性设置为适合属于特定Keyspace的实体,以便在该Keyspace中创建相关的表。
现在...
对于每个用户的“附加”表,这就变得更加复杂和棘手。
您可能可以在此处利用Spring Profiles,但是,配置文件通常仅在启动时应用。如果不同的用户登录到已运行的应用程序中,您需要一种在运行时向Spring ApplicationContext
提供附加@Configuration
类的方法。
您的Spring Boot应用程序可以注入对AnnotationConfigApplicationContext
的引用,然后在登录事件上使用它,根据登录到应用程序的用户编程式地注册附加的@Configuration
类。在您的register(Class...)
调用之后,需要跟随ApplicationContext.refresh()
。
以下 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;
}
}
@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
使用配置文件而不是硬编码的字符串,您可以在例如GitHub上发布您的代码,而不会公开密码和入口点(.gitignore
文件),这可能会带来安全风险。
@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;");
}
}
您可以在application.properties文件中使用以下内容来创建表格:
spring.data.cassandra.schema-action=CREATE_IF_NOT_EXISTS
这个答案受到了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")