Создайте пространство ключей, таблицу и динамически создавайте таблицы с помощью Spring Data Cassandra
используя Cassandra, я хочу динамически создавать пространство ключей и таблицы с помощью приложения Spring Boot. Я использую конфигурацию на основе Java.
У меня есть сущность, аннотированная @Table, схему которой я хочу создать до запуска приложения, поскольку она имеет фиксированные поля, которые известны заранее.
однако в зависимости от зарегистрированного пользователя я также хочу создать дополнительные таблицы для этих пользователей динамически и иметь возможность вставлять записи в эти таблицы.
может кто-нибудь направить меня к некоторым ресурсам, которые я могу использовать или указать мне в правильном направлении, как решить эти проблемы. Большое спасибо за помощь!
5 ответов
проще всего было бы добавить Данные Стартера Spring Boot Cassandra зависимость в Весна Загрузки приложение, например...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-cassandra</artifactId>
<version>1.3.5.RELEASE</version>
</dependency>
кроме того, это добавит Весна Данных Cassandra зависимость к вашему заявлению.
С Весна Данных Cassandra, вы можете настроить Keyspace(Ы) вашего приложения с помощью CassandraClusterFactoryBean
(точнее, производный класс... CassandraCqlClusterFactoryBean
) путем вызова setKeyspaceCreations (: Set) метод.
на KeyspaceActionSpecification класс довольно понятен. Вы даже можете создать один с KeyspaceActionSpecificationFactorybean добавьте Set
а затем передайте это setKeyspaceCreations(..)
метод CassandraClusterFactoryBean
.
для создания таблиц приложения вам по существу просто нужно аннотировать объект(ы) домена приложения) (сущности) использование SD Cassandra @Table аннотация и убедитесь, что ваши объекты/сущности домена можно найти на пути к классам приложения.
в частности, вы можете иметь ваши приложения @Configuration
класс расширения SD Cassandra AbstractClusterConfiguration класса. Там вы найдете getEntityBasePackages():строка[] метод, который можно переопределить для предоставления расположения пакетов, содержащих домен приложения классы объектов / сущностей, которые SD Cassandra затем будет использовать для сканирование на @Table
домен объект/объекты.
С приложением @Table
объект/объекты домена правильно идентифицированы, вы устанавливаете SD Cassandra SchemaAction to CREATE
С помощью CassandraSessionFactoryBean
метод setSchemaAction (: SchemaAction). Это создаст таблицы в вашем пространстве ключей для всех объектов/сущностей домена, найденных во время сканирования, предоставив вам выявлен правильное пространство ключей на вашем CassandraSessionFactoryBean
надлежащим образом.
очевидно, что если ваше приложение создает / использует несколько Keyspaces, вам нужно будет создать отдельный CassandraSessionFactoryBean
для каждого ключа, с entityBasePackages
свойства конфигурации соответствующее значение для лиц, принадлежащих к определенной скорости, так что связанные таблицы создаются в скорости.
сейчас...
для "дополнительных" таблиц на одного пользователя это довольно сложно и хитрый.
вы можете использовать профили Spring здесь, однако профили обычно применяются только при запуске. Если другой пользователь входит в уже запущенное приложение, вам нужен способ предоставить дополнительные @Configuration
занятия к весне ApplicationContext
во время выполнения.
код Весна Загрузки приложение может ввести ссылку на AnnotationConfigApplicationContext
, а затем использовать его в событии входа в систему программно зарегистрироваться дополнительные @Configuration
классы, основанные на пользователе, который вошел в приложение. Вы должны следовать за своим register(Class...)
вызов(ы) с ApplicationContext.refresh()
.
вам также необходимо соответствующим образом обрабатывать ситуацию, когда таблицы уже существуют.
в настоящее время это не поддерживается в SD Cassandra, но см. DATACASS-219 для получения дополнительной информации.
технически было бы намного проще создать все возможные таблицы, необходимые приложению для всех пользователей во время выполнения и используйте параметры безопасности Cassandra для ограничения доступа отдельных пользователей по ролям и назначенным разрешениям.
другой вариант может быть просто создать временные Keyspaces и / или таблицы по мере необходимости, когда пользователь входит в приложение, отбросьте их, когда пользователь выходит из системы.
ясно, что здесь есть много разных вариантов, и это сводится больше к архитектурным решениям, компромиссам и соображениям, а затем делает техническую осуществимость, поэтому осторожный.
надеюсь, что это помогает.
Ура!
следующий класс конфигурации 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;
}
}
следующее Кассандра конфигурации создаст пространство ключей, когда оно не существует, а также запустит сценарий запуска, указанный
@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;");
}
}
этот ответ вдохновлен ответом Вишваната.
мой 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")
используя @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)));
}
для определения ваших varaibles используйте pplication.properties
или :
cassandra:
keyspace: yout_keyspace_name
используя файлы конфигурации вместо жестко закодированных строк, вы можете опубликовать свой код, например, на GitHub, не публикуя свои пароли и entrypoints (.gitignore
файлы), которые могут представлять угрозу безопасности.