Spring DataSource错误用法


三寻猿
发布于 2024-07-11 / 21 阅读 / 0 评论 /
适用场景 一般在多数据源应用中,我们会使用Spring Configuration类+application.properties配置DataSource。此时应该注意相关用法,避免出现配置不生效,甚至运行时取不到数据库连接的问题。 如果你是单数据源应用,只需在application.propert

适用场景

一般在多数据源应用中,我们会使用Spring Configuration类+application.properties配置DataSource。此时应该注意相关用法,避免出现配置不生效,甚至运行时取不到数据库连接的问题。

如果你是单数据源应用,只需在application.properties中配置即可避免本文的问题。以下内容均在假设你的应用是Spring Configuration类+application.properties配置DataSource的前提下。

注意事项

应该指定type,不应该省略

原因是,当省略type时,Spring boot会顺序尝试加载不同type的DataSource。但不同Spring boot版本的获取DataSource优先级顺序不同,

如Spring boot 1.x为:

{ "org.apache.tomcat.jdbc.pool.DataSource",
			"com.zaxxer.hikari.HikariDataSource", "org.apache.commons.dbcp.BasicDataSource", 
			"org.apache.commons.dbcp2.BasicDataSource" };

Spring boot 2.x为:

{ "com.zaxxer.hikari.HikariDataSource",
			"org.apache.tomcat.jdbc.pool.DataSource", "org.apache.commons.dbcp2.BasicDataSource" }

这样会导致:

  • 相同的配置在A应用生效,在B应用无效。(A、B应用Spring boot版本不同)

  • 没有改配置,但是因为依赖包变化,导致原来生效的配置失效。(DataSource的type变了)

应该在Configuration类中指定type,不应该在application.properties

原因是,DataSourceBuilder在build时就会确定DataSource的type,application.properties里配置的type是不起作用的。

错误写法:

@Bean(name = "adbDataSource")
@ConfigurationProperties(prefix = "spring.datasource.adb")
public DataSource adbDataSource() {
    return DataSourceBuilder.create().build();
}

application.properties
----------------------
spring.datasource.adb.username=xxx
spring.datasource.adb.password=xxx
spring.datasource.adb.jdbc-url=jdbc:mysql:xxx
spring.datasource.adb.type=com.zaxxer.hikari.HikariDataSource

正确写法:

@Bean(name = "adbDataSource")
@ConfigurationProperties(prefix = "spring.datasource.adb")
public DataSource adbDataSource() {
    return DataSourceBuilder.create()
        .type(HikariDataSource.class)
        .build();
}

application.properties
----------------------
spring.datasource.adb.username=xxx
spring.datasource.adb.password=xxx
spring.datasource.adb.jdbc-url=jdbc:mysql:xxx

逐个确认配置参数

不同的DataSource,甚至相同DataSource的不同版本,配置参数的名称和配置值方式都可能不同。应该逐个确认配置参数,否则可能会出现配置不生效(且运行无提示)。

如druid探活配置为

spring.datasource.adb.validation-query=SELECT 1
spring.datasource.adb.time-between-eviction-runs-millis=18800

hikari探活配置为

spring.datasource.adb.connection-test-query=SELECT 1 # 可省略,省略时通过JDBC4.x ping数据包方式探活,性能更好
spring.datasource.adb.keepalive-time=18800

推荐配置

以hikari举例

@Bean(name = "adbDataSource")
@ConfigurationProperties(prefix = "spring.datasource.adb")
public DataSource adbDataSource() {
    return DataSourceBuilder.create()
        .type(HikariDataSource.class)
        .build();
}
spring.datasource.adb.username=xxx
spring.datasource.adb.password=xxx
spring.datasource.adb.jdbc-url=jdbc:mysql:xxx
spring.datasource.adb.driver-class-name=com.mysql.cj.jdbc.Driver

# 按需打开
# spring.datasource.adb.read-only=true

# 最大连接数
spring.datasource.adb.maximum-pool-size=50

# 最小空闲连接数和空闲连接回收时间
# spring.datasource.adb.minimum-idle=1
# spring.datasource.adb.idle-timeout=30000

# 建立链接超时时间5秒
spring.datasource.adb.connection-timeout=5000

# 每30秒探活
spring.datasource.adb.keepalive-time=30000
# connection-test-query可省略,省略时通过JDBC4.x ping数据包方式探活,性能更好
# spring.datasource.adb.connection-test-query=SELECT 1

# 探活超时时间
# spring.datasource.adb.validation-timeout=5000

# 最多持有15分钟
spring.datasource.adb.max-lifetime=900000


评论