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 <jschatte@redhat.com>
This commit is contained in:
Jan Schatteman 2024-10-07 22:59:34 +02:00 committed by Jan Schatteman
parent 2d13afb511
commit d702496e4d
4 changed files with 70 additions and 6 deletions

View File

@ -9,10 +9,11 @@
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;
@ -36,6 +37,7 @@
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
@ -64,6 +66,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
@ -92,6 +95,8 @@ private static <T> void copyProperty(Map<String, Object> properties, String key,
@Override
public void configure(Map<String, Object> props) throws HibernateException {
isMetadataAccessAllowed = allowJdbcMetadataAccess( props );
ConnectionInfoLogger.INSTANCE.configureConnectionPool( "Agroal" );
try {
AgroalPropertiesReader agroalProperties = new AgroalPropertiesReader( CONFIG_PREFIX )
@ -139,9 +144,12 @@ public DatabaseConnectionInfo getDatabaseConnectionInfo(Dialect dialect) {
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
@ -152,6 +160,19 @@ public DatabaseConnectionInfo getDatabaseConnectionInfo(Dialect dialect) {
);
}
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 )

View File

@ -215,7 +215,7 @@ private static JdbcEnvironmentImpl getJdbcEnvironmentWithExplicitConfiguration(
*
* @see JdbcSettings#ALLOW_METADATA_ON_BOOT
*/
private static boolean allowJdbcMetadataAccess(Map<String, Object> configurationValues) {
public static boolean allowJdbcMetadataAccess(Map<String, Object> configurationValues) {
final Boolean allow = getBooleanWrapper( ALLOW_METADATA_ON_BOOT, configurationValues, null );
if ( allow != null ) {
return allow;

View File

@ -8,9 +8,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;
@ -18,6 +19,7 @@
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;
@ -25,6 +27,8 @@
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.
*
@ -34,6 +38,7 @@
public class HikariCPConnectionProvider implements ConnectionProvider, Configurable, Stoppable {
private static final long serialVersionUID = -9131625057941275711L;
private boolean isMetadataAccessAllowed = true;
/**
* HikariCP configuration.
@ -52,6 +57,8 @@ public class HikariCPConnectionProvider implements ConnectionProvider, Configura
@Override
public void configure(Map<String, Object> props) throws HibernateException {
try {
isMetadataAccessAllowed = allowJdbcMetadataAccess( props );
ConnectionInfoLogger.INSTANCE.configureConnectionPool( "HikariCP" );
hcfg = HikariConfigurationUtil.loadConfiguration( props );
@ -86,7 +93,9 @@ public boolean supportsAggressiveRelease() {
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(),
@ -95,6 +104,19 @@ public DatabaseConnectionInfo getDatabaseConnectionInfo(Dialect dialect) {
);
}
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 )

View File

@ -8,6 +8,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;
@ -17,6 +18,7 @@
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;
@ -29,6 +31,7 @@
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;
/**
* <p>ViburDBCP connection provider for Hibernate integration.
@ -60,9 +63,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<String, Object> configurationValues) {
isMetadataAccessAllowed = allowJdbcMetadataAccess( configurationValues );
ConnectionInfoLogger.INSTANCE.configureConnectionPool( "Vibur" );
dataSource = new ViburDBCPDataSource( transform( configurationValues ) );
@ -97,7 +103,9 @@ public boolean supportsAggressiveRelease() {
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(),
@ -106,6 +114,19 @@ public DatabaseConnectionInfo getDatabaseConnectionInfo(Dialect dialect) {
);
}
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 )