HHH-8869 created hibernate-hikaricp connection provider

Conflicts:
	libraries.gradle
This commit is contained in:
Brett Meyer 2014-03-17 16:33:44 -04:00
parent f6399cd159
commit e8a52e2904
11 changed files with 434 additions and 1 deletions

View File

@ -0,0 +1,17 @@
dependencies {
compile project( ':hibernate-core' )
compile( libraries.hikaricp )
testCompile project( ':hibernate-testing' )
}
def pomName() {
return 'Hibernate/HikariCP Integration'
}
def pomDescription() {
return 'Integration for HikariCP into Hibernate O/RM'
}
def osgiDescription() {
return pomDescription()
}

View File

@ -0,0 +1,131 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* JBoss, Home of Professional Open Source
* Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors
* as indicated by the @authors tag. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package org.hibernate.hikaricp.internal;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Map;
import org.hibernate.HibernateException;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.service.UnknownUnwrapTypeException;
import org.hibernate.service.spi.Configurable;
import org.hibernate.service.spi.Stoppable;
import org.jboss.logging.Logger;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
/**
* HikariCP Connection provider for Hibernate.
*
* @author Brett Wooldridge
* @author Luca Burgazzoli
*/
public class HikariCPConnectionProvider implements ConnectionProvider, Configurable, Stoppable {
private static final long serialVersionUID = -9131625057941275711L;
private static final Logger LOGGER = Logger.getLogger( HikariCPConnectionProvider.class );
/**
* HikariCP configuration.
*/
private HikariConfig hcfg = null;
/**
* HikariCP data source.
*/
private HikariDataSource hds = null;
// *************************************************************************
// Configurable
// *************************************************************************
@SuppressWarnings("rawtypes")
@Override
public void configure(Map props) throws HibernateException {
try {
LOGGER.debug( "Configuring HikariCP" );
hcfg = HikariConfigurationUtil.loadConfiguration( props );
hds = new HikariDataSource( hcfg );
}
catch (Exception e) {
throw new HibernateException( e );
}
LOGGER.debug( "HikariCP Configured" );
}
// *************************************************************************
// ConnectionProvider
// *************************************************************************
@Override
public Connection getConnection() throws SQLException {
Connection conn = null;
if ( hds != null ) {
conn = hds.getConnection();
}
return conn;
}
@Override
public void closeConnection(Connection conn) throws SQLException {
conn.close();
}
@Override
public boolean supportsAggressiveRelease() {
return false;
}
@Override
@SuppressWarnings("rawtypes")
public boolean isUnwrappableAs(Class unwrapType) {
return ConnectionProvider.class.equals( unwrapType )
|| HikariCPConnectionProvider.class.isAssignableFrom( unwrapType );
}
@Override
@SuppressWarnings("unchecked")
public <T> T unwrap(Class<T> unwrapType) {
if ( isUnwrappableAs( unwrapType ) ) {
return (T) this;
}
else {
throw new UnknownUnwrapTypeException( unwrapType );
}
}
// *************************************************************************
// Stoppable
// *************************************************************************
@Override
public void stop() {
hds.shutdown();
}
}

View File

@ -0,0 +1,84 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* JBoss, Home of Professional Open Source
* Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors
* as indicated by the @authors tag. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package org.hibernate.hikaricp.internal;
import java.util.Map;
import java.util.Properties;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.dialect.H2Dialect;
import com.zaxxer.hikari.HikariConfig;
/**
* Utility class to map Hibernate properties to HikariCP configuration properties.
*
* @author Brett Wooldridge
* @author Luca Burgazzoli
* @author Brett Meyer
*/
public class HikariConfigurationUtil {
public static final String CONFIG_PREFIX = "hibernate.hikari.";
/**
* Create/load a HikariConfig from Hibernate properties.
*
* @param props a map of Hibernate properties
* @return a HikariConfig
*/
@SuppressWarnings("rawtypes")
public static HikariConfig loadConfiguration(Map props) {
Properties hikariProps = new Properties();
copyProperty( AvailableSettings.ISOLATION, props, "transactionIsolation", hikariProps );
copyProperty( AvailableSettings.AUTOCOMMIT, props, "autoCommit", hikariProps );
if (props.containsKey( AvailableSettings.DIALECT )
&& props.get( AvailableSettings.DIALECT ).equals( H2Dialect.class.getName() )) {
// Terrible workaround for an issue with H2. The version of H2 we currently use does not include the
// standard DataSource#setUrl, but instead uses setURL. HikariCP's PropertyBeanSetter uses reflection and
// fails without this.
copyProperty( AvailableSettings.URL, props, "dataSource.URL", hikariProps );
}
else {
copyProperty( AvailableSettings.URL, props, "dataSource.url", hikariProps );
}
copyProperty( AvailableSettings.USER, props, "dataSource.user", hikariProps );
copyProperty( AvailableSettings.PASS, props, "dataSource.password", hikariProps );
for ( Object keyo : props.keySet() ) {
String key = (String) keyo;
if ( key.startsWith( CONFIG_PREFIX ) ) {
hikariProps.setProperty( key.substring( CONFIG_PREFIX.length() ), (String) props.get( key ) );
}
}
return new HikariConfig( hikariProps );
}
@SuppressWarnings("rawtypes")
private static void copyProperty(String srcKey, Map src, String dstKey, Properties dst) {
if ( src.containsKey( srcKey ) ) {
dst.setProperty( dstKey, (String) src.get( srcKey ) );
}
}
}

View File

@ -0,0 +1,58 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.hikaricp.internal;
import java.util.Collections;
import java.util.List;
import org.hibernate.boot.registry.selector.SimpleStrategyRegistrationImpl;
import org.hibernate.boot.registry.selector.StrategyRegistration;
import org.hibernate.boot.registry.selector.StrategyRegistrationProvider;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
/**
* Provides the {@link HikariCPConnectionProvider} to the
* {@link org.hibernate.boot.registry.selector.spi.StrategySelector} service.
*
* @author Brett Meyer
*/
public class StrategyRegistrationProviderImpl implements StrategyRegistrationProvider {
private static final List<StrategyRegistration> REGISTRATIONS = Collections.singletonList(
(StrategyRegistration) new SimpleStrategyRegistrationImpl<ConnectionProvider>(
ConnectionProvider.class,
HikariCPConnectionProvider.class,
"hikari",
"hikaricp",
HikariCPConnectionProvider.class.getSimpleName(),
// for consistency's sake
"org.hibernate.connection.HikariCPConnectionProvider"
)
);
@Override
@SuppressWarnings("unchecked")
public Iterable<StrategyRegistration> getStrategyRegistrations() {
return REGISTRATIONS;
}
}

View File

@ -0,0 +1,4 @@
/**
* Implementation of ConnectionProvider using HikariCP.
*/
package org.hibernate.hikaricp.internal;

View File

@ -0,0 +1 @@
org.hibernate.hikaricp.internal.StrategyRegistrationProviderImpl

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<blueprint default-activation="eager"
xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<bean id="strategyRegistrationProvider" class="org.hibernate.hikaricp.internal.StrategyRegistrationProviderImpl"/>
<service ref="strategyRegistrationProvider" interface="org.hibernate.boot.registry.selector.StrategyRegistrationProvider"/>
</blueprint>

View File

@ -0,0 +1,90 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2010, Red Hat, Inc. and/or its affiliates or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat, Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.test.hikaricp;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.hikaricp.internal.HikariCPConnectionProvider;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Test;
/**
* @author Brett Meyer
*/
public class HikariCPConnectionProviderTest extends BaseCoreFunctionalTestCase {
@Test
public void testHikariCPConnectionProvider() throws Exception {
JdbcServices jdbcServices = serviceRegistry().getService( JdbcServices.class );
ConnectionProvider provider = jdbcServices.getConnectionProvider();
assertTrue( provider instanceof HikariCPConnectionProvider );
HikariCPConnectionProvider hikariCP = (HikariCPConnectionProvider) provider;
// For simplicity's sake, using the following in hibernate.properties:
// hibernate.hikari.minimumPoolSize 2
// hibernate.hikari.maximumPoolSize 2
final List<Connection> conns = new ArrayList<Connection>();
for ( int i = 0; i < 2; i++ ) {
Connection conn = hikariCP.getConnection();
assertNotNull( conn );
assertFalse( conn.isClosed() );
conns.add( conn );
}
try {
hikariCP.getConnection();
fail( "SQLException expected -- no more connections should have been available in the pool." );
}
catch (SQLException e) {
// expected
assertTrue( e.getMessage().contains( "Timeout" ) );
}
for ( Connection conn : conns ) {
hikariCP.closeConnection( conn );
assertTrue( conn.isClosed() );
}
releaseSessionFactory();
try {
hikariCP.getConnection();
fail( "Exception expected -- the pool should have been shutdown." );
}
catch (Exception e) {
// expected
assertTrue( e.getMessage().contains( "shutdown" ) );
}
}
}

View File

@ -0,0 +1,37 @@
#
# Hibernate, Relational Persistence for Idiomatic Java
#
# Copyright (c) 2010, Red Hat Inc. or third-party contributors as
# indicated by the @author tags or express copyright attribution
# statements applied by the authors. All third-party contributions are
# distributed under license by Red Hat Inc.
#
# This copyrighted material is made available to anyone wishing to use, modify,
# copy, or redistribute it subject to the terms and conditions of the GNU
# Lesser General Public License, as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
# for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this distribution; if not, write to:
# Free Software Foundation, Inc.
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301 USA
#
hibernate.dialect org.hibernate.dialect.H2Dialect
hibernate.connection.driver_class org.h2.Driver
hibernate.connection.url jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;MVCC=TRUE
hibernate.connection.username sa
hibernate.jdbc.batch_size 10
hibernate.connection.provider_class HikariCPConnectionProvider
hibernate.hikari.dataSourceClassName org.h2.jdbcx.JdbcDataSource
hibernate.hikari.poolName testPool
# Purposefully low and simplisitic.
hibernate.hikari.minimumPoolSize 2
hibernate.hikari.maximumPoolSize 2
hibernate.hikari.idleTimeout 3000

View File

@ -108,10 +108,10 @@ ext {
jnp_client: "org.jboss.naming:jnp-client:${jnpVersion}", jnp_client: "org.jboss.naming:jnp-client:${jnpVersion}",
jnp_server: "org.jboss.naming:jnpserver:${jnpVersion}", jnp_server: "org.jboss.naming:jnpserver:${jnpVersion}",
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ c3p0
c3p0: "com.mchange:c3p0:0.9.2.1", c3p0: "com.mchange:c3p0:0.9.2.1",
ehcache: "net.sf.ehcache:ehcache-core:2.4.3", ehcache: "net.sf.ehcache:ehcache-core:2.4.3",
proxool: "proxool:proxool:0.8.3" proxool: "proxool:proxool:0.8.3"
hikaricp: "com.zaxxer:HikariCP:1.3.0"
] ]
} }

View File

@ -7,6 +7,7 @@ include 'hibernate-osgi'
include 'hibernate-c3p0' include 'hibernate-c3p0'
include 'hibernate-proxool' include 'hibernate-proxool'
include 'hibernate-hikaricp'
include 'hibernate-ehcache' include 'hibernate-ehcache'
include 'hibernate-infinispan' include 'hibernate-infinispan'