簡體   English   中英

如何使用 Spring Boot 初始化 Cassandra 鍵空間和表

[英]How to initialize Cassandra keyspace and tables with Spring boot

我在 Spring boot 應用程序中使用 Cassandra 作為數據源,並希望在應用程序啟動之前初始化數據庫。

到目前為止,我所做的是,我定義了一個擴展“AbstractCassandraConfiguration”類的“CassandraConfiguration”類,如下例所示,我有一個擴展“CassandraRepository”的存儲庫。 當我自己創建鍵空間和表時,應用程序工作正常。

但是,我想在應用程序啟動時自動創建鍵空間和表。 為了做到這一點,我在資源文件夾下提供了一個 schema.cql 文件,但我無法使該腳本工作。

有誰知道我可以做什么來自動創建鍵空間和表?

謝謝。

編輯:我使用的是 Cassandra 2.0.9、spring-boot 1.3.2.RELEASE 和 datastax cassandra 驅動程序 2.1.6 版本。

CassandraConfiguration.java

@Configuration
@PropertySource(value = { "classpath:cassandra.properties" })
@EnableCassandraRepositories(basePackages = { "bla.bla.bla.repository" })
public class CassandraConfiguration extends AbstractCassandraConfiguration {

    @Autowired
    private Environment environment;


    @Bean
    public CassandraClusterFactoryBean cluster() {
        CassandraClusterFactoryBean cluster = new CassandraClusterFactoryBean();
        cluster.setContactPoints( environment.getProperty( "cassandra.contactpoints" ) );
        cluster.setPort( Integer.parseInt( environment.getProperty( "cassandra.port" ) ) );
        return cluster;
    }


    @Bean
    public CassandraMappingContext cassandraMapping() throws ClassNotFoundException {
        return new BasicCassandraMappingContext();
    }


    @Bean
    public CassandraConverter converter() throws ClassNotFoundException {
        return new MappingCassandraConverter(cassandraMapping());
    }


    @Override
    protected String getKeyspaceName() {
        return environment.getProperty( "cassandra.keyspace" );
    }


    @Bean
    public CassandraSessionFactoryBean session() throws Exception {

        CassandraSessionFactoryBean session = new CassandraSessionFactoryBean();
        session.setCluster(cluster().getObject());
        session.setKeyspaceName(environment.getProperty("cassandra.keyspace"));
        session.setConverter(converter());
        session.setSchemaAction(SchemaAction.NONE);

        return session;
    }


    @Override
    public SchemaAction getSchemaAction() {
        return SchemaAction.RECREATE_DROP_UNUSED;
    }
}

如果您仍然遇到此問題,在Spring Boot 2和SD Cassandra 2.0.3中,您可以直接進行Java配置並開箱即用。

@Configuration
@EnableCassandraRepositories(basePackages = "com.example.repository")
public class DbConfigAutoStart extends AbstractCassandraConfiguration {

    /*
     * Provide a contact point to the configuration.
     */
    @Override
    public String getContactPoints() {
        return "exampleContactPointsUrl";
    }

    /*
     * Provide a keyspace name to the configuration.
     */
    @Override
    public String getKeyspaceName() {
        return "exampleKeyspace";
    }

    /*
     * Automatically creates a Keyspace if it doesn't exist
     */
    @Override
    protected List<CreateKeyspaceSpecification> getKeyspaceCreations() {
        CreateKeyspaceSpecification specification = CreateKeyspaceSpecification
                .createKeyspace("exampleKeyspace").ifNotExists()
                .with(KeyspaceOption.DURABLE_WRITES, true).withSimpleReplication();
        return Arrays.asList(specification);
    }


    /*
     * Automatically configure a table if doesn't exist
     */
    @Override
    public SchemaAction getSchemaAction() {
        return SchemaAction.CREATE_IF_NOT_EXISTS;
    }


