mybatis multiple data sources stepped pit, database connections are often disconnected problem

problem

A strange question on a recent project, the database is often every few hours, it reported the connection has been closed

Even the addition of the following configuration is also still does not work, the Internet did not find any articles that explain the pit

test-on-borrow: true
test-while-idle: true
validation-query: select 1 from dual
复制代码

Why can solve the above on configuring connection is interrupted can see three articles

Investigation

Online finding out, it can only own scrutiny guess. Because it is configured mybatis multiple data sources, each db config I have specifically written as a connection configuration.

Watching DataSourceConfig code, I suddenly thought, because I will not use the default method of creating a DataSource, so I did not read to write application.yml configuration:

    @Bean(name = "db1DataSource")
    @ConfigurationProperties(prefix = "spring.datasource.db1")
    @Primary
    public DataSource dbDataSource() {
        return DataSourceBuilder.create().build();
    }
复制代码

Decisive follow-up build () method

	public DataSource build() {
		Class<? extends DataSource> type = getType();
		DataSource result = BeanUtils.instantiate(type);
		maybeGetDriverClassName();
		bind(result);
		return result;
	}
复制代码

Make a break point at this time can see the result returned is a new DataSource

So we can dbDataSource modify () method, we write the configuration parameters:

 @Value("${spring.datasource.db1.url}")
    private String url;
    @Value("${spring.datasource.db1.username}")
    private String username;
    @Value("${spring.datasource.db1.password}")
    private String password;
    @Value("${spring.datasource.db1.tomcat.test-on-borrow}")
    private boolean testOnBorrow;
    @Value("${spring.datasource.db1.tomcat.test-while-idle}")
    private boolean testWhileIdle;
    @Value("${spring.datasource.db1.tomcat.validation-query}")
    private String validationQuery;
    @Value("${spring.datasource.db1.tomcat.max-idle}")
    private int maxIdle;
    @Value("${spring.datasource.db1.tomcat.min-idle}")
    private int minIdle;
    @Value("${spring.datasource.db1.tomcat.initial-size}")
    private int initialSize;
    @Value("${spring.datasource.db1.tomcat.max-active}")
    private int maxActive;
    @Value("${spring.datasource.db1.tomcat.time-between-eviction-runs-millis}")
    private int timeBetweenEvictionRunsMillis;

    @Bean(name = "db1DataSource")
    @ConfigurationProperties(prefix = "spring.datasource.db1")
    @Primary
    public DataSource dbDataSource() {
        org.apache.tomcat.jdbc.pool.DataSource dataSource = new org.apache.tomcat.jdbc.pool.DataSource();
        dataSource.setDriverClassName("oracle.jdbc.driver.OracleDriver");
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        dataSource.setMaxActive(maxActive);
        dataSource.setMinIdle(minIdle);
        dataSource.setMaxIdle(maxIdle);
        dataSource.setTestOnBorrow(testOnBorrow);
        dataSource.setTestWhileIdle(testWhileIdle);
        dataSource.setValidationQuery(validationQuery);
        dataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
        dataSource.setInitialSize(initialSize);
        return dataSource;
        //return DataSourceBuilder.create().build();
    }
复制代码

Secondary investigation

You can really solve the problem by the above method, but I suddenly thought, DataSource created by default is not necessary basic information url, username, password, etc. That's why these configuration parameters and can be written into it?

This time I see we have a dbDataSource method @Bean(name = "db1DataSource"), so bold guess we inject these configuration parameters is the first time created by Spring's IOC injection. Debug by I found the fact that it is.

Method DataBinder break point bind class,

	public void bind(PropertyValues pvs) {
		MutablePropertyValues mpvs = (pvs instanceof MutablePropertyValues) ?
				(MutablePropertyValues) pvs : new MutablePropertyValues(pvs);
		doBind(mpvs);
	}
复制代码

We can see the call path method

See the familiar refresh Dafa, this part of the source code associated Look Spring Spring source code analysis

At this time only last a doubt, our url, username, password, etc. since DataSource injected into the inside through the IOC, other arguments why not? With my DataSource class all the way up to find his father class interface PoolConfiguration, see all parameters and getset method.

Look at my application.yml configuration file parameters

spring:
    datasource:
        db1:
            url: 
            username: 
            password: 
            driver-class-name: oracle.jdbc.driver.OracleDriver
            tomcat:
                max-wait: 10000
                max-active: 30
                test-on-borrow: true
                max-idle: 5
        db2:
            xxx
            ....
复制代码

Finally found this one up!
Spring data original default tomcat-jdbc connection pool when the parameter settings are

spring:
    datasource:
        url: 
        username: 
        password: 
        driver-class-name: oracle.jdbc.driver.OracleDriver
        tomcat:
            max-wait: 10000
            max-active: 30
            test-on-borrow: true
            max-idle: 5
复制代码

And when using a multi data source configuration and simple that you can just copy the past, so when the IOC Spring injection, read to tomcat.max-wait does not match the DataSource in the setMaxWait method. Nature will not work.

So this problem only need to configure the file to read as follows

spring:
    datasource:
        db1:
            url: 
            username: 
            password: 
            driver-class-name: oracle.jdbc.driver.OracleDriver
            max-wait: 10000
            max-active: 30
            test-on-borrow: true
            test-while-idle: true
            validation-query: select 1 from dual
            max-idle: 5
        db2:
            xxx
            ....
复制代码

to sum up

The problem from the results, then it is not simple, but from the process, not only let me go over it again and spring IOC process, let me feel this issue step by step dissection, more knowledge to connect the dots the sense of accomplishment. If you do not learn until spring source, the high probability I would not think it to see the bean injection

Guess you like

Origin juejin.im/post/5d673fbc5188256e8b5d0490