【问题标题】:Spring Boot application will not connect to the second datasourceSpring Boot 应用程序不会连接到第二个数据源
【发布时间】:2019-12-16 10:41:28
【问题描述】:

我有一个使用 2 个数据源的 Spring Boot 应用程序。它可以很好地连接到第一个。当我尝试使用第二个数据源时,我收到 SQL 错误:表或​​视图不存在,因为它使用第一个数据源作为其连接。

这是我的应用程序属性文件:

#Property for both DBs
spring.datasource.driver.class.name=oracle.jdbc.driver.OracleDriver

## Database Properties DB #1
spring.datasource.tms.url=jdbc:oracle:thin:@ldap:<connection properties have been removed but are present>
spring.datasource.tms.username=own_app
spring.datasource.tms.password=own_app_l1
spring.datasource.tms.jmx.enabled=true

spring.main.allow-bean-definition-overriding=true

## Database Properties DB #2
spring.datasource.lhl.url=jdbc:oracle:thin:@ldap:<connection string has been removed but is correct>
spring.datasource.lhl.username=LHL_PURCH_APP
spring.datasource.lhl.password=ChangemeChangemeChangeme$$2019
spring.datasource.lhl.jmx-enabled=true

这是我的两个数据源的配置文件:

@Configuration
@PropertySource("classpath:application-local.properties")
public class FxgLhlPurchasedItineraryAdapterDataSourceConfiguration {

    @Value("${spring.datasource.driver.class.name}")
    private String driverClassName;

    //TMS properties
    @Value("${spring.datasource.tms.url}")
    private String tmsUrl;

    @Value("${spring.datasource.tms.username}")
    private String tmsUsername;

    @Value("${spring.datasource.tms.password}")
    private String tmsPassword;

    //LHL Properties
    @Value("${spring.datasource.lhl.url}")
    private String lhlUrl;

    @Value("${spring.datasource.lhl.username}")
    private String lhlUsername;

    @Value("${spring.datasource.lhl.password}")
    private String lhlPassword;

    @Primary
    @Bean(name = "tmsDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.tms")
    public DataSource tmsDataSource() {
        DataSourceBuilder factory = DataSourceBuilder.create(this.getClass().getClassLoader())
                .driverClassName(driverClassName).url(tmsUrl)
                .username(tmsUsername)
                .password(tmsPassword);

        return factory.build();
    }

    @Bean(name = "lhlDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.lhl")
    public DataSource lhlDataSource() {
        DataSourceBuilder factory = DataSourceBuilder.create(this.getClass().getClassLoader())
                .driverClassName(driverClassName).url(lhlUrl)
                .username(lhlUsername)
                .password(lhlPassword);

        return factory.build();
    }

    @Bean(name = "tmsJdbcTemplate")
    public JdbcTemplate tmsJdbcTemplate(final DataSource tmsDataSource) {
        return new JdbcTemplate(tmsDataSource);
    }

    @Bean(name = "lhlJdbcTemplate")
    public JdbcTemplate lhlJdbcTemplate(final DataSource lhlDataSource) {
        return new JdbcTemplate(lhlDataSource);
    }

}

如果服务无法运行,我必须添加 @Primary 注释。
当我尝试对不是主数据库的表执行简单的 SELECT 时,我收到该表不存在的错误。 这是调用select语句的代码:

 private JdbcTemplate lhlJdbcTemplate;
    DataSource ds = lhlJdbcTemplate.getDataSource();
    Connection con = ds.getConnection();
    LOGGER.info("Connection info:  {}", con.getSchema());

    lhlParmSqIdModelList = lhlJdbcTemplate.query(
                         selectSequenceNbrSQLStatement,
                        new LhlParmSqIdModelRowMapper());

logger 语句返回主数据库的架构。 如何获得连接以使用第二个数据库

【问题讨论】:

  • 默认情况下,应用程序将只连接一个数据库。您必须手动配置才能拥有多个数据库连接。
  • 你能在声明 lhlJdbcTemplate 的地方添加代码吗?在 lhlJdbcTemplate.query 中使用?
  • 添加了 jdbcTemplate 的声明。只是private JdbcTemplate lhlJdbcTemplate;

标签: java spring-boot jdbctemplate


【解决方案1】:

因为你有多个 DataSource bean,通常 Spring 会失败,因为它不知道如何自动决定它应该使用多个等效 bean 中的哪一个,它把这个责任交给了你作为程序员。

通过添加@Primary 注释,您是在告诉Spring“如果有多个这种类型的候选bean,请使用这个。”

您的 bean 方法并没有向 Spring 请求特定的 DataSource,它们只需要 任何 数据源,因此 Spring 为每个方法都提供了标有 @Primary 的数据源。

相反,您需要使用 @Qualifier 来准确指出他们想要的名称为 DataSource

@Bean(name = "tmsJdbcTemplate")
public JdbcTemplate tmsJdbcTemplate(@Qualifier("tmsDataSource") final DataSource tmsDataSource) {
    return new JdbcTemplate(tmsDataSource);
}

@Bean(name = "lhlJdbcTemplate")
public JdbcTemplate lhlJdbcTemplate(@Qualifier("lhlDataSource") final DataSource lhlDataSource) {
    return new JdbcTemplate(lhlDataSource);
}

我不保证这个语法是完全正确的,但是类似的。

您还需要限定 JdbcTemplate 注入点。 (感谢 cmets 中的Sherif Behna

【讨论】:

  • 在需要它的类中注入 JdbcTemplate 时,您还需要使用@Qualifier。
  • 没错,正在输入相同的答案。应使用限定符来区分 JDBCTemplate 应使用哪个 DS。否则,它默认为 Primary。
  • 太棒了!那行得通!还使用了指向显示如何限定 JDBCTemplate 的副本的链接。非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-10-26
  • 2019-01-12
  • 2015-05-31
  • 1970-01-01
  • 2022-08-18
  • 2023-01-15
  • 2017-08-24
相关资源
最近更新 更多