如何使用默认的Tomcat连接池在Spring Boot 1.3.x中的DataSource上设置自定义连接属性

问题描述 投票:9回答:4

我需要设置一些特定的Oracle JDBC连接属性,以加快批量INSERTs(defaultBatchValue)和质量SELECTs(defaultRowPrefetch)。我得到suggestions如何用DBCP实现这一点(感谢M. Deinum)但我想:

  • 保留默认的Tomcat jdbc连接池
  • 保留application.yml进行配置

我正在考虑将来支持spring.datasource.custom_connection_properties或类似功能的功能请求,因为这已经尝试了这个已经成为可能。我这样做是通过在创建DataSource时传递相关信息并操纵DataSource的创建,如下所示:

@Bean
public DataSource dataSource() {
    DataSource ds = null;

    try {
        Field props = DataSourceBuilder.class.getDeclaredField("properties");
        props.setAccessible(true);
        DataSourceBuilder builder = DataSourceBuilder.create();
        Map<String, String> properties = (Map<String, String>) props.get(builder);

        properties.put("defaultRowPrefetch", "1000");
        properties.put("defaultBatchValue", "1000");

        ds = builder.url( "jdbc:oracle:thin:@xyz:1521:abc" ).username( "ihave" ).password( "wonttell" ).build();

        properties = (Map<String, String>) props.get(builder);

        log.debug("properties after: {}", properties);
    } ... leaving out the catches ...
    }
    log.debug("We are using this datasource: {}", ds);
    return ds;
}

在日志中我可以看到我正在创建正确的DataSource:

2016-01-18 14:40:32.924 DEBUG 31204 --- [           main] d.a.e.a.c.config.DatabaseConfiguration   : We are using this datasource: org.apache.tomcat.jdbc.pool.DataSource@19f040ba{ConnectionPool[defaultAutoCommit=null; ...

2016-01-18 14:40:32.919 DEBUG 31204 --- [           main] d.a.e.a.c.config.DatabaseConfiguration   : properties after: {password=wonttell, driverClassName=oracle.jdbc.OracleDriver, defaultRowPrefetch=1000, defaultBatchValue=1000, url=jdbc:oracle:thin:@xyz:1521:abc, username=ihave}

执行器向我显示我的代码替换了数据源:

enter image description here

但是没有激活设置,我可以在分析应用程序时看到这些设置。 defaultRowPrefetch仍然在10,这导致我的SELECTs比1000被激活时要慢得多。

spring-boot connection-pooling jdbctemplate ojdbc tomcat-jdbc
4个回答
9
投票

设置池connectionProperties应该工作。这些将被传递给JDBC驱动程序。将其添加到application.properties:

spring.datasource.connectionProperties: defaultRowPrefetch=1000;defaultBatchValue=1000

编辑(一些背景信息):

另请注意,您可以通过spring.datasource配置任何DataSource实现特定属性。*:有关更多详细信息,请参阅您正在使用的连接池实现的文档。

来源:spring-boot documentation


2
投票

一些额外的信息来补充@Cyril的答案。如果你想upvote使用他的答案,而不是我的。

我有点困惑的是,在创建数据库连接时最终设置的其他连接属性是多么容易。所以我做了一些研究。

spring.datasource.connectionProperties中没有提到reference。因为这个我创造了一个issue。如果我使用过Spring Boot YML editor,我会看到支持哪些属性。以下是STS在您创建application.yml并按Ctrl + Space时的建议:

Autocomplete for spring.datasource

短划线无关紧要因为relaxed binding,但如果你从字面上解释它的属性名称是spring.datasource.connection-properties

application.yml中的正确设置如下所示:

spring:
    datasource:
        connection-properties: defaultBatchValue=1000;defaultRowPrefetch=1000
        ...

这得到了荣誉,我的perf4j质量SELECTs测量证明了这一点。

之前:

2016-01-19 08:58:32.604 INFO 15108 --- [main] org.perf4j.TimingLogger:start [1453190311227] time [1377] tag [get elements]

后:

2016-01-19 08:09:18.214 INFO 9152 --- [main] org.perf4j.TimingLogger:start [1453187358066] time [147] tag [get elements]

完成SQL语句所需的时间从1377ms降至147,这是性能的巨大提升。


1
投票

在挖掘了Tomcat代码之后,我发现dataSource.getPoolProperties().getDbProperties()Properties对象,它实际上将用于为池生成连接。

如果您使用@m-deinum提到的BeanPostProcessor方法,而是使用它来填充dbProperties,那么您应该能够以一种使它们坚持并传递给Oracle驱动程序的方式添加属性。

import java.util.Properties;
import org.apache.tomcat.jdbc.pool.DataSource;
import org.apache.tomcat.jdbc.pool.PoolConfiguration;

@Component
public class OracleConfigurer implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String name) throws BeansException {
        if (bean instanceof DataSource) {
            DataSource dataSource = (DataSource)bean;
            PoolConfiguration configuration = dataSource.getPoolProperties();
            Properties properties = configuration.getDbProperties();
            if (null == properties) properties = new Properties();
            properties.put("defaultRowPrefetch", 1000);
            properties.put("defaultBatchValue", 1000);
            configuration.setDbProperties(properties);
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String name) throws BeansException {
        return bean;
    }
}

1
投票

由于Spring Boot已经很长时间了,我使用新的默认连接池Hikari切换到Spring Boot 2.1。这里的解决方案更简单,可以在application.properties或(如此处所示)application.yml中完成:

spring:
  datasource:
    hikari:
      data-source-properties:
        defaultRowPrefetch: 1000

(在现实生活中的配置中会有其他一些配置项,但由于它们对我提出的问题不感兴趣,我只是在我的例子中将它们遗漏了)

© www.soinside.com 2019 - 2024. All rights reserved.