    /*
     * Get the entity package (where the entity class has the @Table annotation)
     */
    @Override
    public String[] getEntityBasePackages() {
        return new String[] { "com.example.entity" };
    }

你很高興

您的返回類型BasicCassandraMappingContext()可能已被棄用。 使用

@Bean
public CassandraMappingContext mappingContext() throws ClassNotFoundException {
    CassandraMappingContext mappingContext= new CassandraMappingContext();
    mappingContext.setInitialEntitySet(getInitialEntitySet());
    return mappingContext;
}
@Override
public String[] getEntityBasePackages() {
    return new String[]{"base-package name of all your entity, annotated 
with @Table"};
}

@Override
protected Set<Class<?>> getInitialEntitySet() throws ClassNotFoundException {
    return CassandraEntityClassScanner.scan(getEntityBasePackages());
}

代替,

@Bean
public CassandraMappingContext cassandraMapping() throws ClassNotFoundException {
    return new BasicCassandraMappingContext();
}

還設置:

session.setSchemaAction(SchemaAction.RECREATE_DROP_UNUSED);

並排除:

@Override
public SchemaAction getSchemaAction() {
    return SchemaAction.RECREATE_DROP_UNUSED;
}

在這里得到參考。

我正在使用spring-boot 1.5.10.RELEASEcassandra 3.0.16但你可以嘗試縮減版本。 要創建鍵空間,可以從application.ymlapplication.properties導入keyspacename。 如果已設置實體基礎包,則應使用@Table注釋自動生成表。

@Value("${cassandra.keyspace}")
private String keySpace;

@Override
public String[] getEntityBasePackages() {
    return new String[]{"com.example.your.entities"};
}

@Override
protected List<CreateKeyspaceSpecification> getKeyspaceCreations() {
    return Arrays.asList(
            CreateKeyspaceSpecification.createKeyspace()
                    .name(keySpace)
                    .ifNotExists()
    );
}

最后,我通過將setKeyspaceCreations(getKeyspaceCreations())添加到CassandraClusterFactoryBean Override並確保啟用@ComponentScan來實現它。

import com.datastax.driver.core.PlainTextAuthProvider;
import com.datastax.driver.core.policies.ConstantReconnectionPolicy;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.cassandra.config.*;
import org.springframework.data.cassandra.core.cql.keyspace.CreateKeyspaceSpecification;
import org.springframework.data.cassandra.core.cql.keyspace.DropKeyspaceSpecification;
import org.springframework.data.cassandra.core.cql.keyspace.KeyspaceOption;
import org.springframework.data.cassandra.repository.config.EnableReactiveCassandraRepositories;

import java.util.Arrays;
import java.util.List;



@Configuration
@EnableReactiveCassandraRepositories(basePackages = "com.company.domain.data")
public class CassandraConfig extends AbstractReactiveCassandraConfiguration{
@Value("${spring.data.cassandra.contactpoints}") private String contactPoints;
@Value("${spring.data.cassandra.port}") private int port;
@Value("${spring.data.cassandra.keyspace-name}") private String keyspace;

@Value("${spring.data.cassandra.username}") private String userName;
@Value("${spring.data.cassandra.password}") private String password;
@Value("${cassandra.basepackages}") private String basePackages;


@Override protected String getKeyspaceName() {
    return keyspace;
}
@Override protected String getContactPoints() {
    return contactPoints;
}
@Override protected int getPort() {
    return port;
}
@Override public SchemaAction getSchemaAction() {
    return SchemaAction.CREATE_IF_NOT_EXISTS;
}
@Override
public String[] getEntityBasePackages() {
    return new String[]{"com.company.domain.data"};
}

@Override
public CassandraClusterFactoryBean cluster() {
    PlainTextAuthProvider authProvider = new PlainTextAuthProvider(userName, password);

    CassandraClusterFactoryBean cluster=new CassandraClusterFactoryBean();

    cluster.setJmxReportingEnabled(false);
    cluster.setContactPoints(contactPoints);
    cluster.setPort(port);
    cluster.setAuthProvider(authProvider);
    cluster.setKeyspaceCreations(getKeyspaceCreations());
    cluster.setReconnectionPolicy(new ConstantReconnectionPolicy(1000));

    return cluster;
}


@Override
protected List<CreateKeyspaceSpecification> getKeyspaceCreations() {

    CreateKeyspaceSpecification specification = CreateKeyspaceSpecification.createKeyspace(keyspace)
            .ifNotExists()
            .with(KeyspaceOption.DURABLE_WRITES, true);

    return Arrays.asList(specification);
}



@Override
protected List<DropKeyspaceSpecification> getKeyspaceDrops() {
    return Arrays.asList(DropKeyspaceSpecification.dropKeyspace(keyspace));
}



}

之前的答案基於spring-data-cassandra AbstractCassandraConfiguration 如果您使用spring-boot那么它可以為您自動配置 Cassandra 並且無需擴展AbstractCassandraConfiguration 但是,即使在這種情況下,您也需要做一些工作來自動創建鍵空間。 我已經決定將自動配置添加到我們公司的 spring-boot 啟動器中,但您也可以將其定義為應用程序中的常規配置。

/**
 * create the configured keyspace before the first cqlSession is instantiated. This is guaranteed by running this
 * autoconfiguration before the spring-boot one.
 */
@ConditionalOnClass(CqlSession.class)
@ConditionalOnProperty(name = "spring.data.cassandra.create-keyspace", havingValue = "true")
@AutoConfigureBefore(CassandraAutoConfiguration.class)
public class CassandraCreateKeyspaceAutoConfiguration {

    private static final Logger logger = LoggerFactory.getLogger(CassandraCreateKeyspaceAutoConfiguration.class);

    public CassandraCreateKeyspaceAutoConfiguration(CqlSessionBuilder cqlSessionBuilder, CassandraProperties properties) {
        // It's OK to mutate cqlSessionBuilder because it has prototype scope.
        try (CqlSession session = cqlSessionBuilder.withKeyspace((CqlIdentifier) null).build()) {
            logger.info("Creating keyspace {} ...", properties.getKeyspaceName());
            session.execute(CreateKeyspaceCqlGenerator.toCql(
                    CreateKeyspaceSpecification.createKeyspace(properties.getKeyspaceName()).ifNotExists()));
        }
    }
}

就我而言,我還添加了一個配置屬性來控制創建, spring.data.cassandra.create-keyspace ,如果您不需要靈活性,可以將其省略。

請注意, spring-boot自動配置取決於某些配置屬性,這是我在開發環境中的配置:

spring:
  data:
    cassandra:
      keyspace-name: mykeyspace
      contact-points: 127.0.0.1
      port: 9042
      local-datacenter: datacenter1
      schema-action: CREATE_IF_NOT_EXISTS
      create-keyspace: true

更多細節: spring-boot 和 Cassandra

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM