Across and HikariCP
What is HikariCP?
HikariCP is an alternative lightweight connection pool, it's an alternative some of the well known connection pools:
HikariCP claims to be the fastest of them all, see the benchmarks on https://github.com/brettwooldridge/HikariCP
Usage in Across
For the Knooppunt project we switched the Across Datasource to use HikariCP, instead of using DBCP, this is the  existing code block for DBCP:
@Bean @DependsOn("logbackConfigurer") public DataSource acrossDataSource() { BasicDataSource dataSource = new BasicDataSource(); dataSource.setDriverClassName( environment.getRequiredProperty( "datasource.driver" ) ); dataSource.setUrl( environment.getRequiredProperty( "datasource.url" ) ); dataSource.setUsername( environment.getRequiredProperty( "datasource.username" ) ); dataSource.setPassword( environment.getRequiredProperty( "datasource.password" ) ); return dataSource; }
This the configuration for Hikari:
@Bean @DependsOn("logbackConfigurer") public DataSource acrossDataSource() { HikariConfig config = new HikariConfig(); config.setMaximumPoolSize(20); config.setDataSourceClassName( environment.getRequiredProperty( "datasource.classname" ) ); String serverName = environment.getRequiredProperty( "datasource.servername" ); if( StringUtils.isNotEmpty( serverName ) ) { // not required for HSQLDB config.addDataSourceProperty("serverName", serverName ); } String port = environment.getRequiredProperty( "datasource.port" ); if( StringUtils.isNotEmpty( port ) ) { // not required for HSQLDB config.addDataSourceProperty("port", port ); } config.addDataSourceProperty("databaseName", environment.getRequiredProperty( "datasource.database" )); config.addDataSourceProperty("user", environment.getRequiredProperty( "datasource.username" ) ); config.addDataSourceProperty("password", environment.getRequiredProperty( "datasource.password" )); return new HikariDataSource( config); }
The properties are pretty self-explanatory, basically you need the the datasource class name, servername, port, databasename, dbuser and dbpassword passed to Hikari.
DataSourceClassName vs JDBCUrl
There are two ways of configuring HikariDatasource:
- Via DataSourceClassName (recommended)
- Via JDBC Url
The DataSourceClassName option requires a few more properties to be set, but is recommended because it directly instantiates the correct database driver.
The list of popular DataSourceClassName can be found on https://github.com/brettwooldridge/HikariCP, the most popular are listed here:
Database | Driver | DataSource class |
---|---|---|
Apache Derby | Derby | org.apache.derby.jdbc.ClientDataSource |
HSQLDB | HSQLDB | org.hsqldb.jdbc.JDBCDataSource |
MariaDB & MySQL | MariaDB | org.mariadb.jdbc.MySQLDataSource |
MySQL | Connector/J | com.mysql.jdbc.jdbc2.optional.MysqlDataSource |
MS SQL Server | Microsoft | com.microsoft.sqlserver.jdbc.SQLServerDataSource |
Oracle | Oracle | oracle.jdbc.pool.OracleDataSource |
Â
With JDBCurl, when using the following construct:
config.setJdbcUrl("jdbc:mysql://localhost:3306/mysqldb");
Hikari will have to wrap the Datasource into a DriverDataSource class, leading to more calls and cause a performance hit as can be seen in HikariPool.java
return new DriverDataSource(configuration.getJdbcUrl(), configuration.getDataSourceProperties(), username, password);
Hibernate 4.2 bug leading to premature close()
However, when switching the datasource we encountered the following error in the project:
2014-09-04 12:12:46,069 [] [RMI TCP Connection(3)-127.0.0.1] WARN - Connection com.mysql.jdbc.JDBC4Connection@123dead (HikariPool-0) marked as broken because of SQLSTATE(08003), ErrorCode(0). com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: No operations allowed after statement closed.
Looking this up led to several threads of which most important is https://hibernate.atlassian.net/browse/HHH-8853 which seems to be a Hibernate bug that was fixed in 4.3
To work around this issue we have created a fix in Across, which uses FixedBatchBuilderImpl and FixedNonBatchingBatch classes to fix this, only if the detected version is 4.2.
The workaround was pushed to https://bitbucket.org/beforeach/across-standard-modules/commits/d73294e8bb9424d04812ae1e6f25de883de6f1e6 for the across-hibernate module in 1.0.4-SNAPSHOT.
Note that Upgrading to Hibernate 4.3 might be an issue if you are using JBoss!
Hibernate 4.3 supports JPA 2.1 but is not compatible with JPA 2.0. The latest JBoss wildfly release does not support JPA 2.1.
Several threads have been started: