10

Does Spring Data Cassandra support multiple keyspace repositories in the same application context? I am setting up the cassandra spring data configuration using the following JavaConfig class

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

@Override
public String getKeyspaceName() {
    return "keyspace1";
}

I tried creating a second configuration class after moving the repository classes to a different package.

@Configuration
@EnableCassandraRepositories(basePackages = "com.blah.secondrepository")
public class SecondCassandraConfig extends AbstractCassandraConfiguration {

@Override
public String getKeyspaceName() {
    return "keyspace2";
}

However in that case the first set if repositories fail as the configured column family for the entities is not found in the keyspace. I think it is probably looking for the column family in the second keyspace.

Does spring-data-cassandra support multiple keyspace repositories? The only place where I found a reference for multiple keyspaces was here. But it does not explain if this can be done with repositories?

4

6 回答 6

5

工作应用程序示例:http: //valchkou.com/spring-boot-cassandra.html#multikeyspace

您需要覆盖默认 bean 的想法:sessionfactory 和模板

样本:

1)应用程序.yml

 spring:
  data:
    cassandra:
      test1:
        keyspace-name: test1_keyspace
        contact-points: localhost
      test2:
        keyspace-name: test2_keyspace
        contact-points: localhost

2) 基本配置类

public abstract class CassandraBaseConfig extends AbstractCassandraConfiguration{
    protected String contactPoints;
    protected String keyspaceName;

    public String getContactPoints() {
        return contactPoints;
    }
    public void setContactPoints(String contactPoints) {
        this.contactPoints = contactPoints;
    }

    public void setKeyspaceName(String keyspaceName) {
        this.keyspaceName = keyspaceName;
    }
    @Override
    protected String getKeyspaceName() {
        return keyspaceName;
    }
}

3) test1 的配置实现

package com.sample.repo.test1;

@Configuration
@ConfigurationProperties("spring.data.cassandra.test1")
@EnableCassandraRepositories(
        basePackages = "com.sample.repo.test1",
        cassandraTemplateRef = "test1Template"
)
public class Test1Config extends CassandraBaseConfig {

    @Override
    @Primary
    @Bean(name = "test1Template")
    public CassandraAdminOperations cassandraTemplate() throws Exception {
        return new CassandraAdminTemplate(session().getObject(), cassandraConverter());
    }

    @Override
    @Bean(name = "test1Session")
    public CassandraSessionFactoryBean session() throws Exception {

        CassandraSessionFactoryBean session = new CassandraSessionFactoryBean();

        session.setCluster(cluster().getObject());
        session.setConverter(cassandraConverter());
        session.setKeyspaceName(getKeyspaceName());
        session.setSchemaAction(getSchemaAction());
        session.setStartupScripts(getStartupScripts());
        session.setShutdownScripts(getShutdownScripts());

        return session;
    }
}

4) test2 相同,只是使用不同的包 package com.sample.repo.test2;

5)将每个键空间的存储库放在专用包中,即

package com.sample.repo.test1;

@Repository
public interface RepositoryForTest1 extends CassandraRepository<MyEntity> {
// ....
}


package com.sample.repo.test2;

@Repository
public interface RepositoryForTest2 extends CassandraRepository<MyEntity> {
// ....
}
于 2016-07-15T23:15:25.137 回答
2

尝试CassandraTemplate为每个键空间显式命名您的 bean,并在@EnableCassandraRepositories注释的cassandraTemplateRef属性中使用这些名称(请参阅与/* CHANGED */更改的行)。

在您的第一个配置中:

@Configuration
@EnableCassandraRepositories(basePackages = "com.blah.repository",
    /* CHANGED */ cassandraTemplateRef = "template1")
