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

启动时LiquibaseProperties多Bean冲突,如何指定目标Bean?

问题

启动应用时出现如下错误:

***************************
APPLICATION FAILED TO START
***************************

Description:

Parameter 3 of method liquibase in org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration$LiquibaseConfiguration required a single bean, but 2 were found:
    - liquibaseConnectionDetailsForKeycloak_db: defined in unknown location
    - liquibaseConnectionDetailsForServer_db: defined in unknown location

查看自动配置类,相关方法为:

@Bean
public SpringLiquibase liquibase(ObjectProvider<DataSource> dataSource,
                @LiquibaseDataSource ObjectProvider<DataSource> liquibaseDataSource, LiquibaseProperties properties,
                LiquibaseConnectionDetails connectionDetails) {...}

经确认冲突Bean类型为LiquibaseProperties,原因是用Docker Compose启动应用时同时启动了Keycloak及其数据库,导致自动配置检测到两个数据源,希望Liquibase仅连接应用自身的数据源(非Keycloak的)。

application.properties配置:

spring.datasource.url=${SERVER_DB_URL}/${SERVER_DB}
spring.datasource.username=${SERVER_DB_USER}
spring.datasource.password=${SERVER_DB_PASSWORD}
spring.datasource.driver-class-name=org.postgresql.Driver

spring.liquibase.url=${SERVER_DB_URL}/${SERVER_DB}
spring.liquibase.user=${SERVER_DB_USER}
spring.liquibase.password=${SERVER_DB_PASSWORD}
spring.liquibase.change-log=classpath:db/changelogs/changelog-master.xml

Keycloak数据库URL为jdbc:postgresql://localhost:5433,与应用数据源不同。

Docker Compose配置:

services:

  keycloak_db:
    image: postgres
    container_name: keycloak_db
    restart: always
    ports:
      - "${KEYCLOAK_DB_PORT}:5432"
    environment:
      POSTGRES_DB: ${KEYCLOAK_DB}
      POSTGRES_USER: ${KEYCLOAK_DB_USER}
      POSTGRES_PASSWORD: ${KEYCLOAK_DB_PASSWORD}
    volumes:
      - keycloak-db-volume:/var/lib/postgresql/data

  keycloak:
    image: keycloak/keycloak
    container_name: keycloak
    restart: always
    command:
      - start-dev
    ports:
      - "${KEYCLOAK_PORT}:8080"
    environment:
      KEYCLOAK_ADMIN: ${KEYCLOAK_ADMIN}
      KEYCLOAK_ADMIN_PASSWORD: ${KEYCLOAK_ADMIN_PASSWORD}
      KC_DB: postgres
      KC_DB_URL: jdbc:postgresql://keycloak_db/${KEYCLOAK_DB}
      KC_DB_USERNAME: ${KEYCLOAK_DB_USER}
      KC_DB_PASSWORD: ${KEYCLOAK_DB_PASSWORD}
    depends_on:
        - keycloak_db
    volumes:
      - keycloak-volume:/opt/keycloak/data/import/

  postgres:
    image: postgres
    container_name: server_db
    restart: always
    ports:
      - "${SERVER_DB_PORT}:5432"
    environment:
      POSTGRES_DB: ${SERVER_DB}
      POSTGRES_USER: ${SERVER_DB_USER}
      POSTGRES_PASSWORD: ${SERVER_DB_PASSWORD}
    depends_on:
      - keycloak
    volumes:
      - server_db_volume:/var/lib/postgresql/data

已尝试@Primary注解但无效,冲突Bean定义位置显示未知,需要指定Liquibase使用的目标Bean,优先实现忽略Keycloak数据源,同时了解后续支持多数据源的方案。


解决方案

一、优先忽略Keycloak数据源(快速解决当前问题)

1. 手动配置Liquibase Bean,排除默认自动配置

在Spring Boot启动类上排除默认的Liquibase自动配置,避免自动检测多数据源:

@SpringBootApplication(exclude = {LiquibaseAutoConfiguration.class})
public class YourApplication {
    public static void main(String[] args) {
        SpringApplication.run(YourApplication.class, args);
    }
}

然后创建自定义配置类,明确指定Liquibase使用应用的数据源:

@Configuration
public class CustomLiquibaseConfig {

    @Autowired
    @Qualifier("dataSource") // 绑定默认的应用数据源Bean
    private DataSource appDataSource;

