1. 引入 Druid 后是否需要自己维护连接池?
1.1 Druid 的作用
Druid是一个高性能的数据库连接池组件,它负责管理数据库连接的生命周期。- 一旦配置好
Druid数据源,所有的连接获取和释放都会由Druid自动处理。 - 只需要在配置文件中定义数据源的相关参数(如最大连接数、最小空闲连接数等),
Druid会根据这些参数动态管理连接池。
1.2 不需要手动维护连接池
- 在使用
JdbcTemplate或其他数据库操作工具时,Druid会自动从连接池中获取连接,并在操作完成后将连接返回到池中。 - 因此,不需要手动创建或关闭数据库连接,所有这些工作都由
Druid完成。
2. 涉及多种数据源时的处理方式
当项目中需要支持多个数据源(如 MySQL、Oracle、GBase 等)时,Spring Boot 提供了灵活的机制来实现多数据源的支持。以下是具体的解决方案:
2.1 配置多个数据源
在 Spring Boot 中,可以通过以下步骤配置多个数据源:
(1) 定义多个数据源 Bean
为每个数据源创建一个独立的 DataSource Bean,并指定对应的连接池配置。
@Configuration
public class DataSourceConfig {
@Bean(name = "mysqlDataSource")
@ConfigurationProperties(prefix = "spring.datasource.mysql")
public DataSource mysqlDataSource() {
return DruidDataSourceBuilder.create().build();
}
@Bean(name = "oracleDataSource")
@ConfigurationProperties(prefix = "spring.datasource.oracle")
public DataSource oracleDataSource() {
return DruidDataSourceBuilder.create().build();
}
@Bean(name = "gbaseDataSource")
@ConfigurationProperties(prefix = "spring.datasource.gbase")
public DataSource gbaseDataSource() {
return DruidDataSourceBuilder.create().build();
}
}(2) 配置文件中定义多数据源参数
在 application.yml 或 application.properties 中,分别为每个数据源定义配置。
spring:
datasource:
mysql:
url: jdbc:mysql://localhost:3306/mysql_db
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
oracle:
url: jdbc:oracle:thin:@localhost:1521:orcl
username: scott
password: tiger
driver-class-name: oracle.jdbc.OracleDriver
gbase:
url: jdbc:gbase://localhost:5258/gbase_db
username: admin
password: gbase123
driver-class-name: com.gbase.jdbc.Driver2.2 为每个数据源配置 JdbcTemplate
为了区分不同数据源的操作,可以为每个数据源创建独立的 JdbcTemplate 实例。
@Configuration
public class JdbcTemplateConfig {
@Bean(name = "mysqlJdbcTemplate")
public JdbcTemplate mysqlJdbcTemplate(@Qualifier("mysqlDataSource") DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
@Bean(name = "oracleJdbcTemplate")
public JdbcTemplate oracleJdbcTemplate(@Qualifier("oracleDataSource") DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
@Bean(name = "gbaseJdbcTemplate")
public JdbcTemplate gbaseJdbcTemplate(@Qualifier("gbaseDataSource") DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
}2.3 使用多数据源
在业务代码中,通过注入对应的 JdbcTemplate 来操作不同的数据源。
@Service
public class MultiDataSourceService {
@Autowired
@Qualifier("mysqlJdbcTemplate")
private JdbcTemplate mysqlJdbcTemplate;
@Autowired
@Qualifier("oracleJdbcTemplate")
private JdbcTemplate oracleJdbcTemplate;
@Autowired
@Qualifier("gbaseJdbcTemplate")
private JdbcTemplate gbaseJdbcTemplate;
public void queryFromMysql() {
List<Map<String, Object>> result = mysqlJdbcTemplate.queryForList("SELECT * FROM users");
System.out.println("MySQL Result: " + result);
}
public void queryFromOracle() {
List<Map<String, Object>> result = oracleJdbcTemplate.queryForList("SELECT * FROM employees");
System.out.println("Oracle Result: " + result);
}
public void queryFromGbase() {
List<Map<String, Object>> result = gbaseJdbcTemplate.queryForList("SELECT * FROM customers");
System.out.println("GBase Result: " + result);
}
}2.4 动态切换数据源(可选)
如果需要在运行时动态切换数据源,可以使用 Spring 提供的 AbstractRoutingDataSource 来实现动态数据源路由。
(1) 定义动态数据源
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DataSourceContextHolder.getDataSource();
}
}(2) 数据源上下文管理
public class DataSourceContextHolder {
private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
public static void setDataSource(String dataSource) {
contextHolder.set(dataSource);
}
public static String getDataSource() {
return contextHolder.get();
}
public static void clearDataSource() {
contextHolder.remove();
}
}(3) 配置动态数据源
@Configuration
public class DynamicDataSourceConfig {
@Bean
public DataSource dynamicDataSource(
@Qualifier("mysqlDataSource") DataSource mysqlDataSource,
@Qualifier("oracleDataSource") DataSource oracleDataSource,
@Qualifier("gbaseDataSource") DataSource gbaseDataSource) {
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put("mysql", mysqlDataSource);
targetDataSources.put("oracle", oracleDataSource);
targetDataSources.put("gbase", gbaseDataSource);
DynamicDataSource dynamicDataSource = new DynamicDataSource();
dynamicDataSource.setDefaultTargetDataSource(mysqlDataSource); // 默认数据源
dynamicDataSource.setTargetDataSources(targetDataSources);
return dynamicDataSource;
}
}(4) 使用动态数据源
@Service
public class DynamicService {
@Autowired
private JdbcTemplate jdbcTemplate;
public void queryWithDynamicDataSource(String dataSourceKey) {
DataSourceContextHolder.setDataSource(dataSourceKey);
try {
List<Map<String, Object>> result = jdbcTemplate.queryForList("SELECT * FROM some_table");
System.out.println("Result: " + result);
} finally {
DataSourceContextHolder.clearDataSource();
}
}
}3、何时创建连接?
| 场景 | 是否创建连接 | 说明 |
|---|---|---|
| Druid 初始化时 | 取决于initialSize参数 | 如果initialSize > 0,初始化时会创建指定数量的连接;否则不创建。 |
| 第一次触发查询时 | 按需创建 | 如果连接池中没有可用连接,Druid 会动态创建新的连接。 |
| 连接池空闲连接不足时 | 动态补充 | 如果空闲连接数小于minIdle,Druid 会自动补充连接,直到达到minIdle。 |