public class CassandraConfig extends AbstractCassandraConfiguration {

@Override
public String getKeyspaceName() {
    return "keyspace1";
}

/* CHANGED */
@Override
@Bean(name = "template1")
public CassandraAdminOperations cassandraTemplate() throws Exception {
    return new CassandraAdminTemplate(session().getObject(), cassandraConverter());
}

...在您的第二个配置中:

@Configuration
@EnableCassandraRepositories(basePackages = "com.blah.secondrepository",
    /* CHANGED */ cassandraTemplateRef = "template2")
public class SecondCassandraConfig extends AbstractCassandraConfiguration {

@Override
public String getKeyspaceName() {
    return "keyspace2";
}

/* CHANGED */
@Override
@Bean(name = "template2")
public CassandraAdminOperations cassandraTemplate() throws Exception {
    return new CassandraAdminTemplate(session().getObject(), cassandraConverter());
}

我认为这可能会奏效。如果没有请回帖。

于 2014-09-19T13:50:06.983 回答
0

似乎建议在由一个会话管理的查询中使用完全限定的键空间名称,因为会话不是很轻量级。
在此处查看参考

于 2015-04-04T00:26:17.927 回答
0

我试过这种方法。但是,我在尝试访问列族 2 时遇到了异常。列族 1 上的操作似乎没问题。

我猜是因为底层的 CassandraSessionFactoryBean bean 是一个单例。这会导致未配置的 columnfamily columnfamily2

这里还有一些提供上下文的日志

调试 org.springframework.beans.factory.support.DefaultListableBeanFactory - 返回单例 bean 'entityManagerFactory' 的缓存实例 调试 org.springframework.beans.factory.support.DefaultListableBeanFactory - 返回单例 bean 'session' 的缓存实例 调试 org.springframework.beans .factory.support.DefaultListableBeanFactory - 返回单例 bean 'cluster' 的缓存实例

org.springframework.cassandra.support.exception.CassandraInvalidQueryException:未配置的 columnfamily shardgroup;嵌套异常是 com.datastax.driver.core.exceptions.InvalidQueryException: unconfigured columnfamily columnfamily2 at org.springframework.cassandra.support.CassandraExceptionTranslator.translateExceptionIfPossible(CassandraExceptionTranslator.java:116) at org.springframework.cassandra.config.CassandraCqlSessionFactoryBean.translateExceptionIfPossible( CassandraCqlSessionFactoryBean.java:74)

于 2015-07-12T00:45:23.757 回答
0

唔。无法评论马修亚当斯的答案。但这将重用会话对象,因为 AbstractCassandraConfiguration 在所有相关的 getter 上都用 @Bean 注释。

在一个类似的设置中,我最初让它覆盖所有的 getter,并专门给它们不同的 bean 名称。但是由于 Spring 仍然声称需要带有名称的 bean。我现在必须制作一个 AbstractCassandraConfiguration 的副本,没有可以继承的注释。

确保公开 CassandraTemplate,以便在使用时可以从 @EnableCassandraRepositories 中引用它。

我还有一个 AbstractClusterConfiguration 的单独实现,以公开一个常见的 CassandraCqlClusterFactoryBean,以便重用底层连接。

编辑:我猜根据 bclarance 链接的电子邮件线程,应该真正尝试重用 Session 对象。似乎 Spring Data Cassandra 并没有真正为此设置

于 2015-08-13T13:57:11.627 回答
0

就我而言,我有一个 Spring Boot 应用程序,其中大多数存储库都在一个键空间中,而一秒钟内只有两个。我为第一个键空间保留了默认的 Spring Boot 配置,并使用 Spring Boot 用于其自动配置的相同配置方法手动配置了第二个键空间。

@Repository
@NoRepositoryBean // This uses a different keyspace than the default, so not auto-creating
public interface SecondKeyspaceTableARepository 
        extends MapIdCassandraRepository<SecondKeyspaceTableA> {
}
@Repository
@NoRepositoryBean // This uses a different keyspace than the default, so not auto-creating
public interface SecondKeyspaceTableBRepository
        extends MapIdCassandraRepository<SecondKeyspaceTableB> {
}
@Configuration
public class SecondKeyspaceCassandraConfig {
    public static final String KEYSPACE_NAME = "second_keyspace";

    /**
     * @see org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration#cassandraSession(CassandraConverter)
     */
    @Bean(autowireCandidate = false)
    public CassandraSessionFactoryBean secondKeyspaceCassandraSession(
            Cluster cluster, Environment environment, CassandraConverter converter) {
        CassandraSessionFactoryBean session = new CassandraSessionFactoryBean();
        session.setCluster(cluster);
        session.setConverter(converter);
        session.setKeyspaceName(KEYSPACE_NAME);
        Binder binder = Binder.get(environment);
        binder.bind("spring.data.cassandra.schema-action", SchemaAction.class)
                .ifBound(session::setSchemaAction);
        return session;
    }

    /**
     * @see org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration#cassandraTemplate(com.datastax.driver.core.Session, CassandraConverter)
     */
    @Bean(autowireCandidate = false)
    public CassandraTemplate secondKeyspaceCassandraTemplate(
            Cluster cluster, Environment environment, CassandraConverter converter) {
        return new CassandraTemplate(secondKeyspaceCassandraSession(cluster, environment, converter)
                .getObject(), converter);
    }

    @Bean
    public SecondKeyspaceTableARepository cdwEventRepository(
            Cluster cluster, Environment environment, CassandraConverter converter) {
        return createRepository(CDWEventRepository.class, 
                secondKeyspaceCassandraTemplate(cluster, environment, converter));
    }

    @Bean
    public SecondKeyspaceTableBTypeRepository dailyCapacityRepository(
            Cluster cluster, Environment environment, CassandraConverter converter) {
        return createRepository(DailyCapacityRepository.class,
                secondKeyspaceCassandraTemplate(cluster, environment, converter));
    }

    private <T> T createRepository(Class<T> repositoryInterface, CassandraTemplate operations) {
        return new CassandraRepositoryFactory(operations).getRepository(repositoryInterface);
    }
}
于 2020-08-21T17:29:20.143 回答