Spring Boot 2.7.x中Spring Data Cassandra双会话管理问题求助
技术栈
- Spring Boot 2.7.x
- spring-boot-starter-data-cassandra 2.7.x
- Spring Batch 5.x
- Java 11
现有配置
两个Cassandra仓库配置类
第一个集群配置:
@Configuration @EnableCassandraRepositories( basePackages = {"com.package1"}, cassandraTemplateRef = "cassandraTemplate1", repositoryFactoryBeanClass = CassandraRepositoryWithTtlFactoryBean.class ) public class CassandraConfigurationCluster1 extends CassandraConfiguration { // 省略其他配置 }
第二个集群配置:
@Configuration @EnableCassandraRepositories( basePackages = {"com.package2"}, cassandraTemplateRef = "cassandraTemplate2", repositoryFactoryBeanClass = CassandraRepositoryWithTtlFactoryBean.class ) public class CassandraConfigurationCluster2 extends CassandraConfiguration { // 省略其他配置 }
两个CassandraAdminTemplate Bean配置
第一个集群的Session和Template:
@Bean("session1") public CqlSessionFactoryBean session() { return new CqlSessionFactoryBean(); } @Bean("cassandraTemplate1") public CassandraAdminOperations cassandraTemplate( @Qualifier("session1") final CqlSessionFactoryBean session) { return new CassandraAdminTemplate(session.getObject(), cassandraConverter()); }
第二个集群的Session和Template:
@Bean("session2") public CqlSessionFactoryBean session() { return new CqlSessionFactoryBean(); } @Bean("cassandraTemplate2") public CassandraAdminOperations cassandraTemplate( @Qualifier("session2") final CqlSessionFactoryBean session) { return new CassandraAdminTemplate(session.getObject(), cassandraConverter()); }
报错信息
Unsatisfied dependency expressed through field 'cassandraTemplate'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'cassandraTemplate' defined in class path resource [/config/CassandraConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.data.cassandra.core.CassandraAdminTemplate]: Factory method 'cassandraTemplate' threw exception; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'cassandraSessionFactory' defined in class path resource [/config/CassandraConfiguration.class]: Unsatisfied dependency expressed through method 'cassandraSessionFactory' parameter 0; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.datastax.oss.driver.api.core.CqlSession' available: expected single matching bean but found 3: session1,session2
解决方案
问题根源是CassandraConfiguration会自动创建默认的cassandraSessionFactory和cassandraTemplate Bean,加上自定义的两个实例后,Spring无法确定注入哪个CqlSession。需要禁用自动配置的默认Bean,同时为每个集群独立配置专属的Session、Converter和Template,避免冲突。
步骤1:修改配置类,独立配置每个集群
每个集群的配置类需要覆盖cassandraSessionFactory方法,指定唯一的Session Bean,同时自定义专属的CassandraConverter,避免共用默认实例导致冲突。
第一个集群完整配置示例:
@Configuration @EnableCassandraRepositories( basePackages = {"com.package1"}, cassandraTemplateRef = "cassandraTemplate1", repositoryFactoryBeanClass = CassandraRepositoryWithTtlFactoryBean.class ) public class CassandraConfigurationCluster1 extends CassandraConfiguration { @Override protected String getKeyspaceName() { return "keyspace1"; } @Override protected String getContactPoints() { return "cluster1-host"; } @Bean("session1") public CqlSessionFactoryBean session() { CqlSessionFactoryBean session = new CqlSessionFactoryBean(); session.setKeyspaceName(getKeyspaceName()); session.setContactPoints(getContactPoints()); // 补充其他连接配置,比如端口、认证信息等 return session; } @Bean("cassandraConverter1") public CassandraConverter cassandraConverter() { return new MappingCassandraConverter(cassandraMappingContext()); } @Override @Bean("cassandraSessionFactory1") public SessionFactory cassandraSessionFactory(@Qualifier("session1") CqlSession session) { return DefaultSessionFactory.of(session); } @Bean("cassandraTemplate1") public CassandraAdminOperations cassandraTemplate( @Qualifier("cassandraSessionFactory1") SessionFactory sessionFactory, @Qualifier("cassandraConverter1") CassandraConverter converter) { return new CassandraAdminTemplate(sessionFactory, converter); } }
第二个集群完整配置示例:
@Configuration @EnableCassandraRepositories( basePackages = {"com.package2"}, cassandraTemplateRef = "cassandraTemplate2", repositoryFactoryBeanClass = CassandraRepositoryWithTtlFactoryBean.class ) public class CassandraConfigurationCluster2 extends CassandraConfiguration { @Override protected String getKeyspaceName() { return "keyspace2"; } @Override protected String getContactPoints() { return "cluster2-host"; } @Bean("session2") public CqlSessionFactoryBean session() { CqlSessionFactoryBean session = new CqlSessionFactoryBean(); session.setKeyspaceName(getKeyspaceName()); session.setContactPoints(getContactPoints()); // 补充其他连接配置 return session; } @Bean("cassandraConverter2") public CassandraConverter cassandraConverter() { return new MappingCassandraConverter(cassandraMappingContext()); } @Override @Bean("cassandraSessionFactory2") public SessionFactory cassandraSessionFactory(@Qualifier("session2") CqlSession session) { return DefaultSessionFactory.of(session); } @Bean("cassandraTemplate2") public CassandraAdminOperations cassandraTemplate( @Qualifier("cassandraSessionFactory2") SessionFactory sessionFactory, @Qualifier("cassandraConverter2") CassandraConverter converter) { return new CassandraAdminTemplate(sessionFactory, converter); } }
步骤2:排除Spring Boot自动配置的Cassandra类(可选)
如果自动配置仍有干扰,可在启动类添加注解禁用默认Cassandra配置:
@SpringBootApplication(exclude = CassandraDataAutoConfiguration.class) public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
关键说明
- 每个集群的Session、SessionFactory、Converter、Template都使用唯一Bean名称,避免冲突。
- 覆盖
CassandraConfiguration的cassandraSessionFactory方法,绑定当前集群的Session,防止父类创建默认实例导致依赖混淆。 - 为每个集群创建独立的
CassandraConverter,避免不同集群的实体映射互相干扰。
内容的提问来源于stack exchange,提问作者Govind Kalyankar

