From bcac1e32996a8b27aa7b4e892b9e596674c48135 Mon Sep 17 00:00:00 2001 From: Jan Schatteman Date: Mon, 7 Oct 2024 22:59:34 +0200 Subject: [PATCH] HHH-18669 - resolve the driver name from the connection metadata, in case it wasn't explicitly set and access to the database metadata is allowed Signed-off-by: Jan Schatteman --- .../internal/AgroalConnectionProvider.java | 25 ++++++++++++++++-- .../internal/JdbcEnvironmentInitiator.java | 2 +- .../internal/HikariCPConnectionProvider.java | 26 +++++++++++++++++-- .../internal/ViburDBCPConnectionProvider.java | 23 +++++++++++++++- 4 files changed, 70 insertions(+), 6 deletions(-) diff --git a/hibernate-agroal/src/main/java/org/hibernate/agroal/internal/AgroalConnectionProvider.java b/hibernate-agroal/src/main/java/org/hibernate/agroal/internal/AgroalConnectionProvider.java index 0fd403b12b..092eaa8d77 100644 --- a/hibernate-agroal/src/main/java/org/hibernate/agroal/internal/AgroalConnectionProvider.java +++ b/hibernate-agroal/src/main/java/org/hibernate/agroal/internal/AgroalConnectionProvider.java @@ -6,10 +6,11 @@ package org.hibernate.agroal.internal; import java.sql.Connection; import java.sql.SQLException; +import java.sql.DatabaseMetaData; +import javax.sql.DataSource; import java.util.Map; import java.util.function.Consumer; import java.util.function.Function; -import javax.sql.DataSource; import org.hibernate.HibernateException; import org.hibernate.cfg.AgroalSettings; @@ -33,6 +34,7 @@ import io.agroal.api.security.NamePrincipal; import io.agroal.api.security.SimplePassword; import static org.hibernate.cfg.AgroalSettings.AGROAL_CONFIG_PREFIX; +import static org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.allowJdbcMetadataAccess; /** * ConnectionProvider based on Agroal connection pool @@ -61,6 +63,7 @@ public class AgroalConnectionProvider implements ConnectionProvider, Configurabl public static final String CONFIG_PREFIX = AGROAL_CONFIG_PREFIX + "."; private static final long serialVersionUID = 1L; private AgroalDataSource agroalDataSource = null; + private boolean isMetadataAccessAllowed = true; // --- Configurable @@ -89,6 +92,8 @@ public class AgroalConnectionProvider implements ConnectionProvider, Configurabl @Override public void configure(Map props) throws HibernateException { + isMetadataAccessAllowed = allowJdbcMetadataAccess( props ); + ConnectionInfoLogger.INSTANCE.configureConnectionPool( "Agroal" ); try { AgroalPropertiesReader agroalProperties = new AgroalPropertiesReader( CONFIG_PREFIX ) @@ -136,9 +141,12 @@ public class AgroalConnectionProvider implements ConnectionProvider, Configurabl final AgroalConnectionPoolConfiguration acpc = agroalDataSource.getConfiguration().connectionPoolConfiguration(); final AgroalConnectionFactoryConfiguration acfc = acpc.connectionFactoryConfiguration(); + return new DatabaseConnectionInfoImpl( acfc.jdbcUrl(), - acfc.connectionProviderClass().toString(), + // Attempt to resolve the driver name from the dialect, in case it wasn't explicitly set and access to + // the database metadata is allowed + acfc.connectionProviderClass() != null ? acfc.connectionProviderClass().toString() : extractDriverNameFromMetadata(), dialect.getVersion(), Boolean.toString( acfc.autoCommit() ), acfc.jdbcTransactionIsolation() != null @@ -149,6 +157,19 @@ public class AgroalConnectionProvider implements ConnectionProvider, Configurabl ); } + private String extractDriverNameFromMetadata() { + if (isMetadataAccessAllowed) { + try ( Connection conn = getConnection() ) { + DatabaseMetaData dbmd = conn.getMetaData(); + return dbmd.getDriverName(); + } + catch (SQLException e) { + // Do nothing + } + } + return null; + } + @Override public boolean isUnwrappableAs(Class unwrapType) { return ConnectionProvider.class.equals( unwrapType ) diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/JdbcEnvironmentInitiator.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/JdbcEnvironmentInitiator.java index 2e021ff0bf..2ed99ad80f 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/JdbcEnvironmentInitiator.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/JdbcEnvironmentInitiator.java @@ -216,7 +216,7 @@ public class JdbcEnvironmentInitiator implements StandardServiceInitiator configurationValues) { + public static boolean allowJdbcMetadataAccess(Map configurationValues) { final Boolean allow = getBooleanWrapper( ALLOW_METADATA_ON_BOOT, configurationValues, null ); if ( allow != null ) { return allow; diff --git a/hibernate-hikaricp/src/main/java/org/hibernate/hikaricp/internal/HikariCPConnectionProvider.java b/hibernate-hikaricp/src/main/java/org/hibernate/hikaricp/internal/HikariCPConnectionProvider.java index 097ba75b94..a4f6b073b4 100644 --- a/hibernate-hikaricp/src/main/java/org/hibernate/hikaricp/internal/HikariCPConnectionProvider.java +++ b/hibernate-hikaricp/src/main/java/org/hibernate/hikaricp/internal/HikariCPConnectionProvider.java @@ -5,9 +5,10 @@ package org.hibernate.hikaricp.internal; import java.sql.Connection; +import java.sql.DatabaseMetaData; import java.sql.SQLException; -import java.util.Map; import javax.sql.DataSource; +import java.util.Map; import org.hibernate.HibernateException; import org.hibernate.dialect.Dialect; @@ -15,6 +16,7 @@ import org.hibernate.engine.jdbc.connections.internal.DatabaseConnectionInfoImpl import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; import org.hibernate.engine.jdbc.connections.spi.DatabaseConnectionInfo; import org.hibernate.internal.log.ConnectionInfoLogger; +import org.hibernate.internal.util.StringHelper; import org.hibernate.service.UnknownUnwrapTypeException; import org.hibernate.service.spi.Configurable; import org.hibernate.service.spi.Stoppable; @@ -22,6 +24,8 @@ import org.hibernate.service.spi.Stoppable; import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; +import static org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.allowJdbcMetadataAccess; + /** * HikariCP Connection provider for Hibernate. * @@ -31,6 +35,7 @@ import com.zaxxer.hikari.HikariDataSource; public class HikariCPConnectionProvider implements ConnectionProvider, Configurable, Stoppable { private static final long serialVersionUID = -9131625057941275711L; + private boolean isMetadataAccessAllowed = true; /** * HikariCP configuration. @@ -49,6 +54,8 @@ public class HikariCPConnectionProvider implements ConnectionProvider, Configura @Override public void configure(Map props) throws HibernateException { try { + isMetadataAccessAllowed = allowJdbcMetadataAccess( props ); + ConnectionInfoLogger.INSTANCE.configureConnectionPool( "HikariCP" ); hcfg = HikariConfigurationUtil.loadConfiguration( props ); @@ -83,7 +90,9 @@ public class HikariCPConnectionProvider implements ConnectionProvider, Configura public DatabaseConnectionInfo getDatabaseConnectionInfo(Dialect dialect) { return new DatabaseConnectionInfoImpl( hcfg.getJdbcUrl(), - hcfg.getDriverClassName(), + // Attempt to resolve the driver name from the dialect, in case it wasn't explicitly set and access to + // the database metadata is allowed + !StringHelper.isBlank( hcfg.getDriverClassName() ) ? hcfg.getDriverClassName() : extractDriverNameFromMetadata(), dialect.getVersion(), Boolean.toString( hcfg.isAutoCommit() ), hcfg.getTransactionIsolation(), @@ -92,6 +101,19 @@ public class HikariCPConnectionProvider implements ConnectionProvider, Configura ); } + private String extractDriverNameFromMetadata() { + if (isMetadataAccessAllowed) { + try ( Connection conn = getConnection() ) { + DatabaseMetaData dbmd = conn.getMetaData(); + return dbmd.getDriverName(); + } + catch (SQLException e) { + // Do nothing + } + } + return null; + } + @Override public boolean isUnwrappableAs(Class unwrapType) { return ConnectionProvider.class.equals( unwrapType ) diff --git a/hibernate-vibur/src/main/java/org/hibernate/vibur/internal/ViburDBCPConnectionProvider.java b/hibernate-vibur/src/main/java/org/hibernate/vibur/internal/ViburDBCPConnectionProvider.java index 6c88cdd7af..dfc2e545b7 100644 --- a/hibernate-vibur/src/main/java/org/hibernate/vibur/internal/ViburDBCPConnectionProvider.java +++ b/hibernate-vibur/src/main/java/org/hibernate/vibur/internal/ViburDBCPConnectionProvider.java @@ -5,6 +5,7 @@ package org.hibernate.vibur.internal; import java.sql.Connection; +import java.sql.DatabaseMetaData; import java.sql.SQLException; import java.util.Map; import java.util.Properties; @@ -14,6 +15,7 @@ import org.hibernate.engine.jdbc.connections.internal.DatabaseConnectionInfoImpl import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; import org.hibernate.engine.jdbc.connections.spi.DatabaseConnectionInfo; import org.hibernate.internal.log.ConnectionInfoLogger; +import org.hibernate.internal.util.StringHelper; import org.hibernate.service.UnknownUnwrapTypeException; import org.hibernate.service.spi.Configurable; import org.hibernate.service.spi.Stoppable; @@ -26,6 +28,7 @@ import static org.hibernate.cfg.AvailableSettings.ISOLATION; import static org.hibernate.cfg.AvailableSettings.PASS; import static org.hibernate.cfg.AvailableSettings.URL; import static org.hibernate.cfg.AvailableSettings.USER; +import static org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.allowJdbcMetadataAccess; /** *

