You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot 2.7.x中Spring Data Cassandra双会话管理问题求助

多Cassandra连接的Bean冲突问题及解决方案

技术栈

  • 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 06:24:51