0%

Spring Boot + HikariCP 多数据源配置

关于 Spring Boot 多数据源的配置网上已经很多了,就不赘述了,讲下遇到的坑以及结合 HikariCP 时的设置。

配置多数据源

直接按照网上的配置一直有报错,解决不了,所以还是一步一步来,每次进一步。

单数据源的项目代码:https://github.com/kengdingxiaoman/workdemo/releases/tag/V0.1

不使用 HikariCP 的多数据源

  1. entity 和 repository类都存放在不同的 package 下

  2. 因为不使用 HikariCP 了,所以在 pom.xml 中把 排除tomcat-jdbc连接池部分注释以便放开使用,如下:

1
2
3
4
5
6
7
8
9
10
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<!--<exclusions>-->
<!--<exclusion>-->
<!--<groupId>org.apache.tomcat</groupId>-->
<!--<artifactId>tomcat-jdbc</artifactId>-->
<!--</exclusion>-->
<!--</exclusions>-->
</dependency>
  1. application.yml 中的配置如下,driver我们先用 com.mysql.jdbc.Driver

先不用 net.sf.log4jdbc.DriverSpy,所以 url 就要改成:

url: ${MYSQL_URL:jdbc:mysql://127.0.0.1:3306/orca?useUnicode=true&characterEncoding=utf8}

而不是

url: ${MYSQL_URL:jdbc:log4jdbc:mysql://127.0.0.1:3306/orca?useUnicode=true&characterEncoding=utf8}

1
2
3
4
5
6
7
8
9
10
11
12
datasource:
book:
driver-class-name: com.mysql.jdbc.Driver
url: ${MYSQL_URL:jdbc:mysql://127.0.0.1:3306/duck?useUnicode=true&characterEncoding=utf8}
username: ${MYSQL_USER:orcauser}
password: ${MYSQL_PASS:orcauser}

user:
driver-class-name: com.mysql.jdbc.Driver
url: ${MYSQL_URL:jdbc:mysql://127.0.0.1:3306/duck?useUnicode=true&characterEncoding=utf8}
username: ${MYSQL_USER:duckuser}
password: ${MYSQL_PASS:duckuser}
  1. 按照网上的配置配置多数据源

修改 DataSourceConfig
增加 BookDataSourceConfig
增加 UserDataSourceConfig

这里遇到一个问题,当时怎么都不行,当初的配置类是 BookDataSource,和配置的datasource名字冲突,结果就一直报错:

No matching factory method found:
factory bean ‘bookDataSource’;
factory method ‘entityManagerFactoryBook()’.
Check that a method with the specified name exists and that it is non-static.

简单多数据源的项目代码:https://github.com/kengdingxiaoman/workdemo/releases/tag/v0.2

引入 net.sf.log4jdbc.DriverSpy

原先的sql语句也可以打印,但参数都是占位符,对于调试和查原因并不方便。引入 net.sf.log4jdbc.DriverSpy 则可以清晰的打印sql语句了。

  1. datasource 的 driver-class-name 配置改为使用 net.sf.log4jdbc.DriverSpy

2)datasource 的 url 配置增加 log4jdbc

1
2
3
4
5
6
7
8
9
10
11
12
datasource:
book:
driver-class-name: net.sf.log4jdbc.DriverSpy
url: ${MYSQL_URL:jdbc:log4jdbc:mysql://127.0.0.1:3306/orca?useUnicode=true&characterEncoding=utf8}
username: ${MYSQL_USER:orcauser}
password: ${MYSQL_PASS:orcauser}

user:
driver-class-name: net.sf.log4jdbc.DriverSpy
url: ${MYSQL_URL:jdbc:log4jdbc:mysql://127.0.0.1:3306/duck?useUnicode=true&characterEncoding=utf8}
username: ${MYSQL_USER:duckuser}
password: ${MYSQL_PASS:duckuser}

否则会报错:

java.sql.SQLException:
Driver:net.sf.log4jdbc.DriverSpy@2cacb7cb returned null for URL:
jdbc:mysql://127.0.0.1:3306/duck?useUnicode=true&characterEncoding=utf8

引入net.sf.log4jdbc.DriverSpy后的多数据源项目代码:https://github.com/kengdingxiaoman/workdemo/releases/tag/v0.3

引入 HikariCP

HikariCP是现在性能最好的数据库连接池组件,不过引入过程中也经历了好多磨难啊。

  1. 使用 HikariCP,放开排除 tomcat-jdbc

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
    <exclusions>
    <exclusion>
    <groupId>org.apache.tomcat</groupId>
    <artifactId>tomcat-jdbc</artifactId>
    </exclusion>
    </exclusions>
    </dependency>
  2. datasource配置中使用 HikariCP

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    datasource:
    book:
    driver-class-name: net.sf.log4jdbc.DriverSpy
    url: ${MYSQL_URL:jdbc:log4jdbc:mysql://127.0.0.1:3306/orca?useUnicode=true&characterEncoding=utf8}
    username: ${MYSQL_USER:orcauser}
    password: ${MYSQL_PASS:orcauser}
    type: com.zaxxer.hikari.HikariDataSource
    hikari:
    connection-timeout: 30000
    idle-timeout: 600000
    max-lifetime: 1800000
    maximum-pool-size: 5
    connection-test-query: SELECT 1

    user:
    driver-class-name: net.sf.log4jdbc.DriverSpy
    url: ${MYSQL_URL:jdbc:log4jdbc:mysql://127.0.0.1:3306/duck?useUnicode=true&characterEncoding=utf8}
    username: ${MYSQL_USER:duckuser}
    password: ${MYSQL_PASS:duckuser}
    type: com.zaxxer.hikari.HikariDataSource
    hikari:
    connection-timeout: 30000
    idle-timeout: 600000
    max-lifetime: 1800000
    maximum-pool-size: 5
    connection-test-query: SELECT 1

具体 hikari 的配置参数可以自行搜索

3)修改 DataSouceConfig

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
@Configuration
public class DataSourceConfig{

@Bean(name = "bookDataSourceProperties")
@Primary
@ConfigurationProperties("spring.datasource.book")
public DataSourceProperties bookDataSourceProperties() {
return new DataSourceProperties();
}

@Bean(name = "userDataSourceProperties")
@ConfigurationProperties("spring.datasource.user")
public DataSourceProperties userDataSourceProperties() {
return new DataSourceProperties();
}

@Primary
@Bean(name = "bookDataSource")
@Qualifier("bookDataSource")
@ConfigurationProperties(prefix = "spring.datasource.book")
public DataSource bookDataSource() {
return bookDataSourceProperties().initializeDataSourceBuilder().type(HikariDataSource.class).build();
}

@Bean(name = "userDataSource")
@Qualifier("userDataSource")
@ConfigurationProperties(prefix = "spring.datasource.user")
public DataSource userDataSource(DataSourceProperties properties) {
return userDataSourceProperties().initializeDataSourceBuilder().type(HikariDataSource.class).build();
}
}

如果提示类DataSourceProperties没有initializeDataSourceBuilder()方法,那请更新Spring Boot的版本,至少升级到1.5.9.RELEASE,在pom.xml中修改:

1
2
3
4
5
6
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
<relativePath />
</parent>

如果 DataSourceConfig不做修改,那么会报错:
Caused by: java.lang.IllegalArgumentException: jdbcUrl is required with driverClassName.

这个错误困扰了我好久,后来参考了这篇文章才解决:https://docs.spring.io/spring-boot/docs/current/reference/html/howto-data-access.html

现在大功告成了!

最终 Spring Boot + HikariCP 的版本请下载:
https://github.com/kengdingxiaoman/workdemo/releases/tag/v0.4