使用jdbcTemplate查询数据库
springboot2版本项目中已经整合了mybatis框架,yml文件中配置好了数据源, 现在想再使用jdbcTemplate查询另外一个数据库,需要怎么配置

# 这是你现有的MyBatis数据源配置(假设使用默认前缀)
spring:
datasource:
url: jdbc:mysql://localhost:3306/main_db
username: root
password: password
driver-class-name: com.mysql.cj.jdbc.Driver
# 新增的第二个数据源配置
datasource:
secondary:
jdbc-url: jdbc:mysql://localhost:3306/another_db # 注意这里使用jdbc-url而非url:cite[5]:cite[10]
username: root
password: password
driver-class-name: com.mysql.cj.jdbc.Driver
# 可以根据需要配置连接池参数,例如HikariCP:
hikari:
maximum-pool-size: 10
minimum-idle: 2
注意:第二个数据源的URL配置,建议使用 jdbc-url 而不是 url。这是因为Spring Boot在自动配置多个数据源时可能会产生冲突,明确指定 jdbc-url 可以避免 "jdbcUrl is required with driverClassName" 的错误
编写Java配置类
新建一个Java配置类(例如 JdbcTemplateConfig),用于创建第二个数据源的 DataSource Bean 和 JdbcTemplate Bean。
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.jdbc.DataSourceBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.jdbc.core.JdbcTemplate; import javax.sql.DataSource; @Configuration public class JdbcTemplateConfig { /** * 配置第二个数据源 * 使用@ConfigurationProperties注解绑定配置文件中"spring.datasource.secondary"开头的属性 */ @Bean(name = "secondaryDataSource") @ConfigurationProperties(prefix = "spring.datasource.secondary") public DataSource secondaryDataSource() { return DataSourceBuilder.create().build(); } /** * 创建第二个JdbcTemplate,并注入名为"secondaryDataSource"的数据源。 * 使用@Qualifier注解明确指定要注入的Bean名称。 */ @Bean(name = "secondaryJdbcTemplate") public JdbcTemplate secondaryJdbcTemplate(@Qualifier("secondaryDataSource") DataSource dataSource) { return new JdbcTemplate(dataSource); } }
关键点说明:
-
@Bean(name = "secondaryDataSource"): 为Bean定义一个名称,便于后续注入时区分。 -
@ConfigurationProperties(prefix = "spring.datasource.secondary"): 告诉Spring将配置文件中以spring.datasource.secondary为前缀的属性映射到这个DataSource的所有属性上。 -
@Qualifier("secondaryDataSource"): 当注入DataSource时,通过名称明确指定要注入的是我们刚刚定义的第二个数据源Bean,而不是MyBatis使用的那个默认数据源
在Service中使用第二个JdbcTemplate
在你的Service类中,使用 @Autowired 和 @Qualifier 注解注入指定的 JdbcTemplate Bean。
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Service; import java.util.List; import java.util.Map; @Service public class YourService { // 注入第二个JdbcTemplate @Autowired @Qualifier("secondaryJdbcTemplate") // 指定注入名为"secondaryJdbcTemplate"的Bean private JdbcTemplate secondaryJdbcTemplate; public List<Map<String, Object>> queryFromOtherDatabase() { String sql = "SELECT * FROM some_table"; // 使用secondaryJdbcTemplate执行查询,操作的就是另一个数据库 return secondaryJdbcTemplate.queryForList(sql); } }
重要的注意事项
-
事务管理:需要特别注意事务问题。如果你在使用了
@Transactional注解的方法中操作多个数据源,默认的事务管理器可能只管理其中一个数据源的事务。你需要为每个数据源配置独立的PlatformTransactionManagerBean,并在@Transactional注解中通过transactionManager属性指定使用哪个事务管理器。例如:@Bean(name = "secondaryTransactionManager")
public PlatformTransactionManager secondaryTransactionManager(@Qualifier("secondaryDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
然后在使用时:
@Transactional(transactionManager = "secondaryTransactionManager") // 指定事务管理器
public void updateInSecondaryDatabase() {
// ... 使用secondaryJdbcTemplate执行更新操作
}
对于需要跨数据源的真正分布式事务,需要考虑使用JTA解决方案,但这会复杂得多
<!-- MyBatis Spring Boot Starter --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.4</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency>
如果遇到数据源错乱问题,参考👇🏻
🧩 原因分析与解决方案
1. 数据源(DataSource)Bean的注入问题
Spring Boot的自动配置在遇到多个DataSource Bean时,如果未明确指定,可能会注入错误的Bean。
-
原因:你可能配置了多个
DataSourceBean(例如一个给MyBatis,一个给JdbcTemplate),但没有明确地通过@Primary注解指定哪个是默认数据源,或者没有在注入时通过@Qualifier注解按名称(Bean Name)进行区分。这会导致Spring自动注入时发生混乱。 -
解决方案:确保每个
DataSourceBean都有唯一的名称,并且为MyBatis使用的数据源设置@Primary注解(如果你的MyBatis期望使用主数据源)。同时,在注入时使用@Qualifier明确指定。
@Configuration public class DataSourceConfig { // 为MyBatis配置主数据源(primary) @Bean(name = "mybatisDataSource") @Primary // 关键:标记为默认数据源,MyBatis通常会使用默认的DataSource @ConfigurationProperties(prefix = "spring.datasource.mybatis") public DataSource mybatisDataSource() { return DataSourceBuilder.create().build(); } // 为JdbcTemplate配置另一个数据源 @Bean(name = "jdbcTemplateDataSource") @ConfigurationProperties(prefix = "spring.datasource.jdbctemplate") public DataSource jdbcTemplateDataSource() { return DataSourceBuilder.create().build(); } }
然后在配置JdbcTemplate时,明确指定使用哪个数据源:
@Bean public JdbcTemplate jdbcTemplate(@Qualifier("jdbcTemplateDataSource") DataSource dataSource) { return new JdbcTemplate(dataSource); }
MyBatis(尤其是通过mybatis-spring-boot-starter自动配置时)通常会自动使用标记了@Primary的DataSource。
2. MyBatis配置未正确关联指定数据源
如果你为MyBatis自定义了配置,需要确保其使用的SqlSessionFactoryBean关联到了正确的DataSource Bean。
-
原因:自定义的
SqlSessionFactoryBean可能没有注入你希望它使用的DataSource。 -
解决方案:在创建
SqlSessionFactoryBean时,通过@Qualifier注入为MyBatis准备的特定数据源。
@Configuration @MapperScan(basePackages = "com.example.mapper", sqlSessionFactoryRef = "mybatisSqlSessionFactory") public class MyBatisConfig { @Bean(name = "mybatisSqlSessionFactory") public SqlSessionFactoryBean sqlSessionFactory(@Qualifier("mybatisDataSource") DataSource dataSource) throws Exception { SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); sessionFactory.setDataSource(dataSource); // 关联MyBatis专用的数据源 // 其他MyBatis配置(如mapper.xml位置等) return sessionFactory; } }
3. 事务管理器(TransactionManager)冲突
Spring的事务管理也需要知道操作哪个数据源。
-
原因:如果只配置了一个全局的
PlatformTransactionManager,它可能绑定到了错误的数据源上。 -
解决方案:为不同的数据源配置各自的事务管理器,并在使用
@Transactional注解时根据需要指定事务管理器(但通常查询操作不涉及事务,此问题影响较小)。
@Bean(name = "mybatisTransactionManager") @Primary public PlatformTransactionManager mybatisTransactionManager(@Qualifier("mybatisDataSource") DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } @Bean(name = "jdbcTemplateTransactionManager") public PlatformTransactionManager jdbcTemplateTransactionManager(@Qualifier("jdbcTemplateDataSource") DataSource dataSource) { return new DataSourceTransactionManager(dataSource); }
4. 配置文件(application.yml)问题
确保你的配置文件中的多数据源配置前缀正确,并且没有相互覆盖。
spring:
datasource:
# MyBatis 使用的数据源配置
mybatis:
jdbc-url: jdbc:mysql://localhost:3306/db_mybatis
username: user_mybatis
password: pass_mybatis
driver-class-name: com.mysql.cj.jdbc.Driver
# JdbcTemplate 使用的数据源配置
jdbctemplate:
jdbc-url: jdbc:mysql://localhost:3306/db_jtemplate # 注意此处使用 jdbc-url 而非 url:cite[1]
username: user_jtemplate
password: pass_jtemplate
driver-class-name: com.mysql.cj.jdbc.Driver
核心检查点
-
Bean名称与限定:检查是否为每个
DataSource、JdbcTemplate、SqlSessionFactoryBean等定义了清晰的Bean名称,并在注入时使用@Qualifier。 -
@Primary注解:通常将MyBatis使用的数据源设为@Primary,因为许多Spring Boot自动配置默认期望存在一个主数据源。 -
配置隔离:在
application.yml中使用不同的前缀(如spring.datasource.mybatis和spring.datasource.jdbctemplate)清晰隔离两个数据源的配置。 -
URL属性:在多数据源配置中,使用
jdbc-url而非url来避免潜在的配置解析问题

浙公网安备 33010602011771号