ViburDBCP connection provider for Hibernate integration. @@ -57,9 +60,12 @@ public class ViburDBCPConnectionProvider implements ConnectionProvider, Configur private static final String VIBUR_PREFIX = VIBUR_CONFIG_PREFIX + "."; private ViburDBCPDataSource dataSource = null; + private boolean isMetadataAccessAllowed = true; @Override public void configure(Map configurationValues) { + isMetadataAccessAllowed = allowJdbcMetadataAccess( configurationValues ); + ConnectionInfoLogger.INSTANCE.configureConnectionPool( "Vibur" ); dataSource = new ViburDBCPDataSource( transform( configurationValues ) ); @@ -94,7 +100,9 @@ public class ViburDBCPConnectionProvider implements ConnectionProvider, Configur public DatabaseConnectionInfo getDatabaseConnectionInfo(Dialect dialect) { return new DatabaseConnectionInfoImpl( dataSource.getJdbcUrl(), - dataSource.getDriverClassName(), + // Attempt to resolve the driver name from the dialect, in case it wasn't explicitly set and access to + // the database metadata is allowed + !StringHelper.isBlank( dataSource.getDriverClassName() ) ? dataSource.getDriverClassName() : extractDriverNameFromMetadata(), dialect.getVersion(), String.valueOf( dataSource.getDefaultAutoCommit() ), dataSource.getDefaultTransactionIsolation(), @@ -103,6 +111,19 @@ public class ViburDBCPConnectionProvider implements ConnectionProvider, Configur ); } + private String extractDriverNameFromMetadata() { + if (isMetadataAccessAllowed) { + try ( Connection conn = getConnection() ) { + DatabaseMetaData dbmd = conn.getMetaData(); + return dbmd.getDriverName(); + } + catch (SQLException e) { + // Do nothing + } + } + return null; + } + @Override public boolean isUnwrappableAs(Class unwrapType) { return ConnectionProvider.class.equals( unwrapType )