HHH-17414 Create a UCP connection pool module

This commit is contained in:
sreekarareddy 2023-11-10 20:34:18 +05:30 committed by Christian Beikov
parent 22e5fe06ae
commit 3d2a525eb5
15 changed files with 536 additions and 1 deletions

View File

@ -20,6 +20,8 @@ ext {
'jdbc.user' : 'sa',
'jdbc.pass' : '',
'jdbc.url' : 'jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE',
'jdbc.datasource' : 'org.h2.Driver',
// 'jdbc.datasource' : 'org.h2.jdbcx.JdbcDataSource',
'connection.init_sql' : '',
'hibernate.dialect.native_param_markers' : 'true'
],
@ -29,6 +31,8 @@ ext {
'jdbc.user' : 'sa',
'jdbc.pass' : '',
'jdbc.url' : 'jdbc:hsqldb:mem:test',
'jdbc.datasource' : 'org.hsqldb.jdbc.JDBCDriver',
// 'jdbc.datasource' : 'org.hsqldb.jdbc.JDBCDataSource',
'connection.init_sql' : ''
],
derby : [
@ -37,6 +41,8 @@ ext {
'jdbc.user' : 'hibernate_orm_test',
'jdbc.pass' : 'hibernate_orm_test',
'jdbc.url' : 'jdbc:derby:memory:;databaseName=hibernate_orm_test;create=true',
'jdbc.datasource' : 'org.apache.derby.jdbc.EmbeddedDriver',
// 'jdbc.datasource' : 'org.apache.derby.jdbc.EmbeddedDataSource',
'connection.init_sql' : ''
],
derby_old : [
@ -45,6 +51,8 @@ ext {
'jdbc.user' : 'hibernate_orm_test',
'jdbc.pass' : 'hibernate_orm_test',
'jdbc.url' : 'jdbc:derby:memory:;databaseName=hibernate_orm_test;create=true',
'jdbc.datasource' : 'org.apache.derby.jdbc.EmbeddedDriver',
// 'jdbc.datasource' : 'org.apache.derby.jdbc.EmbeddedDataSource',
'connection.init_sql' : ''
],
pgsql : [
@ -54,6 +62,8 @@ ext {
'jdbc.pass' : 'hibernate_orm_test',
// Disable prepared statement caching due to https://www.postgresql.org/message-id/CAEcMXhmmRd4-%2BNQbnjDT26XNdUoXdmntV9zdr8%3DTu8PL9aVCYg%40mail.gmail.com
'jdbc.url' : 'jdbc:postgresql://' + dbHost + '/hibernate_orm_test?preparedStatementCacheQueries=0&escapeSyntaxCallMode=callIfNoReturn',
'jdbc.datasource' : 'org.postgresql.Driver',
// 'jdbc.datasource' : 'org.postgresql.ds.PGSimpleDataSource',
'connection.init_sql' : ''
],
pgsql_ci : [
@ -63,6 +73,8 @@ ext {
'jdbc.pass' : 'hibernate_orm_test',
// Disable prepared statement caching due to https://www.postgresql.org/message-id/CAEcMXhmmRd4-%2BNQbnjDT26XNdUoXdmntV9zdr8%3DTu8PL9aVCYg%40mail.gmail.com
'jdbc.url' : 'jdbc:postgresql://' + dbHost + '/hibernate_orm_test?preparedStatementCacheQueries=0&escapeSyntaxCallMode=callIfNoReturn',
'jdbc.datasource' : 'org.postgresql.Driver',
// 'jdbc.datasource' : 'org.postgresql.ds.PGSimpleDataSource',
'connection.init_sql' : ''
],
edb_ci : [
@ -72,6 +84,8 @@ ext {
'jdbc.pass' : 'hibernate_orm_test',
// Disable prepared statement caching due to https://www.postgresql.org/message-id/CAEcMXhmmRd4-%2BNQbnjDT26XNdUoXdmntV9zdr8%3DTu8PL9aVCYg%40mail.gmail.com
'jdbc.url' : 'jdbc:postgresql://' + dbHost + '/hibernate_orm_test?preparedStatementCacheQueries=0&escapeSyntaxCallMode=callIfNoReturn',
'jdbc.datasource' : 'org.postgresql.Driver',
// 'jdbc.datasource' : 'org.postgresql.ds.PGSimpleDataSource',
'connection.init_sql' : ''
],
sybase_ci : [
@ -81,6 +95,8 @@ ext {
'jdbc.pass' : 'hibernate_orm_test',
// Disable prepared statement caching to avoid issues with changing schemas
'jdbc.url' : 'jdbc:jtds:sybase://' + dbHost + ':9000/hibernate_orm_test;maxStatements=0;cacheMetaData=false',
'jdbc.datasource' : 'net.sourceforge.jtds.jdbc.Driver',
// 'jdbc.datasource' : 'net.sourceforge.jtds.jdbcx.JtdsDataSource',
'connection.init_sql' : 'set ansinull on'
],
sybase_jconn_ci : [
@ -90,6 +106,8 @@ ext {
'jdbc.pass' : 'hibernate_orm_test',
// Disable prepared statement caching to avoid issues with changing schemas
'jdbc.url' : 'jdbc:sybase:Tds:' + dbHost + ':9000/hibernate_orm_test',
'jdbc.datasource' : 'com.sybase.jdbc4.jdbc.SybDriver',
// 'jdbc.datasource' : 'com.sybase.jdbc4.jdbc.SybDataSource',
'connection.init_sql' : 'set ansinull on set quoted_identifier on'
],
mysql : [
@ -98,6 +116,8 @@ ext {
'jdbc.user' : 'hibernateormtest',
'jdbc.pass' : 'hibernateormtest',
'jdbc.url' : 'jdbc:mysql://' + dbHost + '/hibernate_orm_test',
'jdbc.datasource' : 'com.mysql.jdbc.Driver',
// 'jdbc.datasource' : 'com.mysql.cj.jdbc.MysqlDataSource',
'connection.init_sql' : ''
],
mysql_ci : [
@ -106,6 +126,8 @@ ext {
'jdbc.user' : 'hibernate_orm_test',
'jdbc.pass' : 'hibernate_orm_test',
'jdbc.url' : 'jdbc:mysql://' + dbHost + '/hibernate_orm_test?allowPublicKeyRetrieval=true',
'jdbc.datasource' : 'com.mysql.jdbc.Driver',
// 'jdbc.datasource' : 'com.mysql.cj.jdbc.MysqlDataSource',
'connection.init_sql' : ''
],
mariadb : [
@ -114,6 +136,8 @@ ext {
'jdbc.user' : 'hibernate_orm_test',
'jdbc.pass' : 'hibernate_orm_test',
'jdbc.url' : 'jdbc:mariadb://' + dbHost + '/hibernate_orm_test',
'jdbc.datasource' : 'org.mariadb.jdbc.Driver',
// 'jdbc.datasource' : 'org.mariadb.jdbc.MariaDbDataSource',
'connection.init_sql' : ''
],
mariadb_ci : [
@ -122,6 +146,8 @@ ext {
'jdbc.user' : 'root',
'jdbc.pass' : 'hibernate_orm_test',
'jdbc.url' : 'jdbc:mariadb://' + dbHost + '/hibernate_orm_test',
'jdbc.datasource' : 'org.mariadb.jdbc.Driver',
// 'jdbc.datasource' : 'org.mariadb.jdbc.MariaDbDataSource',
'connection.init_sql' : ''
],
tidb : [
@ -130,6 +156,8 @@ ext {
'jdbc.user' : 'hibernate_orm_test',
'jdbc.pass' : 'hibernate_orm_test',
'jdbc.url' : 'jdbc:mysql://' + dbHost + ':4000/hibernate_orm_test',
'jdbc.datasource' : 'com.mysql.jdbc.Driver',
// 'jdbc.datasource' : 'com.mysql.cj.jdbc.MysqlDataSource',
'connection.init_sql' : ''
],
oracle : [
@ -138,6 +166,8 @@ ext {
'jdbc.user' : 'hibernate_orm_test',
'jdbc.pass' : 'hibernate_orm_test',
'jdbc.url' : 'jdbc:oracle:thin:@' + dbHost + ':1521/xepdb1',
'jdbc.datasource' : 'oracle.jdbc.OracleDriver',
// 'jdbc.datasource' : 'oracle.jdbc.datasource.impl.OracleDataSource',
'connection.init_sql' : ''
],
oracle_ci : [
@ -146,6 +176,8 @@ ext {
'jdbc.user' : 'hibernate_orm_test',
'jdbc.pass' : 'hibernate_orm_test',
'jdbc.url' : 'jdbc:oracle:thin:@' + dbHost + ':1521/freepdb1',
'jdbc.datasource' : 'oracle.jdbc.OracleDriver',
// 'jdbc.datasource' : 'oracle.jdbc.datasource.impl.OracleDataSource',
'connection.init_sql' : ''
],
oracle_xe_ci : [
@ -154,6 +186,8 @@ ext {
'jdbc.user' : 'hibernate_orm_test',
'jdbc.pass' : 'hibernate_orm_test',
'jdbc.url' : 'jdbc:oracle:thin:@' + dbHost + ':1521/xepdb1',
'jdbc.datasource' : 'oracle.jdbc.OracleDriver',
// 'jdbc.datasource' : 'oracle.jdbc.datasource.impl.OracleDataSource',
'connection.init_sql' : ''
],
oracle_legacy_ci : [
@ -163,6 +197,8 @@ ext {
'jdbc.pass' : 'hibernate_orm_test',
// For 11 version that doesn't have any XEPDB1 database service
'jdbc.url' : 'jdbc:oracle:thin:@' + dbHost + ':1521:XE',
'jdbc.datasource' : 'oracle.jdbc.OracleDriver',
// 'jdbc.datasource' : 'oracle.jdbc.datasource.impl.OracleDataSource',
'connection.init_sql' : ''
],
oracle_cloud_autonomous_tls : [
@ -175,6 +211,8 @@ ext {
// To avoid hibernate-spatial tests failure, JVM must be enabled as stated in documentation:
// https://docs.oracle.com/en/cloud/paas/autonomous-database/adbsa/autonomous-oracle-java.html
'jdbc.url' : 'jdbc:oracle:thin:@(description=(retry_count=5)(retry_delay=1)(address=(protocol=tcps)(port=1521)(host=' + dbHost + '.oraclecloud.com))(connect_data=(service_name=' + dbService + '_tp.adb.oraclecloud.com))(security=(ssl_server_dn_match=no)))?oracle.jdbc.enableQueryResultCache=false&oracle.jdbc.thinForceDNSLoadBalancing=true&tcp.nodelay=yes',
'jdbc.datasource' : 'oracle.jdbc.OracleDriver',
// 'jdbc.datasource' : 'oracle.jdbc.datasource.impl.OracleDataSource',
'connection.init_sql' : ''
],
oracle_cloud_db19c : [
@ -187,6 +225,8 @@ ext {
// To avoid hibernate-spatial tests failure, JVM must be enabled as stated in documentation:
// https://docs.oracle.com/en/cloud/paas/autonomous-database/adbsa/autonomous-oracle-java.html
'jdbc.url' : 'jdbc:oracle:thin:@' + dbHost + ':1521/' + dbService,
'jdbc.datasource' : 'oracle.jdbc.OracleDriver',
// 'jdbc.datasource' : 'oracle.jdbc.datasource.impl.OracleDataSource',
'connection.init_sql' : ''
],
oracle_cloud_db21c : [
@ -199,6 +239,8 @@ ext {
// To avoid hibernate-spatial tests failure, JVM must be enabled as stated in documentation:
// https://docs.oracle.com/en/cloud/paas/autonomous-database/adbsa/autonomous-oracle-java.html
'jdbc.url' : 'jdbc:oracle:thin:@' + dbHost + ':1521/' + dbService,
'jdbc.datasource' : 'oracle.jdbc.OracleDriver',
// 'jdbc.datasource' : 'oracle.jdbc.datasource.impl.OracleDataSource',
'connection.init_sql' : ''
],
oracle_cloud_db23c : [
@ -211,6 +253,8 @@ ext {
// To avoid hibernate-spatial tests failure, JVM must be enabled as stated in documentation:
// https://docs.oracle.com/en/cloud/paas/autonomous-database/adbsa/autonomous-oracle-java.html
'jdbc.url' : 'jdbc:oracle:thin:@' + dbHost + ':1521/' + dbService,
'jdbc.datasource' : 'oracle.jdbc.OracleDriver',
// 'jdbc.datasource' : 'oracle.jdbc.datasource.impl.OracleDataSource',
'connection.init_sql' : ''
],
mssql : [
@ -219,6 +263,8 @@ ext {
'jdbc.user' : 'hibernate_orm_test',
'jdbc.pass' : 'hibernate_orm_test',
'jdbc.url' : 'jdbc:sqlserver://' + dbHost + ';instance=SQLEXPRESS;databaseName=hibernate_orm_test;trustServerCertificate=true',
'jdbc.datasource' : 'com.microsoft.sqlserver.jdbc.SQLServerDriver',
// 'jdbc.datasource' : 'com.microsoft.sqlserver.jdbc.SQLServerDataSource',
'connection.init_sql' : ''
],
mssql_ci : [
@ -227,6 +273,8 @@ ext {
'jdbc.user' : 'sa',
'jdbc.pass' : 'Hibernate_orm_test',
'jdbc.url' : 'jdbc:sqlserver://' + dbHost + ';databaseName=hibernate_orm_test;sendTimeAsDatetime=false;trustServerCertificate=true',
'jdbc.datasource' : 'com.microsoft.sqlserver.jdbc.SQLServerDriver',
// 'jdbc.datasource' : 'com.microsoft.sqlserver.jdbc.SQLServerDataSource',
'connection.init_sql' : ''
],
informix : [
@ -235,6 +283,8 @@ ext {
'jdbc.user' : 'informix',
'jdbc.pass' : 'in4mix',
'jdbc.url' : 'jdbc:informix-sqli://' + dbHost + ':9088/sysuser:INFORMIXSERVER=dev;user=informix;password=in4mix',
'jdbc.datasource' : 'com.informix.jdbc.IfxDriver',
// 'jdbc.datasource' : 'com.informix.jdbcx.IfxDataSource',
'connection.init_sql' : ''
],
db2 : [
@ -243,6 +293,8 @@ ext {
'jdbc.user' : 'db2inst1',
'jdbc.pass' : 'db2inst1-pwd',
'jdbc.url' : 'jdbc:db2://' + dbHost + ':50000/orm_test',
'jdbc.datasource' : 'com.ibm.db2.jcc.DB2Driver',
// 'jdbc.datasource' : 'com.ibm.db2.jcc.DB2SimpleDataSource',
'connection.init_sql' : ''
],
db2_ci : [
@ -251,6 +303,8 @@ ext {
'jdbc.user' : 'orm_test',
'jdbc.pass' : 'orm_test',
'jdbc.url' : 'jdbc:db2://' + dbHost + ':50000/orm_test',
'jdbc.datasource' : 'com.ibm.db2.jcc.DB2Driver',
// 'jdbc.datasource' : 'com.ibm.db2.jcc.DB2SimpleDataSource',
'connection.init_sql' : ''
],
hana_cloud : [
@ -260,6 +314,8 @@ ext {
'jdbc.pass' : 'H1bernate_test',
// Disable prepared statement caching due to https://help.sap.com/viewer/0eec0d68141541d1b07893a39944924e/2.0.04/en-US/78f2163887814223858e4369d18e2847.html
'jdbc.url' : 'jdbc:sap://' + dbHost + ':443/?encrypt=true&validateCertificate=false&statementCacheSize=0',
'jdbc.datasource' : 'com.sap.db.jdbc.Driver',
// 'jdbc.datasource' : 'com.sap.db.jdbcext.HanaDataSource',
'connection.init_sql' : ''
],
hana_ci : [
@ -269,6 +325,8 @@ ext {
'jdbc.pass' : 'H1bernate_test',
// Disable prepared statement caching due to https://help.sap.com/viewer/0eec0d68141541d1b07893a39944924e/2.0.04/en-US/78f2163887814223858e4369d18e2847.html
'jdbc.url' : 'jdbc:sap://' + dbHost + ':39017/?statementCacheSize=0',
'jdbc.datasource' : 'com.sap.db.jdbc.Driver',
// 'jdbc.datasource' : 'com.sap.db.jdbcext.HanaDataSource',
'connection.init_sql' : ''
],
cockroachdb : [
@ -279,6 +337,8 @@ ext {
'jdbc.pass' : '',
// Disable prepared statement caching due to https://www.postgresql.org/message-id/CAEcMXhmmRd4-%2BNQbnjDT26XNdUoXdmntV9zdr8%3DTu8PL9aVCYg%40mail.gmail.com
'jdbc.url' : 'jdbc:postgresql://' + dbHost + ':26257/defaultdb?sslmode=disable&preparedStatementCacheQueries=0&escapeSyntaxCallMode=callIfNoReturn',
'jdbc.datasource' : 'org.postgresql.Driver',
// 'jdbc.datasource' : 'org.postgresql.ds.PGSimpleDataSource',
'connection.init_sql' : ''
],
firebird : [
@ -290,6 +350,8 @@ ext {
// Expects alias 'hibernate_orm_test' in aliases.conf (FB2.5 and earlier) or databases.conf (FB3.0 and later)
// Created database must either use default character set NONE, or UTF8 with page size 16384 or higher (to prevent issues with indexes due to keysize)
'jdbc.url' : 'jdbc:firebirdsql://' + dbHost +'/hibernate_orm_test?charSet=utf-8;TRANSACTION_READ_COMMITTED=read_committed,rec_version,wait,lock_timeout=5',
'jdbc.datasource' : 'org.firebirdsql.jdbc.FBDriver',
// 'jdbc.datasource' : 'org.firebirdsql.jdbc.FBDataSource',
'connection.init_sql' : ''
],
altibase : [
@ -298,7 +360,8 @@ ext {
'jdbc.user' : 'sys',
'jdbc.pass' : 'manager',
'connection.init_sql' : '',
'jdbc.url' : 'jdbc:Altibase://' + dbHost + ':20300/mydb?force_clob_bind=true'
'jdbc.url' : 'jdbc:Altibase://' + dbHost + ':20300/mydb?force_clob_bind=true',
'jdbc.datasource' : 'Altibase.jdbc.driver.AltibaseDriver'
],
]
}

View File

@ -95,6 +95,7 @@ dependencies {
//Databases
testRuntimeOnly dbLibs.h2
testRuntimeOnly dbLibs.derby
testRuntimeOnly dbLibs.derbyTools
testRuntimeOnly dbLibs.hsqldb
testRuntimeOnly dbLibs.postgresql
testRuntimeOnly dbLibs.mssql

View File

@ -152,6 +152,7 @@ task copyBundleResourcesXml (type: Copy) {
'jdbc.user' : dbBundle[db]['jdbc.user'].replace("&", "&"),
'jdbc.pass' : dbBundle[db]['jdbc.pass'].replace("&", "&"),
'jdbc.url' : dbBundle[db]['jdbc.url'].replace("&", "&"),
'jdbc.datasource' : dbBundle[db]['jdbc.datasource'].replace("&", "&"),
'connection.init_sql' : dbBundle[db]['connection.init_sql'].replace("&", "&")
]
ext.bundleTokens['buildDirName'] = project.relativePath( buildDir )

View File

@ -67,6 +67,11 @@ public class ConnectionProviderInitiator implements StandardServiceInitiator<Con
*/
public static final String VIBUR_STRATEGY = "vibur";
/**
* The strategy for oracle ucp connection pooling
*/
public static final String UCP_STRATEGY = "ucp";
/**
* The strategy for agroal connection pooling
*/
@ -187,6 +192,12 @@ public class ConnectionProviderInitiator implements StandardServiceInitiator<Con
}
}
if ( connectionProvider == null ) {
if ( oracleUCPConfigDefined( configurationValues ) ) {
connectionProvider = instantiateUCPProvider( strategySelector );
}
}
if ( connectionProvider == null ) {
if ( agroalConfigDefined( configurationValues ) ) {
connectionProvider = instantiateAgroalProvider( strategySelector );
@ -343,6 +354,25 @@ public class ConnectionProviderInitiator implements StandardServiceInitiator<Con
}
}
private boolean oracleUCPConfigDefined(Map<String, Object> configValues) {
for ( String key : configValues.keySet() ) {
if ( key.startsWith( "hibernate.oracleucp." ) ) {
return true;
}
}
return false;
}
private ConnectionProvider instantiateUCPProvider(StrategySelector strategySelector) {
try {
return strategySelector.selectStrategyImplementor( ConnectionProvider.class, UCP_STRATEGY ).newInstance();
}
catch ( Exception e ) {
LOG.ucpProviderClassNotFound();
return null;
}
}
/**
* Build the connection properties capable of being passed to
* {@link java.sql.DriverManager#getConnection(String, Properties)} forms taking {@link Properties} argument.

View File

@ -1866,4 +1866,8 @@ public interface CoreMessageLogger extends BasicLogger {
id = 516)
void enhancementDiscoveryFailed(String className, @Cause Throwable cause);
@LogMessage(level = WARN)
@Message(value = "UCP properties were encountered, but the UCP ConnectionProvider was not found on the classpath; these properties are going to be ignored.",
id = 517)
void ucpProviderClassNotFound();
}

View File

@ -0,0 +1,18 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
description = 'Integration for Oracle UCP into Hibernate O/RM'
apply from: rootProject.file( 'gradle/published-java-module.gradle' )
dependencies {
implementation project( ':hibernate-core' )
implementation libs.ucp
implementation libs.ojdbc11
testImplementation project( ':hibernate-testing' )
}

View File

@ -0,0 +1,40 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.oracleucp.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 UCPCPConnectionProvider} to the
* {@link org.hibernate.boot.registry.selector.spi.StrategySelector} service.
*
*/
public class StrategyRegistrationProviderImpl implements StrategyRegistrationProvider {
private static final List<StrategyRegistration> REGISTRATIONS = Collections.singletonList(
(StrategyRegistration) new SimpleStrategyRegistrationImpl<ConnectionProvider>(
ConnectionProvider.class,
UCPConnectionProvider.class,
"ucp",
"oracleucp",
UCPConnectionProvider.class.getSimpleName(),
"org.oracle.ucp.connection.UCPConnectionProvider"
)
);
@Override
@SuppressWarnings("unchecked")
public Iterable<StrategyRegistration> getStrategyRegistrations() {
return REGISTRATIONS;
}
}

View File

@ -0,0 +1,225 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.oracleucp.internal;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import javax.sql.DataSource;
import org.hibernate.HibernateException;
import org.hibernate.engine.jdbc.connections.internal.ConnectionProviderInitiator;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.internal.util.config.ConfigurationHelper;
import org.hibernate.service.UnknownUnwrapTypeException;
import org.hibernate.service.spi.Configurable;
import org.hibernate.service.spi.Stoppable;
import org.jboss.logging.Logger;
import oracle.ucp.UniversalConnectionPoolAdapter;
import oracle.ucp.UniversalConnectionPoolException;
import oracle.ucp.admin.UniversalConnectionPoolManager;
import oracle.ucp.admin.UniversalConnectionPoolManagerImpl;
import oracle.ucp.jdbc.PoolDataSource;
import oracle.ucp.jdbc.PoolDataSourceFactory;
import org.hibernate.cfg.AvailableSettings;
public class UCPConnectionProvider implements ConnectionProvider, Configurable, Stoppable {
private static final long serialVersionUID = 1L;
private static final Logger LOGGER = Logger.getLogger( "UCPConnectionProvider.class" );
private PoolDataSource ucpDS = null;
private UniversalConnectionPoolManager poolManager = null;
private static final String CONFIG_PREFIX = "hibernate.oracleucp.";
private boolean autoCommit;
private Integer isolation;
@SuppressWarnings("rawtypes")
@Override
public void configure(Map props) throws HibernateException {
try {
LOGGER.trace( "Configuring oracle UCP" );
isolation = ConnectionProviderInitiator.extractIsolation( props );
autoCommit = ConfigurationHelper.getBoolean( AvailableSettings.AUTOCOMMIT, props );
UniversalConnectionPoolManager poolManager = UniversalConnectionPoolManagerImpl.
getUniversalConnectionPoolManager();
ucpDS = PoolDataSourceFactory.getPoolDataSource();
Properties ucpProps = getConfiguration(props);
configureDataSource(ucpDS, ucpProps);
}
catch (Exception e) {
LOGGER.debug( "oracle UCP Configuration failed" );
throw new HibernateException( e );
}
LOGGER.trace( "oracle UCP Configured" );
}
private void configureDataSource(PoolDataSource ucpDS, Properties ucpProps) {
List<Method> methods = Arrays.asList(PoolDataSource.class.getDeclaredMethods());
for(String propName : ucpProps.stringPropertyNames()) {
String value = ucpProps.getProperty(propName);
final String methodName = "set" + propName.substring(0, 1).toUpperCase(Locale.ENGLISH) + propName.substring(1);
Method writeMethod = methods.stream().filter(m -> m.getName().equals(methodName) && m.getParameterCount() == 1).findFirst().orElse(null);
if (writeMethod == null) {
throw new RuntimeException("Property " + propName + " does not exist on target " + PoolDataSource.class);
}
try {
Class<?> paramClass = writeMethod.getParameterTypes()[0];
if (paramClass == int.class) {
writeMethod.invoke(ucpDS, Integer.parseInt(value.toString()));
}
else if (paramClass == long.class) {
writeMethod.invoke(ucpDS, Long.parseLong(value.toString()));
}
else if (paramClass == boolean.class || paramClass == Boolean.class) {
writeMethod.invoke(ucpDS, Boolean.parseBoolean(value.toString()));
}
else if (paramClass == String.class) {
writeMethod.invoke(ucpDS, value.toString());
}
else {
if(propName.equals("connectionProperties") ||
propName.equals("connectionFactoryProperties")) {
if (value != null) {
Properties connProps = new Properties();
// The Properties string is in the following format:
// {prop1=val1, prop2=val2, ..., propN=valN}
String[] propStrs = value.substring(1, value.length() - 1).split(", ");
for (String onePropStr : propStrs) {
// Separate the name and value strings for each property
String[] nvPair = onePropStr.split("=");
connProps.setProperty(nvPair[0], nvPair[1]);
}
writeMethod.invoke(ucpDS, connProps);
}
}
else {
writeMethod.invoke(ucpDS, value);
}
}
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
}
private Properties getConfiguration(Map<?,?> props) {
Properties ucpProps = new Properties();
copyProperty( AvailableSettings.URL, props, "URL", ucpProps );
copyProperty( AvailableSettings.USER, props, "user", ucpProps );
copyProperty( AvailableSettings.PASS, props, "password", ucpProps );
for ( Object keyo : props.keySet() ) {
if ( !(keyo instanceof String) ) {
continue;
}
String key = (String) keyo;
if ( key.startsWith( CONFIG_PREFIX ) ) {
ucpProps.setProperty( key.substring( CONFIG_PREFIX.length() ), (String) props.get( key ) );
}
}
return ucpProps;
}
@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 ) );
}
}
// *************************************************************************
// ConnectionProvider
// *************************************************************************
@Override
public Connection getConnection() throws SQLException {
Connection conn = null;
if ( ucpDS != null ) {
conn = ucpDS.getConnection();
if ( isolation != null && isolation != conn.getTransactionIsolation()) {
conn.setTransactionIsolation( isolation );
}
if ( conn.getAutoCommit() != autoCommit ) {
conn.setAutoCommit( autoCommit );
}
}
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 )
|| UCPConnectionProvider.class.isAssignableFrom( unwrapType )
|| DataSource.class.isAssignableFrom( unwrapType );
}
@Override
@SuppressWarnings("unchecked")
public <T> T unwrap(Class<T> unwrapType) {
if ( ConnectionProvider.class.equals( unwrapType ) ||
UCPConnectionProvider.class.isAssignableFrom( unwrapType ) ) {
return (T) this;
}
else if ( DataSource.class.isAssignableFrom( unwrapType ) ) {
return (T) ucpDS;
}
else {
throw new UnknownUnwrapTypeException( unwrapType );
}
}
@Override
public void stop() {
if(this.ucpDS!=null && ucpDS.getConnectionPoolName() != null) {
try {
UniversalConnectionPoolManager poolManager = UniversalConnectionPoolManagerImpl.
getUniversalConnectionPoolManager();
poolManager.destroyConnectionPool(ucpDS.getConnectionPoolName());
}
catch (UniversalConnectionPoolException e) {
LOGGER.debug("Unable to destroy UCP connection pool");
}
}
}
}

View File

@ -0,0 +1,11 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
/**
* Implementation of ConnectionProvider using UCP.
*/
package org.hibernate.ucp.internal;

View File

@ -0,0 +1,14 @@
#
# Hibernate, Relational Persistence for Idiomatic Java
#
# License: GNU Lesser General Public License (LGPL), version 2.1 or later.
# See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
#
#
# Hibernate, Relational Persistence for Idiomatic Java
#
# License: GNU Lesser General Public License (LGPL), version 2.1 or later.
# See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
#
org.hibernate.oracleucp.internal.StrategyRegistrationProviderImpl

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Hibernate, Relational Persistence for Idiomatic Java
~
~ License: GNU Lesser General Public License (LGPL), version 2.1 or later.
~ See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
-->
<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.oracleucp.internal.StrategyRegistrationProviderImpl"/>
<service ref="strategyRegistrationProvider" interface="org.hibernate.boot.registry.selector.StrategyRegistrationProvider"/>
</blueprint>

View File

@ -0,0 +1,75 @@
package org.hibernate.test.ucp;
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.dialect.SybaseDialect;
import org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.ConnectionProviderJdbcConnectionAccess;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.oracleucp.internal.UCPConnectionProvider;
import org.hibernate.testing.orm.junit.SkipForDialect;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Test;
import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@SkipForDialect(dialectClass = SybaseDialect.class, matchSubTypes = true, reason = "The jTDS driver doesn't implement Connection#isValid so this fails")
public class UCPConnectionProviderTest extends BaseCoreFunctionalTestCase {
@Test
public void testUCPConnectionProvider() throws Exception {
JdbcServices jdbcServices = serviceRegistry().getService( JdbcServices.class );
ConnectionProviderJdbcConnectionAccess connectionAccess = assertTyping(
ConnectionProviderJdbcConnectionAccess.class,
jdbcServices.getBootstrapJdbcConnectionAccess()
);
assertTyping( UCPConnectionProvider.class, connectionAccess.getConnectionProvider() );
UCPConnectionProvider ucpProvider = (UCPConnectionProvider) connectionAccess.getConnectionProvider();
final List<Connection> conns = new ArrayList<Connection>();
for ( int i = 0; i < 2; i++ ) {
Connection conn = ucpProvider.getConnection();
assertNotNull( conn );
assertFalse( conn.isClosed() );
conns.add( conn );
}
try {
ucpProvider.getConnection();
fail( "SQLException expected -- no more connections should have been available in the pool." );
}
catch (SQLException e) {
// expected
assertTrue( e.getMessage().contains( "Failed to get a connection" ) );
}
for ( Connection conn : conns ) {
ucpProvider.closeConnection( conn );
assertTrue( conn.isClosed() );
}
releaseSessionFactory();
try {
ucpProvider.getConnection();
fail( "Exception expected -- the pool should have been shutdown." );
}
catch (Exception e) {
// expected
assertTrue( e.getMessage().contains( "Failed to get a connection" ) );
}
}
}

View File

@ -0,0 +1,17 @@
package org.hibernate.test.ucp;
import org.hibernate.dialect.SybaseDialect;
import org.hibernate.dialect.TiDBDialect;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.oracleucp.internal.UCPConnectionProvider;
import org.hibernate.testing.common.connections.BaseTransactionIsolationConfigTest;
import org.hibernate.testing.orm.junit.SkipForDialect;
@SkipForDialect(dialectClass = SybaseDialect.class, matchSubTypes = true, reason = "The jTDS driver doesn't implement Connection#getNetworkTimeout() so this fails")
@SkipForDialect(dialectClass = TiDBDialect.class, matchSubTypes = true, reason = "Doesn't support SERIALIZABLE isolation")
public class UCPTransactionIsolationConfigTest extends BaseTransactionIsolationConfigTest{
@Override
protected ConnectionProvider getConnectionProviderUnderTest() {
return new UCPConnectionProvider();
}
}

View File

@ -0,0 +1,12 @@
hibernate.dialect @db.dialect@
hibernate.connection.driver_class @jdbc.driver@
hibernate.connection.url @jdbc.url@
hibernate.connection.username @jdbc.user@
hibernate.connection.password @jdbc.pass@
hibernate.connection.init_sql @connection.init_sql@
hibernate.connection.provider_class=UCPConnectionProvider
hibernate.oracleucp.connectionFactoryClassName=@jdbc.datasource@
hibernate.oracleucp.minPoolSize=0
hibernate.oracleucp.maxPoolSize=2
hibernate.oracleucp.connectionPoolName=TestUCPPool

View File

@ -79,6 +79,7 @@ dependencyResolutionManagement {
def hikaricpVersion = version "hikaricp", "3.2.0"
def proxoolVersion = version "proxool", "0.8.3"
def viburVersion = version "vibur", "25.0"
def ucpVersion = version "ucp", "23.3.0.23.09"
def jcacheVersion = version "jcache", "1.0.0"
def ehcache3Version = version "ehcache3", "3.10.8"
@ -117,6 +118,10 @@ dependencyResolutionManagement {
library( "vibur", "org.vibur", "vibur-dbcp" ).versionRef( viburVersion )
library( "ucp", "com.oracle.database.jdbc", "ucp11" ).versionRef( ucpVersion )
library( "ojdbc11", "com.oracle.database.jdbc", "ojdbc11" ).versionRef( ucpVersion )
library( "geolatte", "org.geolatte", "geolatte-geom" ).versionRef( geolatteVersion )
library( "jcache", "javax.cache", "cache-api" ).versionRef( jcacheVersion )
@ -236,6 +241,7 @@ dependencyResolutionManagement {
library( "h2gis", "org.orbisgis", "h2gis" ).versionRef( h2gisVersion )
library( "hsqldb", "org.hsqldb", "hsqldb" ).versionRef( hsqldbVersion )
library( "derby", "org.apache.derby", "derby" ).versionRef( derbyVersion )
library( "derbyTools", "org.apache.derby", "derbytools" ).versionRef( derbyVersion )
library( "postgresql", "org.postgresql", "postgresql" ).versionRef( pgsqlVersion )
library( "cockroachdb", "org.postgresql", "postgresql" ).versionRef( pgsqlVersion )
library( "mysql", "com.mysql", "mysql-connector-j" ).versionRef( mysqlVersion )
@ -311,6 +317,7 @@ include 'hibernate-proxool'
include 'hibernate-hikaricp'
include 'hibernate-vibur'
include 'hibernate-agroal'
include 'hibernate-ucp'
include 'hibernate-jcache'