在Java企业级应用开发中,数据库连接管理是一个基础但至关重要的环节。Spring框架作为Java生态中最流行的开发框架之一,提供了多种数据源(DataSource)配置方式,帮助开发者灵活应对不同场景下的数据库连接需求。
数据源本质上是对数据库连接的抽象和管理,它负责创建、维护和分发数据库连接。合理配置数据源不仅能提升应用性能,还能增强系统的稳定性和可维护性。Spring本身并不直接实现数据源,而是通过集成各种成熟的数据源实现,为开发者提供统一的配置和使用方式。
在实际项目中,我们通常会根据应用场景选择以下几种数据源类型:
数据库连接池是一种重要的性能优化技术,它通过预先创建并维护一定数量的数据库连接,在应用需要时快速提供可用连接,使用完毕后回收连接而非直接关闭。这种方式避免了频繁创建和销毁连接的开销,特别适合高并发场景。
Spring支持多种流行的连接池实现,每种都有其特点和适用场景:
DBCP是Apache基金会下的一个成熟连接池项目,配置相对简单,适合大多数常规应用场景。
xml复制<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${db.driverClass}"/>
<property name="url" value="${db.url}"/>
<property name="username" value="${db.username}"/>
<property name="password" value="${db.password}"/>
<!-- 连接池调优参数 -->
<property name="initialSize" value="5"/>
<property name="maxActive" value="20"/>
<property name="maxIdle" value="10"/>
<property name="minIdle" value="5"/>
<property name="maxWait" value="30000"/>
</bean>
java复制@Bean(destroyMethod = "close")
public DataSource dataSource() {
BasicDataSource ds = new BasicDataSource();
ds.setDriverClassName(env.getProperty("db.driverClass"));
ds.setUrl(env.getProperty("db.url"));
ds.setUsername(env.getProperty("db.username"));
ds.setPassword(env.getProperty("db.password"));
// 连接池调优参数
ds.setInitialSize(5);
ds.setMaxActive(20);
ds.setMaxIdle(10);
ds.setMinIdle(5);
ds.setMaxWait(30000);
return ds;
}
| 参数名 | 默认值 | 建议值 | 说明 |
|---|---|---|---|
| initialSize | 0 | 5-10 | 初始连接数,避免首次请求等待 |
| maxActive | 8 | 根据系统负载调整 | 最大活动连接数 |
| maxIdle | 8 | 同maxActive | 最大空闲连接数 |
| minIdle | 0 | 3-5 | 最小空闲连接数 |
| maxWait | 无限 | 30000(ms) | 获取连接超时时间 |
提示:生产环境中,maxActive的值应该根据数据库服务器配置和应用负载情况合理设置,过大会导致数据库压力过大,过小则无法满足并发需求。
c3p0是另一个广泛使用的连接池实现,提供了更多高级功能如连接测试、自动重连等。
xml复制<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="${db.driverClass}"/>
<property name="jdbcUrl" value="${db.url}"/>
<property name="user" value="${db.username}"/>
<property name="password" value="${db.password}"/>
<!-- 连接池调优参数 -->
<property name="minPoolSize" value="5"/>
<property name="maxPoolSize" value="30"/>
<property name="acquireIncrement" value="5"/>
<property name="idleConnectionTestPeriod" value="60"/>
</bean>
java复制@Bean(destroyMethod = "close")
public DataSource dataSource() throws PropertyVetoException {
ComboPooledDataSource ds = new ComboPooledDataSource();
ds.setDriverClass(env.getProperty("db.driverClass"));
ds.setJdbcUrl(env.getProperty("db.url"));
ds.setUser(env.getProperty("db.username"));
ds.setPassword(env.getProperty("db.password"));
// 连接池调优参数
ds.setMinPoolSize(5);
ds.setMaxPoolSize(30);
ds.setAcquireIncrement(5);
ds.setIdleConnectionTestPeriod(60);
return ds;
}
BoneCP曾以高性能著称,虽然现在维护较少,但在某些特定场景下仍有使用价值。
java复制@Bean(destroyMethod = "close")
public DataSource dataSource() {
BoneCPDataSource ds = new BoneCPDataSource();
ds.setDriverClass(env.getProperty("db.driverClass"));
ds.setJdbcUrl(env.getProperty("db.url"));
ds.setUsername(env.getProperty("db.username"));
ds.setPassword(env.getProperty("db.password"));
// 高性能相关配置
ds.setPartitionCount(3);
ds.setMaxConnectionsPerPartition(20);
ds.setMinConnectionsPerPartition(5);
return ds;
}
注意:BoneCP目前已被HikariCP取代,新项目建议使用HikariCP作为首选连接池。
Spring提供了三种基于JDBC驱动的简单数据源实现:
这些实现适合测试或简单应用,生产环境不推荐使用。
java复制@Bean
public DataSource driverManagerDataSource() {
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/test");
ds.setUsername("root");
ds.setPassword("password");
return ds;
}
警告:在多线程环境下,这些数据源可能成为性能瓶颈或导致连接泄漏,生产环境务必使用连接池。
嵌入式数据库作为应用的一部分运行,无需单独安装数据库服务,具有以下特点:
xml复制<jdbc:embedded-database id="dataSource" type="H2">
<jdbc:script location="classpath:schema.sql"/>
<jdbc:script location="classpath:test-data.sql"/>
</jdbc:embedded-database>
java复制@Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.addScript("classpath:schema.sql")
.addScript("classpath:test-data.sql")
.build();
}
java复制// 启用H2控制台示例
@Bean(initMethod = "start", destroyMethod = "stop")
public Server h2WebConsole() throws SQLException {
return Server.createWebServer("-web", "-webAllowOthers", "-webPort", "8082");
}
properties复制# 典型MySQL连接字符串优化示例
db.url=jdbc:mysql://localhost:3306/dbname?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&autoReconnect=true
Spring Boot极大简化了数据源配置,自动配置逻辑如下:
properties复制# application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=secret
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.hikari.maximum-pool-size=20
spring.datasource.hikari.connection-timeout=30000
对于需要连接多个数据库的场景,需禁用自动配置并手动定义:
java复制@Configuration
public class DataSourceConfig {
@Bean
@ConfigurationProperties("app.datasource.primary")
public DataSource primaryDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties("app.datasource.secondary")
public DataSource secondaryDataSource() {
return DataSourceBuilder.create().build();
}
}
对应属性配置:
properties复制# 主数据源
app.datasource.primary.url=jdbc:mysql://localhost:3306/primary
app.datasource.primary.username=root
app.datasource.primary.password=secret
# 次数据源
app.datasource.secondary.url=jdbc:postgresql://localhost:5432/secondary
app.datasource.secondary.username=postgres
app.datasource.secondary.password=secret
在实际项目中,我推荐使用HikariCP作为默认连接池,它在大多数场景下都能提供最佳性能。对于配置参数,初始阶段可以采用保守值,再通过监控逐步优化。特别是在微服务架构中,合理的数据源配置对系统稳定性至关重要。