    @Value("${spring.liquibase.change-log}")
    private String changeLogPath;

    @Bean
    public SpringLiquibase liquibase() {
        SpringLiquibase liquibase = new SpringLiquibase();
        liquibase.setDataSource(appDataSource);
        liquibase.setChangeLog(changeLogPath);
        return liquibase;
    }
}

2. 通过配置指定Liquibase绑定的数据源

在application.properties中添加配置,强制Liquibase使用指定的数据源Bean:

# 指定Liquibase使用的数据源Bean名称(默认是dataSource)
spring.liquibase.data-source=dataSource

如果应用的数据源Bean有自定义名称,替换为对应名称即可。

3. 禁用Keycloak数据源的自动配置

如果Keycloak的数据源是Spring自动加载的,可在启动类中排除默认的数据源自动配置,再手动注册应用的数据源:

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class YourApplication {
    public static void main(String[] args) {
        SpringApplication.run(YourApplication.class, args);
    }
}

手动配置应用数据源:

@Configuration
public class AppDataSourceConfig {
    @Bean("dataSource")
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource appDataSource() {
        return DataSourceBuilder.create().build();
    }
}

二、多数据源场景下的Liquibase配置方案

若后续需要为多个数据源分别配置Liquibase,可按以下方式实现:

1. 配置多数据源及对应Liquibase参数

在application.properties中添加多数据源和各自的Liquibase配置:

# 应用主数据源
spring.datasource.url=${SERVER_DB_URL}/${SERVER_DB}
spring.datasource.username=${SERVER_DB_USER}
spring.datasource.password=${SERVER_DB_PASSWORD}
spring.datasource.driver-class-name=org.postgresql.Driver

# Keycloak数据源
spring.keycloak-datasource.url=${KEYCLOAK_DB_URL}/${KEYCLOAK_DB}
spring.keycloak-datasource.username=${KEYCLOAK_DB_USER}
spring.keycloak-datasource.password=${KEYCLOAK_DB_PASSWORD}
spring.keycloak-datasource.driver-class-name=org.postgresql.Driver

# 应用主数据源的Liquibase配置
spring.liquibase.app.change-log=classpath:db/changelogs/changelog-master.xml

# Keycloak数据源的Liquibase配置
spring.liquibase.keycloak.change-log=classpath:db/changelogs/keycloak-changelog.xml

2. 手动注册多数据源及对应Liquibase Bean

创建配置类,分别为每个数据源注册Bean,并绑定对应的Liquibase:

@Configuration
public class MultiLiquibaseConfig {

    // 注册应用主数据源
    @Bean("appDataSource")
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource appDataSource() {
        return DataSourceBuilder.create().build();
    }

    // 注册Keycloak数据源
    @Bean("keycloakDataSource")
    @ConfigurationProperties(prefix = "spring.keycloak-datasource")
    public DataSource keycloakDataSource() {
        return DataSourceBuilder.create().build();
    }

    // 应用主数据源的Liquibase
    @Bean("appLiquibase")
    public SpringLiquibase appLiquibase(@Qualifier("appDataSource") DataSource dataSource,
                                        @Value("${spring.liquibase.app.change-log}") String changeLog) {
        SpringLiquibase liquibase = new SpringLiquibase();
        liquibase.setDataSource(dataSource);
        liquibase.setChangeLog(changeLog);
        return liquibase;
    }

    // Keycloak数据源的Liquibase
    @Bean("keycloakLiquibase")
    public SpringLiquibase keycloakLiquibase(@Qualifier("keycloakDataSource") DataSource dataSource,
                                             @Value("${spring.liquibase.keycloak.change-log}") String changeLog) {
        SpringLiquibase liquibase = new SpringLiquibase();
        liquibase.setDataSource(dataSource);
        liquibase.setChangeLog(changeLog);
        return liquibase;
    }
}

3. 排除默认Liquibase自动配置

在启动类中排除默认的LiquibaseAutoConfiguration,避免自动配置冲突:

@SpringBootApplication(exclude = {LiquibaseAutoConfiguration.class})
public class YourApplication {
    public static void main(String[] args) {
        SpringApplication.run(YourApplication.class, args);
    }
}

内容的提问来源于stack exchange,提问作者Fran Pedreira

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 23:13:16