SpringBoot 应用程序。使用 JdbcTemplate 访问 2 个数据源
SpringBoot app. accessing 2 DataSources using JdbcTemplate
我有一个 SpringBoot 应用程序。必须访问不同的数据源才能将数据从 1 导出到另一个(1 个本地数据源和另一个远程数据源)
这就是我的持久化配置的样子
public class PersistenceConfig {
@Bean
public JdbcTemplate localJdbcTemplate() {
return new JdbcTemplate(localDataSource());
}
@Bean
public JdbcTemplate remoteJdbcTemplate() {
return new JdbcTemplate(remoteDataSource());
}
@Bean
public DataSource localDataSource(){
HikariConfig config = new HikariConfig();
config.setMaximumPoolSize(getLocalDbPoolSize());
config.setMinimumIdle(5);
config.setDriverClassName(getLocalDbDriverClassName());
config.setJdbcUrl(getLocalDbJdbcUrl());
config.addDataSourceProperty("user", getLocalDbUser());
config.addDataSourceProperty("password", getLocalDbPwd());
return new HikariDataSource(config);
}
@Bean
public DataSource remoteDataSource(){
HikariConfig config = new HikariConfig();
config.setMaximumPoolSize(getRemoteDbPoolSize());
config.setMinimumIdle(5);
config.setDriverClassName(getRemoteDbDriverClassName());
config.setJdbcUrl(getRemoteDbJdbcUrl());
config.addDataSourceProperty("user", getRemoteDbUser());
config.addDataSourceProperty("password", getRemoteDbPwd());
return new HikariDataSource(config);
}
}
但是当我初始化我的应用程序时,出现了这个错误:
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'javax.sql.DataSource' available: expected single matching bean but found 2: localDataSource,remoteDataSource
我也试过用户限定bean,如下:
@Bean(name = "localJdbcTemplate")
public JdbcTemplate localJdbcTemplate() {
return new JdbcTemplate(localDataSource());
}
@Bean(name = "remoteJdbcTemplate")
public JdbcTemplate remoteJdbcTemplate() {
return new JdbcTemplate(remoteDataSource());
}
@Bean(name = "localDataSource")
public DataSource localDataSource(){
HikariConfig config = new HikariConfig();
config.setMaximumPoolSize(getLocalDbPoolSize());
config.setMinimumIdle(5);
config.setDriverClassName(getLocalDbDriverClassName());
config.setJdbcUrl(getLocalDbJdbcUrl());
config.addDataSourceProperty("user", getLocalDbUser());
config.addDataSourceProperty("password", getLocalDbPwd());
return new HikariDataSource(config);
}
@Bean(name = "remoteDataSource")
public DataSource remoteDataSource(){
HikariConfig config = new HikariConfig();
config.setMaximumPoolSize(getRemoteDbPoolSize());
config.setMinimumIdle(5);
config.setDriverClassName(getRemoteDbDriverClassName());
config.setJdbcUrl(getRemoteDbJdbcUrl());
config.addDataSourceProperty("user", getRemoteDbUser());
config.addDataSourceProperty("password", getRemoteDbPwd());
return new HikariDataSource(config);
}
但后来我得到了另一个错误:
A component required a bean of type 'org.springframework.transaction.PlatformTransactionManager' that could not be found.
- Bean method 'transactionManager' not loaded because @ConditionalOnSingleCandidate (types: javax.sql.DataSource; SearchStrategy: all) did not find a primary bean from beans 'remoteDataSource', 'localDataSource'
我也试过了
@SpringBootApplication(exclude = {
DataSourceAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class})
@EnableAutoConfiguration(exclude = {
DataSourceAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class})
但后来我得到了
A component required a bean of type 'org.springframework.transaction.PlatformTransactionManager' that could not be found.
您可以使用 bean 名称来限定它们:
@Bean(name = "localDataSource")
public DataSource localDataSource() {
...
}
@Bean(name = "remoteDataSource")
public DataSource remoteDataSource() {
...
}
请注意:您必须对 JdbcTemplate bean 执行相同的操作 - 只需给它们命名即可。
有关详细信息,请参阅 Spring JavaDoc:Bean
@Bean(name = "localJdbcTemplate")
public JdbcTemplate localJdbcTemplate() {
return new JdbcTemplate(localDataSource());
}
当您通过自动装配 (@Autowired) 在导出服务实现中使用 JdbcTemplate beans 时,您需要使用 @Qualifier 来限定它们:
@Autowired
@Qualifier("localJdbcTemplate")
private JdbcTemplate jdbcTemplate;
@Autowired
@Qualifier("remoteJdbcTemplate")
private JdbcTemplate jdbcTemplate;
Bean 从方法名中获取其名称,提供名称属性只是使其显式(保持名称与方法名称相同)。关于 @Bean(name="...")
和 @Qualifier
的总体建议没有为我解决错误。
我用两个嵌入式数据库设置了示例项目,得到了与作者相同的错误。 Spring 建议将其中一个 DataSource bean 注释为 @Primary
,事实上,这修复了错误。通常,当一些其他应用程序部分只想查看一个或一个主要数据源(如果存在多个)时,就会发生这种情况。
似乎更好的解决方案是禁用不需要的自动配置 bean,保持其余代码不变:
@SpringBootApplication(exclude = {
DataSourceAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class})
或:
@EnableAutoConfiguration(exclude = {
DataSourceAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class})
取决于正在使用的注释。
如果作者不使用任何 JPA 提供程序并直接使用 JdbcTemplate 进行操作,它可能是一个合适的解决方案。
我有一个 SpringBoot 应用程序。必须访问不同的数据源才能将数据从 1 导出到另一个(1 个本地数据源和另一个远程数据源)
这就是我的持久化配置的样子
public class PersistenceConfig {
@Bean
public JdbcTemplate localJdbcTemplate() {
return new JdbcTemplate(localDataSource());
}
@Bean
public JdbcTemplate remoteJdbcTemplate() {
return new JdbcTemplate(remoteDataSource());
}
@Bean
public DataSource localDataSource(){
HikariConfig config = new HikariConfig();
config.setMaximumPoolSize(getLocalDbPoolSize());
config.setMinimumIdle(5);
config.setDriverClassName(getLocalDbDriverClassName());
config.setJdbcUrl(getLocalDbJdbcUrl());
config.addDataSourceProperty("user", getLocalDbUser());
config.addDataSourceProperty("password", getLocalDbPwd());
return new HikariDataSource(config);
}
@Bean
public DataSource remoteDataSource(){
HikariConfig config = new HikariConfig();
config.setMaximumPoolSize(getRemoteDbPoolSize());
config.setMinimumIdle(5);
config.setDriverClassName(getRemoteDbDriverClassName());
config.setJdbcUrl(getRemoteDbJdbcUrl());
config.addDataSourceProperty("user", getRemoteDbUser());
config.addDataSourceProperty("password", getRemoteDbPwd());
return new HikariDataSource(config);
}
}
但是当我初始化我的应用程序时,出现了这个错误:
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'javax.sql.DataSource' available: expected single matching bean but found 2: localDataSource,remoteDataSource
我也试过用户限定bean,如下:
@Bean(name = "localJdbcTemplate")
public JdbcTemplate localJdbcTemplate() {
return new JdbcTemplate(localDataSource());
}
@Bean(name = "remoteJdbcTemplate")
public JdbcTemplate remoteJdbcTemplate() {
return new JdbcTemplate(remoteDataSource());
}
@Bean(name = "localDataSource")
public DataSource localDataSource(){
HikariConfig config = new HikariConfig();
config.setMaximumPoolSize(getLocalDbPoolSize());
config.setMinimumIdle(5);
config.setDriverClassName(getLocalDbDriverClassName());
config.setJdbcUrl(getLocalDbJdbcUrl());
config.addDataSourceProperty("user", getLocalDbUser());
config.addDataSourceProperty("password", getLocalDbPwd());
return new HikariDataSource(config);
}
@Bean(name = "remoteDataSource")
public DataSource remoteDataSource(){
HikariConfig config = new HikariConfig();
config.setMaximumPoolSize(getRemoteDbPoolSize());
config.setMinimumIdle(5);
config.setDriverClassName(getRemoteDbDriverClassName());
config.setJdbcUrl(getRemoteDbJdbcUrl());
config.addDataSourceProperty("user", getRemoteDbUser());
config.addDataSourceProperty("password", getRemoteDbPwd());
return new HikariDataSource(config);
}
但后来我得到了另一个错误:
A component required a bean of type 'org.springframework.transaction.PlatformTransactionManager' that could not be found.
- Bean method 'transactionManager' not loaded because @ConditionalOnSingleCandidate (types: javax.sql.DataSource; SearchStrategy: all) did not find a primary bean from beans 'remoteDataSource', 'localDataSource'
我也试过了
@SpringBootApplication(exclude = {
DataSourceAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class})
@EnableAutoConfiguration(exclude = {
DataSourceAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class})
但后来我得到了
A component required a bean of type 'org.springframework.transaction.PlatformTransactionManager' that could not be found.
您可以使用 bean 名称来限定它们:
@Bean(name = "localDataSource")
public DataSource localDataSource() {
...
}
@Bean(name = "remoteDataSource")
public DataSource remoteDataSource() {
...
}
请注意:您必须对 JdbcTemplate bean 执行相同的操作 - 只需给它们命名即可。 有关详细信息,请参阅 Spring JavaDoc:Bean
@Bean(name = "localJdbcTemplate")
public JdbcTemplate localJdbcTemplate() {
return new JdbcTemplate(localDataSource());
}
当您通过自动装配 (@Autowired) 在导出服务实现中使用 JdbcTemplate beans 时,您需要使用 @Qualifier 来限定它们:
@Autowired
@Qualifier("localJdbcTemplate")
private JdbcTemplate jdbcTemplate;
@Autowired
@Qualifier("remoteJdbcTemplate")
private JdbcTemplate jdbcTemplate;
Bean 从方法名中获取其名称,提供名称属性只是使其显式(保持名称与方法名称相同)。关于 @Bean(name="...")
和 @Qualifier
的总体建议没有为我解决错误。
我用两个嵌入式数据库设置了示例项目,得到了与作者相同的错误。 Spring 建议将其中一个 DataSource bean 注释为 @Primary
,事实上,这修复了错误。通常,当一些其他应用程序部分只想查看一个或一个主要数据源(如果存在多个)时,就会发生这种情况。
似乎更好的解决方案是禁用不需要的自动配置 bean,保持其余代码不变:
@SpringBootApplication(exclude = {
DataSourceAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class})
或:
@EnableAutoConfiguration(exclude = {
DataSourceAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class})
取决于正在使用的注释。
如果作者不使用任何 JPA 提供程序并直接使用 JdbcTemplate 进行操作,它可能是一个合适的解决方案。