如何使用Spring配置HikariCP数据源?

44

你好,我正尝试在Spring中使用HikariCP作为连接池,并且我正在使用JdbcTemplate和JdbcDaoSupport。以下是我的数据源的Spring配置文件:

<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource">
    <property name="dataSourceClassName" value="oracle.jdbc.driver.OracleDriver"/>
    <property name="dataSource.url" value="jdbc:oracle:thin:@localhost:1521:XE"/>
    <property name="dataSource.user" value="username"/>
    <property name="dataSource.password" value="password"/>
</bean>

但遗憾的是,以下错误信息正在生成:

Cannot resolve reference to bean 'dataSource' while setting bean property 'dataSource'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in ServletContext resource [/WEB-INF/dispatcher-servlet.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [com.zaxxer.hikari.HikariDataSource]: No default constructor found; nested exception is java.lang.NoSuchMethodException: com.zaxxer.hikari.HikariDataSource.<init>()

请问有人可以告诉我如何解决这个问题吗?


使用oracle.jdbc.pool.OracleDataSource 请参阅https://github.com/brettwooldridge/HikariCP#popular-datasource-class-names - Aalkhodiry
在xml参数中,此答案及其下方的许多内容将dataSourceClass名称定义为与Hikari不同的内容。当我们实际想要的是Hikari数据源时,定义oracle.jdbc作为dataSourceClassName的目的是什么? - Nelda.techspiress
1
在文档 https://github.com/brettwooldridge/HikariCP#configuration-knobs-baby 中找到了答案。参数dataSourceClassName实际上是指jdbc驱动程序类名。 - Nelda.techspiress
9个回答

38

你需要在bean配置中编写以下结构(这是您的数据源):

<bean id="hikariConfig" class="com.zaxxer.hikari.HikariConfig">
    <property name="poolName" value="springHikariCP" />
    <property name="connectionTestQuery" value="SELECT 1" />
    <property name="dataSourceClassName" value="${hibernate.dataSourceClassName}" />
    <property name="maximumPoolSize" value="${hibernate.hikari.maximumPoolSize}" />
    <property name="idleTimeout" value="${hibernate.hikari.idleTimeout}" />

    <property name="dataSourceProperties">
        <props>
            <prop key="url">${dataSource.url}</prop>
            <prop key="user">${dataSource.username}</prop>
            <prop key="password">${dataSource.password}</prop>
        </props>
    </property>
</bean>

<!-- HikariCP configuration -->
<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close">
    <constructor-arg ref="hikariConfig" />
</bean>

这是我的示例,它可以正常工作。您只需要在hibernate.properties上设置并在之前设置您的属性:

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="locations">
        <list>
            <value>classpath:hibernate.properties</value>
        </list>
    </property>
</bean>

注意: 版本如下
log4j: 1.2.16
springframework: 3.1.4.RELEASE
HikariCP: 1.4.0

属性文件(hibernate.properties):

hibernate.dataSourceClassName=oracle.jdbc.pool.OracleDataSource
hibernate.hikari.maximumPoolSize=10
hibernate.hikari.idleTimeout=30000
dataSource.url=jdbc:oracle:thin:@localhost:1521:xe
dataSource.username=admin
dataSource.password=

1
但是我该如何在我的Java代码中使用上述配置,例如HikariConfig hikariConfig = new HikariConfig();,hikariConfig如何知道选择上述配置的配置? - Sumit Arora

36

我的测试Java配置(适用于MySql)

@Bean(destroyMethod = "close")
public DataSource dataSource(){
    HikariConfig hikariConfig = new HikariConfig();
    hikariConfig.setDriverClassName("com.mysql.jdbc.Driver");
    hikariConfig.setJdbcUrl("jdbc:mysql://localhost:3306/spring-test"); 
    hikariConfig.setUsername("root");
    hikariConfig.setPassword("admin");

    hikariConfig.setMaximumPoolSize(5);
    hikariConfig.setConnectionTestQuery("SELECT 1");
    hikariConfig.setPoolName("springHikariCP");

    hikariConfig.addDataSourceProperty("dataSource.cachePrepStmts", "true");
    hikariConfig.addDataSourceProperty("dataSource.prepStmtCacheSize", "250");
    hikariConfig.addDataSourceProperty("dataSource.prepStmtCacheSqlLimit", "2048");
    hikariConfig.addDataSourceProperty("dataSource.useServerPrepStmts", "true");

    HikariDataSource dataSource = new HikariDataSource(hikariConfig);

    return dataSource;
}

9
您可以在servlet上下文中创建一个数据源Bean,如下所示:
<beans:bean id="dataSource"
    class="com.zaxxer.hikari.HikariDataSource" destroy-method="close">
    <beans:property name="dataSourceClassName"
        value="com.mysql.jdbc.jdbc2.optional.MysqlDataSource" />
    <beans:property name="maximumPoolSize" value="5" />
    <beans:property name="maxLifetime" value="30000" />
    <beans:property name="idleTimeout" value="30000" />
    <beans:property name="dataSourceProperties">
        <beans:props>
            <beans:prop key="url">jdbc:mysql://localhost:3306/exampledb</beans:prop>
            <beans:prop key="user">root</beans:prop>
            <beans:prop key="password"></beans:prop>
            <beans:prop key="prepStmtCacheSize">250</beans:prop>
            <beans:prop key="prepStmtCacheSqlLimit">2048</beans:prop>
            <beans:prop key="cachePrepStmts">true</beans:prop>
            <beans:prop key="useServerPrepStmts">true</beans:prop>
        </beans:props>
    </beans:property>
</beans:bean>

只想指出,“useServerPrepStmts”不建议与MySQL一起使用。 - iMysak
2
@iMysak,看起来Hikari wiki确实建议在使用新版本的MySql(v >= 5.5)时使用"useServerPrepStmts=true"。您可以在此处查看:https://github.com/brettwooldridge/HikariCP/wiki/MySQL-Configuration - PeterToTheThird
1
太好了,感谢@PeterToTheThird的通知。现在已经推荐使用了。https://github.com/brettwooldridge/HikariCP/wiki/MySQL-Configuration/_compare/ad57cbedfdba508d6f509171d15454d37878aed0...73d82adb09f49479fd3b36de5960dfc2a9cf23de - iMysak
一些简单的测试表明,userServerPrepStmts = false 更快。Vlad Mihalcea 的答案也说明了这一点。 - bjmi
一些简单的测试表明,userServerPrepStmts = false 更快。Vlad Mihalcea的答案也说明了这一点。 - undefined

4
使用XML配置,您的数据源应该如下所示:

    <bean id="hikariConfig" class="com.zaxxer.hikari.HikariConfig">  
      <property name="dataSourceProperties" >
        <props>
            <prop key="dataSource.url">jdbc:oracle:thin:@localhost:1521:XE</prop>
            <prop key="dataSource.user">username</prop>
            <prop key="dataSource.password">password</prop>
        </props>
      </property>  
      <property name="dataSourceClassName"   
                value="oracle.jdbc.driver.OracleDriver" />  
    </bean>  

    <bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource">  
          <constructor-arg ref="hikariConfig" />  
    </bean>  

或者您可以完全跳过HikariConfig bean,使用像这里提到的方法。


不行啊,它又抛出了一个异常............................在设置bean属性'dataSource'时无法解析对bean 'dataSource'的引用;嵌套异常是org.springframework.beans.factory.BeanCreationException: 在ServletContext资源[/WEB-INF/dispatcher-servlet.xml]中定义的名为'dataSource'的bean创建失败;嵌套异常是java.lang.NoClassDefFoundError: org/slf4j/impl/StaticLoggerBinder。 - Abhinab Kanrar
你的类路径上是否有 slf4j? - geoand
你可以从这里下载javassist:http://www.csg.ci.i.u-tokyo.ac.jp/~chiba/javassist/ - geoand
1
"dataSourceClassName" 错误,应该是 "oracle.jdbc.pool.OracleDataSource",请参见:https://github.com/brettwooldridge/HikariCP#popular-datasource-class-names - veysiertekin
如果您使用的是 HikariCP 2.6.0,则应直接在 HikariConfig 对象上设置属性,否则将无法正常工作(在新的 MySQL Connector/J 6.0 上进行过测试)。 - ieXcept
显示剩余2条评论

3

我最近在一个基于Spring和Hibernate的项目中从C3P0迁移到HikariCP,这并不像我想象的那么容易,所以我在这里分享我的发现。

如果是Spring Boot项目,请查看我的答案这里

我的设置如下:

  • Spring 4.3.8+
  • Hiberante 4.3.8+
  • Gradle 2.x
  • PostgreSQL 9.5

以下一些配置与上面的某些答案相似,但也有不同之处。

Gradle相关

为了引入正确的jar包,我需要引入以下jar包:

//latest driver because *brettw* see https://github.com/pgjdbc/pgjdbc/pull/849
compile 'org.postgresql:postgresql:42.2.0'
compile('com.zaxxer:HikariCP:2.7.6') {
    //they are pulled in separately elsewhere
    exclude group: 'org.hibernate', module: 'hibernate-core'
}

// Recommended to use HikariCPConnectionProvider by Hibernate in 4.3.6+    
compile('org.hibernate:hibernate-hikaricp:4.3.8.Final') {
        //they are pulled in separately elsewhere, to avoid version conflicts
        exclude group: 'org.hibernate', module: 'hibernate-core'
        exclude group: 'com.zaxxer', module: 'HikariCP'
}

// Needed for HikariCP logging if you use log4j
compile('org.slf4j:slf4j-simple:1.7.25')  
compile('org.slf4j:slf4j-log4j12:1.7.25') {
    //log4j pulled in separately, exclude to avoid version conflict
    exclude group: 'log4j', module: 'log4j'
}

基于Spring/Hibernate的配置

为了让Spring和Hibernate使用Hikari连接池,您需要定义HikariDataSource并将其输入到下面显示的sessionFactory bean中。

<!-- HikariCP Database bean -->
<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close">
    <constructor-arg ref="hikariConfig" />
</bean>

<!-- HikariConfig config that is fed to above dataSource -->
<bean id="hikariConfig" class="com.zaxxer.hikari.HikariConfig">
        <property name="poolName" value="SpringHikariPool" />
        <property name="dataSourceClassName" value="org.postgresql.ds.PGSimpleDataSource" />
        <property name="maximumPoolSize" value="20" />
        <property name="idleTimeout" value="30000" />

        <property name="dataSourceProperties">
            <props>
                <prop key="serverName">localhost</prop>
                <prop key="portNumber">5432</prop>
                <prop key="databaseName">dbname</prop>
                <prop key="user">dbuser</prop>
                <prop key="password">dbpassword</prop>
            </props>
        </property>
</bean>

<bean class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" id="sessionFactory">
        <!-- Your Hikari dataSource below -->
        <property name="dataSource" ref="dataSource"/>
        <!-- your other configs go here -->
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.connection.provider_class">org.hibernate.hikaricp.internal.HikariCPConnectionProvider</prop>
                <!-- Remaining props goes here -->
            </props>
        </property>
 </bean>

如果以上步骤设置完成后,您需要向log4j或logback中添加一个条目,并将level设置为DEBUG,以查看Hikari连接池的启动。

Log4j1.2

<!-- Keep additivity=false to avoid duplicate lines -->
<logger additivity="false" name="com.zaxxer.hikari">
    <level value="debug"/>
    <!-- Your appenders goes here -->
</logger>

Logback

通过在Spring Boot中的application.properties文件进行配置

debug=true
logging.level.com.zaxxer.hikari.HikariConfig=DEBUG 

使用 logback.xml

<logger name="com.zaxxer.hikari" level="DEBUG" additivity="false">
    <appender-ref ref="STDOUT" />
</logger>

有了以上内容,你就可以顺利使用了!显然,为了实现承诺的性能,你需要自定义HikariCP连接池配置。


我注意到所有的答案都在设置凭据。如果我有一个场景,其中凭据需要由请求者的凭据在运行时每个HTTP请求设置,那该怎么办?我可以从配置中省略它们吗? - admdev

2
我在http://www.baeldung.com/hikaricp找到了它,它很有效。
你的pom.xml
<dependency>
            <groupId>com.zaxxer</groupId>
            <artifactId>HikariCP</artifactId>
            <version>2.6.3</version>
        </dependency>

您的 data.xml 文件

<bean id="hikariConfig" class="com.zaxxer.hikari.HikariConfig">
    <property name="driverClassName" value="${jdbc.driverClassName}"/>
    <property name="jdbcUrl" value="${jdbc.databaseurl}"/>
    <property name="username" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
</bean>
<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close">
    <constructor-arg ref="hikariConfig" />
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"
      p:dataSource-ref="dataSource"
/>

您的jdbc.properties文件

jdbc.driverClassName=org.postgresql.Driver
jdbc.dialect=org.hibernate.dialect.PostgreSQL94Dialect
jdbc.databaseurl=jdbc:postgresql://localhost:5432/dev_db
jdbc.username=dev
jdbc.password=dev

我在Baeldung上写的。 - Abhinab Kanrar

2

这个最后的错误是由于找不到SLF4J库引起的。HikariCP有两个依赖项:slf4j和javassist。顺便提一下,HikariDataSource 已经有了 默认构造函数,并且不需要HikariConfig,可以查看此链接。所以那也不是问题所在。


我已经添加了SLF4J jar包。现在错误已经消失了。你能告诉我如何添加javassist吗? - Abhinab Kanrar
只需从此处下载Javassist 3.18.1-GA jar文件,并像添加slf4j一样将其添加到您的类路径中即可。 - brettw

1

希望这也能帮助使用类似Java类的配置文件方式。

@Configuration
@PropertySource("classpath:application.properties")
public class DataSourceConfig {
    @Autowired
    JdbcConfigProperties jdbc;


    @Bean(name = "hikariDataSource")
    public DataSource hikariDataSource() {
        HikariConfig config = new HikariConfig();
        HikariDataSource dataSource;

        config.setJdbcUrl(jdbc.getUrl());
        config.setUsername(jdbc.getUser());
        config.setPassword(jdbc.getPassword());
        // optional: Property setting depends on database vendor
        config.addDataSourceProperty("cachePrepStmts", "true");
        config.addDataSourceProperty("prepStmtCacheSize", "250");
        config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
        dataSource = new HikariDataSource(config);

        return dataSource;
    }
}

如何使用它:

@Component
public class Car implements Runnable {
    private static final Logger logger = LoggerFactory.getLogger(AptSommering.class);


    @Autowired
    @Qualifier("hikariDataSource")
    private DataSource hikariDataSource;


}

0

针对DB2,请尝试以下配置。

<bean id="hikariConfig" class="com.zaxxer.hikari.HikariConfig">
    <property name="poolName" value="springHikariCP" />
    <property name="dataSourceClassName" value="com.ibm.db2.jcc.DB2SimpleDataSource"/>

    <property name="maximumPoolSize" value="${db.maxTotal}" />
    <property name="dataSourceProperties">
        <props>
            <prop key="driverType">4</prop>
            <prop key="serverName">192.168.xxx.xxx</prop>
            <prop key="databaseName">dbname</prop>
            <prop key="portNumber">50000</prop>
            <prop key="user">db2inst1</prop>
            <prop key="password">password</prop>
        </props>
    </property>

    <property name="jdbcUrl" value="${db.url}" />
    <property name="username" value="${db.username}" />
    <property name="password" value="${db.password}" />
</bean>
<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close">
    <constructor-arg ref="hikariConfig" />
</bean>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接