HHH-17269 - Add hibernate.boot.allow_jdbc_metadata_access
This commit is contained in:
parent
39cd03d1a5
commit
ab01984807
|
@ -471,6 +471,25 @@ public interface JdbcSettings extends C3p0Settings, ProxoolSettings {
|
|||
*/
|
||||
String CONNECTION_HANDLING = "hibernate.connection.handling_mode";
|
||||
|
||||
/**
|
||||
* Whether access to JDBC {@linkplain java.sql.DatabaseMetaData metadata} is allowed during bootstrap.
|
||||
* <p/>
|
||||
* Typically, Hibernate accesses this metadata to understand the capabilities of the underlying
|
||||
* database to help minimize needed configuration. Disabling this access means that only explicit
|
||||
* settings are used. At a minimum, the Dialect to use must be specified using either the {@value #DIALECT}
|
||||
* or {@value JdbcSettings#JAKARTA_HBM2DDL_DB_NAME} setting. When the Dialect to use is specified in
|
||||
* this manner it is generally a good idea to specify the
|
||||
* {@linkplain JdbcSettings#JAKARTA_HBM2DDL_DB_VERSION database version} as well - Dialects use the version
|
||||
* to configure themselves.
|
||||
*
|
||||
* @apiNote The specified Dialect may also provide defaults into the "explicit" settings.
|
||||
*
|
||||
* @settingDefault {@code true}
|
||||
*
|
||||
* @since 6.5
|
||||
*/
|
||||
String ALLOW_METADATA_ON_BOOT = "hibernate.boot.allow_jdbc_metadata_access";
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Deprecated Hibernate settings
|
||||
|
|
|
@ -14,6 +14,7 @@ import java.util.Map;
|
|||
import java.util.StringTokenizer;
|
||||
|
||||
import org.hibernate.boot.registry.StandardServiceInitiator;
|
||||
import org.hibernate.cfg.JdbcSettings;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.config.spi.ConfigurationService;
|
||||
import org.hibernate.engine.jdbc.batch.spi.BatchBuilder;
|
||||
|
@ -55,6 +56,7 @@ import static org.hibernate.cfg.AvailableSettings.JAKARTA_HBM2DDL_DB_MINOR_VERSI
|
|||
import static org.hibernate.cfg.AvailableSettings.JAKARTA_HBM2DDL_DB_NAME;
|
||||
import static org.hibernate.cfg.AvailableSettings.JTA_TRACK_BY_THREAD;
|
||||
import static org.hibernate.cfg.AvailableSettings.PREFER_USER_TRANSACTION;
|
||||
import static org.hibernate.cfg.JdbcSettings.ALLOW_METADATA_ON_BOOT;
|
||||
import static org.hibernate.cfg.JdbcSettings.CONNECTION_PROVIDER_DISABLES_AUTOCOMMIT;
|
||||
import static org.hibernate.cfg.JdbcSettings.DIALECT;
|
||||
import static org.hibernate.cfg.JdbcSettings.DIALECT_DB_VERSION;
|
||||
|
@ -65,6 +67,7 @@ import static org.hibernate.internal.log.DeprecationLogger.DEPRECATION_LOGGER;
|
|||
import static org.hibernate.internal.util.NullnessHelper.coalesceSuppliedValues;
|
||||
import static org.hibernate.internal.util.StringHelper.isNotEmpty;
|
||||
import static org.hibernate.internal.util.config.ConfigurationHelper.getBoolean;
|
||||
import static org.hibernate.internal.util.config.ConfigurationHelper.getBooleanWrapper;
|
||||
import static org.hibernate.internal.util.config.ConfigurationHelper.getInteger;
|
||||
|
||||
/**
|
||||
|
@ -115,7 +118,7 @@ public class JdbcEnvironmentInitiator implements StandardServiceInitiator<JdbcEn
|
|||
}
|
||||
}
|
||||
|
||||
if ( useJdbcMetadata( configurationValues ) ) {
|
||||
if ( allowJdbcMetadataAccess( configurationValues ) ) {
|
||||
return getJdbcEnvironmentUsingJdbcMetadata(
|
||||
configurationValues,
|
||||
registry,
|
||||
|
@ -179,15 +182,28 @@ public class JdbcEnvironmentInitiator implements StandardServiceInitiator<JdbcEn
|
|||
return new JdbcEnvironmentImpl( registry, dialect );
|
||||
}
|
||||
|
||||
// 'hibernate.temp.use_jdbc_metadata_defaults' is a temporary magic value.
|
||||
// The need for it is intended to be alleviated with future development, thus it is
|
||||
// not defined as an Environment constant...
|
||||
//
|
||||
// it is used to control whether we should consult the JDBC metadata to determine
|
||||
// certain default values; it is useful to *not* do this when the database
|
||||
// may not be available (mainly in tools usage).
|
||||
private static boolean useJdbcMetadata(Map<String, Object> configurationValues) {
|
||||
return getBoolean(USE_JDBC_METADATA_DEFAULTS, configurationValues, true );
|
||||
/**
|
||||
* Determine whether we can access JDBC {@linkplain DatabaseMetaData metadata} based on
|
||||
* the {@value JdbcSettings#ALLOW_METADATA_ON_BOOT} setting. The default is to allow access.
|
||||
*
|
||||
* @implNote Currently also looks for the deprecated {@value JdbcEnvironmentInitiator#USE_JDBC_METADATA_DEFAULTS} setting as a fallback.
|
||||
*
|
||||
* @see JdbcSettings#ALLOW_METADATA_ON_BOOT
|
||||
*/
|
||||
private static boolean allowJdbcMetadataAccess(Map<String, Object> configurationValues) {
|
||||
final Boolean allow = getBooleanWrapper( ALLOW_METADATA_ON_BOOT, configurationValues, null );
|
||||
if ( allow != null ) {
|
||||
return allow;
|
||||
}
|
||||
|
||||
final Boolean use = getBooleanWrapper( USE_JDBC_METADATA_DEFAULTS, configurationValues, null );
|
||||
if ( use != null ) {
|
||||
DEPRECATION_LOGGER.deprecatedSetting( USE_JDBC_METADATA_DEFAULTS, ALLOW_METADATA_ON_BOOT );
|
||||
return use;
|
||||
}
|
||||
|
||||
// allow by default
|
||||
return true;
|
||||
}
|
||||
|
||||
private static String getExplicitDatabaseVersion(
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* 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.orm.test.boot.database.metadata;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.cfg.JdbcSettings;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.dialect.H2Dialect;
|
||||
import org.hibernate.dialect.OracleDialect;
|
||||
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
||||
import org.hibernate.service.spi.ServiceException;
|
||||
|
||||
import org.hibernate.testing.env.TestingDatabaseInfo;
|
||||
import org.hibernate.testing.orm.junit.Jira;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@Jira( "https://hibernate.atlassian.net/browse/HHH-17269" )
|
||||
public class MetadataAccessTests {
|
||||
|
||||
@Test
|
||||
void testAccessAllowed() {
|
||||
final StandardServiceRegistryBuilder registryBuilder = new StandardServiceRegistryBuilder();
|
||||
registryBuilder.clearSettings();
|
||||
|
||||
// allow access to the jdbc metadata
|
||||
registryBuilder.applySetting( JdbcSettings.ALLOW_METADATA_ON_BOOT, true );
|
||||
|
||||
// configure the values needed to connect to a H2 database
|
||||
registryBuilder.applySetting( AvailableSettings.JAKARTA_JDBC_DRIVER, TestingDatabaseInfo.DRIVER );
|
||||
registryBuilder.applySetting( AvailableSettings.JAKARTA_JDBC_URL, TestingDatabaseInfo.URL );
|
||||
registryBuilder.applySetting( AvailableSettings.JAKARTA_JDBC_USER, TestingDatabaseInfo.USER );
|
||||
registryBuilder.applySetting( AvailableSettings.JAKARTA_JDBC_PASSWORD, TestingDatabaseInfo.PASS );
|
||||
|
||||
// make certain there is no explicit dialect configured
|
||||
assertThat( registryBuilder.getSettings() ).doesNotContainKey( JdbcSettings.DIALECT );
|
||||
|
||||
try (StandardServiceRegistry registry = registryBuilder.build()) {
|
||||
final JdbcEnvironment jdbcEnvironment = registry.getService( JdbcEnvironment.class );
|
||||
final Dialect dialect = jdbcEnvironment.getDialect();
|
||||
assertThat( dialect ).isNotNull();
|
||||
assertThat( dialect ).isInstanceOf( H2Dialect.class );
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAccessDisabledExplicitDialect() {
|
||||
final StandardServiceRegistryBuilder registryBuilder = new StandardServiceRegistryBuilder();
|
||||
registryBuilder.clearSettings();
|
||||
|
||||
registryBuilder.applySetting( JdbcSettings.ALLOW_METADATA_ON_BOOT, false );
|
||||
registryBuilder.applySetting( JdbcSettings.DIALECT, "org.hibernate.dialect.OracleDialect" );
|
||||
|
||||
try (StandardServiceRegistry registry = registryBuilder.build()) {
|
||||
final JdbcEnvironment jdbcEnvironment = registry.getService( JdbcEnvironment.class );
|
||||
final Dialect dialect = jdbcEnvironment.getDialect();
|
||||
assertThat( dialect ).isInstanceOf( OracleDialect.class );
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAccessDisabledNoDialect() {
|
||||
final StandardServiceRegistryBuilder registryBuilder = new StandardServiceRegistryBuilder();
|
||||
registryBuilder.clearSettings();
|
||||
assertThat( registryBuilder.getSettings() ).doesNotContainKey( JdbcSettings.DIALECT );
|
||||
|
||||
registryBuilder.applySetting( JdbcSettings.ALLOW_METADATA_ON_BOOT, false );
|
||||
try (StandardServiceRegistry registry = registryBuilder.build()) {
|
||||
final JdbcEnvironment jdbcEnvironment = registry.getService( JdbcEnvironment.class );
|
||||
final Dialect dialect = jdbcEnvironment.getDialect();
|
||||
fail( "Should fail to boot - " + dialect );
|
||||
}
|
||||
catch (ServiceException expected) {
|
||||
assertThat( expected.getCause() ).isInstanceOf( HibernateException.class );
|
||||
final HibernateException cause = (HibernateException) expected.getCause();
|
||||
assertThat( cause.getMessage() ).startsWith( "Unable to determine Dialect without JDBC metadata" );
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue