[英]Multiple keyspace support for spring-data-cassandra repositories?
Spring Data Cassandra 是否支持同一應用程序上下文中的多個鍵空間存儲庫? 我正在使用以下 JavaConfig 類設置 cassandra spring 數據配置
@Configuration
@EnableCassandraRepositories(basePackages = "com.blah.repository")
public class CassandraConfig extends AbstractCassandraConfiguration {
@Override
public String getKeyspaceName() {
return "keyspace1";
}
在將存儲庫類移動到不同的包后,我嘗試創建第二個配置類。
@Configuration
@EnableCassandraRepositories(basePackages = "com.blah.secondrepository")
public class SecondCassandraConfig extends AbstractCassandraConfiguration {
@Override
public String getKeyspaceName() {
return "keyspace2";
}
但是,在這種情況下,如果存儲庫失敗,則第一組設置失敗,因為在鍵空間中找不到實體的配置列族。 我認為它可能正在尋找第二個鍵空間中的列族。
spring-data-cassandra 是否支持多個鍵空間存儲庫? 我找到多個鍵空間引用的唯一地方是這里。 但它沒有解釋這是否可以通過存儲庫完成?
工作應用程序示例: 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相同,只是使用不同的包包com.sample.repo.test2;
5)將每個keyspace的repo放在專用包中,即
package com.sample.repo.test1;
@Repository
public interface RepositoryForTest1 extends CassandraRepository<MyEntity> {
// ....
}
package com.sample.repo.test2;
@Repository
public interface RepositoryForTest2 extends CassandraRepository<MyEntity> {
// ....
}
嘗試為每個鍵空間顯式命名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());
}
我認為這可能會奏效。 如果沒有請回帖。
似乎建議在由一個會話管理的查詢中使用完全限定的鍵空間名稱,因為會話不是很輕量級。
請在此處查看參考
我試過這種方法。 但是,我在嘗試訪問列族 2 時遇到了異常。對列族 1 的操作似乎沒問題。
我猜是因為底層的 CassandraSessionFactoryBean bean 是一個單例。 這會導致未配置的 columnfamily columnfamily2
這里還有一些日志可以提供上下文
DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - 返回單例 bean 'entityManagerFactory' 的緩存實例 DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - 返回單例 bean 'session' 的緩存實例 DEBUG org.springframework.beans .factory.support.DefaultListableBeanFactory - 返回單例 bean 'cluster' 的緩存實例
org.springframework.cassandra.support.exception.CassandraInvalidQueryException:未配置的列族分片組; 嵌套的異常是 com.datastax.driver.core.exceptions.InvalidQueryException: unconfigured columnfamily columnfamily2 at org.springframework.cassandra.support.CassandraExceptionTranslator.translateExceptionIfPossible(CassandraExceptionTranslator.java:116) at org.springframework.cassandra.config.CassandraCql SessionFactoryBeansIf( CassandraCqlSessionFactoryBean.java:74)
唔。 無法評論 matthew-adams 的答案。 但這將重用會話對象,因為 AbstractCassandraConfiguration 在所有相關的 getter 上都用 @Bean 注釋。
在類似的設置中,我最初讓它覆蓋所有的 getter 並專門為它們提供不同的 bean 名稱。 但是由於 Spring 仍然聲稱需要帶有名稱的 bean。 我現在不得不制作一個 AbstractCassandraConfiguration 的副本,沒有可以繼承的注釋。
確保公開 CassandraTemplate,以便在使用時可以從 @EnableCassandraRepositories 中引用它。
我還有一個單獨的 AbstractClusterConfiguration 實現來公開一個通用的 CassandraCqlClusterFactoryBean,以便重用底層連接。
編輯:我猜根據 bclarance 鏈接的電子郵件線程,應該真正嘗試重用 Session 對象。 似乎 Spring Data Cassandra 並沒有真正為此設置的方式
就我而言,我有一個 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);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.