clean up JdbcEnvironmentInitiator and parse micro database version

this resolves a spurious warning on Derby
This commit is contained in:
Gavin King 2024-02-10 11:04:43 +01:00
parent 7445554e88
commit cad2d2bc62
2 changed files with 103 additions and 99 deletions

View File

@ -9,7 +9,6 @@ package org.hibernate.cfg;
import java.util.Calendar; import java.util.Calendar;
import org.hibernate.Incubating; import org.hibernate.Incubating;
import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.engine.jdbc.env.spi.ExtractedDatabaseMetaData; import org.hibernate.engine.jdbc.env.spi.ExtractedDatabaseMetaData;
import org.hibernate.query.Query; import org.hibernate.query.Query;

View File

@ -11,9 +11,10 @@ import java.sql.DatabaseMetaData;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Collections; import java.util.Collections;
import java.util.Map; import java.util.Map;
import java.util.StringTokenizer;
import org.hibernate.boot.registry.StandardServiceInitiator; import org.hibernate.boot.registry.StandardServiceInitiator;
import org.hibernate.cfg.AvailableSettings; import org.hibernate.dialect.Dialect;
import org.hibernate.engine.config.spi.ConfigurationService; import org.hibernate.engine.config.spi.ConfigurationService;
import org.hibernate.engine.jdbc.batch.spi.BatchBuilder; import org.hibernate.engine.jdbc.batch.spi.BatchBuilder;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
@ -54,6 +55,10 @@ 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.JAKARTA_HBM2DDL_DB_NAME;
import static org.hibernate.cfg.AvailableSettings.JTA_TRACK_BY_THREAD; import static org.hibernate.cfg.AvailableSettings.JTA_TRACK_BY_THREAD;
import static org.hibernate.cfg.AvailableSettings.PREFER_USER_TRANSACTION; import static org.hibernate.cfg.AvailableSettings.PREFER_USER_TRANSACTION;
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;
import static org.hibernate.cfg.JdbcSettings.JAKARTA_HBM2DDL_DB_VERSION;
import static org.hibernate.engine.config.spi.StandardConverters.BOOLEAN; import static org.hibernate.engine.config.spi.StandardConverters.BOOLEAN;
import static org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentImpl.isMultiTenancyEnabled; import static org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentImpl.isMultiTenancyEnabled;
import static org.hibernate.internal.log.DeprecationLogger.DEPRECATION_LOGGER; import static org.hibernate.internal.log.DeprecationLogger.DEPRECATION_LOGGER;
@ -73,6 +78,13 @@ public class JdbcEnvironmentInitiator implements StandardServiceInitiator<JdbcEn
public static final JdbcEnvironmentInitiator INSTANCE = new JdbcEnvironmentInitiator(); public static final JdbcEnvironmentInitiator INSTANCE = new JdbcEnvironmentInitiator();
/**
* @deprecated This setting was never a documented feature of Hibernate,
* is not supported, and will be removed.
*/
@Deprecated(since="6", forRemoval = true)
private static final String USE_JDBC_METADATA_DEFAULTS = "hibernate.temp.use_jdbc_metadata_defaults";
@Override @Override
public Class<JdbcEnvironment> getServiceInitiated() { public Class<JdbcEnvironment> getServiceInitiated() {
return JdbcEnvironment.class; return JdbcEnvironment.class;
@ -80,7 +92,7 @@ public class JdbcEnvironmentInitiator implements StandardServiceInitiator<JdbcEn
@Override @Override
public JdbcEnvironment initiateService(Map<String, Object> configurationValues, ServiceRegistryImplementor registry) { public JdbcEnvironment initiateService(Map<String, Object> configurationValues, ServiceRegistryImplementor registry) {
final DialectFactory dialectFactory = registry.getService( DialectFactory.class ); final DialectFactory dialectFactory = registry.requireService( DialectFactory.class );
final String explicitDatabaseName = getExplicitDatabaseName( configurationValues ); final String explicitDatabaseName = getExplicitDatabaseName( configurationValues );
Integer explicitDatabaseMajorVersion = getExplicitDatabaseMajorVersion( configurationValues ); Integer explicitDatabaseMajorVersion = getExplicitDatabaseMajorVersion( configurationValues );
@ -138,10 +150,8 @@ public class JdbcEnvironmentInitiator implements StandardServiceInitiator<JdbcEn
Map<String, Object> configurationValues, Map<String, Object> configurationValues,
ServiceRegistryImplementor registry, ServiceRegistryImplementor registry,
DialectFactory dialectFactory) { DialectFactory dialectFactory) {
return new JdbcEnvironmentImpl( final Dialect dialect = dialectFactory.buildDialect( configurationValues, null );
registry, return new JdbcEnvironmentImpl( registry, dialect );
dialectFactory.buildDialect( configurationValues, null )
);
} }
private static JdbcEnvironmentImpl getJdbcEnvironmentWithExplicitConfiguration( private static JdbcEnvironmentImpl getJdbcEnvironmentWithExplicitConfiguration(
@ -158,16 +168,15 @@ public class JdbcEnvironmentInitiator implements StandardServiceInitiator<JdbcEn
explicitDatabaseVersion != null ? explicitDatabaseVersion : "0", explicitDatabaseVersion != null ? explicitDatabaseVersion : "0",
explicitDatabaseMajorVersion != null ? explicitDatabaseMajorVersion : 0, explicitDatabaseMajorVersion != null ? explicitDatabaseMajorVersion : 0,
explicitDatabaseMinorVersion != null ? explicitDatabaseMinorVersion : 0, explicitDatabaseMinorVersion != null ? explicitDatabaseMinorVersion : 0,
0,
null, null,
0, 0,
0, 0,
null, null,
configurationValues configurationValues
); );
return new JdbcEnvironmentImpl( final Dialect dialect = dialectFactory.buildDialect( configurationValues, () -> dialectResolutionInfo );
registry, return new JdbcEnvironmentImpl( registry, dialect );
dialectFactory.buildDialect( configurationValues, () -> dialectResolutionInfo )
);
} }
// 'hibernate.temp.use_jdbc_metadata_defaults' is a temporary magic value. // 'hibernate.temp.use_jdbc_metadata_defaults' is a temporary magic value.
@ -178,11 +187,7 @@ public class JdbcEnvironmentInitiator implements StandardServiceInitiator<JdbcEn
// certain default values; it is useful to *not* do this when the database // certain default values; it is useful to *not* do this when the database
// may not be available (mainly in tools usage). // may not be available (mainly in tools usage).
private static boolean useJdbcMetadata(Map<String, Object> configurationValues) { private static boolean useJdbcMetadata(Map<String, Object> configurationValues) {
return getBoolean( return getBoolean(USE_JDBC_METADATA_DEFAULTS, configurationValues, true );
"hibernate.temp.use_jdbc_metadata_defaults",
configurationValues,
true
);
} }
private static String getExplicitDatabaseVersion( private static String getExplicitDatabaseVersion(
@ -190,14 +195,11 @@ public class JdbcEnvironmentInitiator implements StandardServiceInitiator<JdbcEn
Integer configuredDatabaseMajorVersion, Integer configuredDatabaseMajorVersion,
Integer configuredDatabaseMinorVersion) { Integer configuredDatabaseMinorVersion) {
return coalesceSuppliedValues( return coalesceSuppliedValues(
() -> (String) configurationValues.get(AvailableSettings.JAKARTA_HBM2DDL_DB_VERSION), () -> (String) configurationValues.get( JAKARTA_HBM2DDL_DB_VERSION ),
() -> { () -> {
final Object value = configurationValues.get(AvailableSettings.DIALECT_DB_VERSION); final Object value = configurationValues.get( DIALECT_DB_VERSION );
if ( value != null ) { if ( value != null ) {
DEPRECATION_LOGGER.deprecatedSetting( DEPRECATION_LOGGER.deprecatedSetting( DIALECT_DB_VERSION, JAKARTA_HBM2DDL_DB_VERSION );
AvailableSettings.DIALECT_DB_VERSION,
AvailableSettings.JAKARTA_HBM2DDL_DB_VERSION
);
} }
return (String) value; return (String) value;
} }
@ -206,7 +208,7 @@ public class JdbcEnvironmentInitiator implements StandardServiceInitiator<JdbcEn
if ( configuredDatabaseMajorVersion != null ) { if ( configuredDatabaseMajorVersion != null ) {
return configuredDatabaseMinorVersion == null return configuredDatabaseMinorVersion == null
? configuredDatabaseMajorVersion.toString() ? configuredDatabaseMajorVersion.toString()
: (configuredDatabaseMajorVersion + "." + configuredDatabaseMinorVersion); : configuredDatabaseMajorVersion + "." + configuredDatabaseMinorVersion;
} }
return null; return null;
} }
@ -266,7 +268,7 @@ public class JdbcEnvironmentInitiator implements StandardServiceInitiator<JdbcEn
jdbcServices, jdbcServices,
registry registry
); );
temporaryJdbcSessionOwner.transactionCoordinator = registry.getService( TransactionCoordinatorBuilder.class ) temporaryJdbcSessionOwner.transactionCoordinator = registry.requireService( TransactionCoordinatorBuilder.class )
.buildTransactionCoordinator( .buildTransactionCoordinator(
new JdbcCoordinatorImpl( null, temporaryJdbcSessionOwner, jdbcServices ), new JdbcCoordinatorImpl( null, temporaryJdbcSessionOwner, jdbcServices ),
() -> false () -> false
@ -276,57 +278,38 @@ public class JdbcEnvironmentInitiator implements StandardServiceInitiator<JdbcEn
return temporaryJdbcSessionOwner.transactionCoordinator.createIsolationDelegate().delegateWork( return temporaryJdbcSessionOwner.transactionCoordinator.createIsolationDelegate().delegateWork(
new AbstractReturningWork<>() { new AbstractReturningWork<>() {
@Override @Override
public JdbcEnvironmentImpl execute(Connection connection) throws SQLException { public JdbcEnvironmentImpl execute(Connection connection) {
try { try {
final DatabaseMetaData dbmd = connection.getMetaData(); final DatabaseMetaData metadata = connection.getMetaData();
logDatabaseAndDriver( dbmd ); logDatabaseAndDriver( metadata );
final String databaseName;
final String databaseVersion;
final int databaseMajorVersion;
final int databaseMinorVersion;
if ( explicitDatabaseName == null ) {
databaseName = dbmd.getDatabaseProductName();
}
else {
databaseName = explicitDatabaseName;
}
if ( explicitDatabaseVersion == null ) {
databaseVersion = dbmd.getDatabaseProductVersion();
}
else {
databaseVersion = explicitDatabaseVersion;
}
if ( explicitDatabaseMajorVersion == null ) {
databaseMajorVersion = dbmd.getDatabaseMajorVersion();
}
else {
databaseMajorVersion = explicitDatabaseMajorVersion;
}
if ( explicitDatabaseMinorVersion == null ) {
databaseMinorVersion = dbmd.getDatabaseMinorVersion();
}
else {
databaseMinorVersion = explicitDatabaseMinorVersion;
}
final DialectResolutionInfo dialectResolutionInfo = new DialectResolutionInfoImpl( final DialectResolutionInfo dialectResolutionInfo = new DialectResolutionInfoImpl(
dbmd, metadata,
databaseName, explicitDatabaseName == null
databaseVersion, ? metadata.getDatabaseProductName()
databaseMajorVersion, : explicitDatabaseName,
databaseMinorVersion, explicitDatabaseVersion == null
dbmd.getDriverName(), ? metadata.getDatabaseProductVersion()
dbmd.getDriverMajorVersion(), : explicitDatabaseVersion,
dbmd.getDriverMinorVersion(), explicitDatabaseMajorVersion == null
dbmd.getSQLKeywords(), ? metadata.getDatabaseMajorVersion()
: explicitDatabaseMajorVersion,
explicitDatabaseMinorVersion == null
? metadata.getDatabaseMinorVersion()
: explicitDatabaseMinorVersion,
explicitDatabaseMinorVersion == null
? databaseMicroVersion( metadata )
: 0,
metadata.getDriverName(),
metadata.getDriverMajorVersion(),
metadata.getDriverMinorVersion(),
metadata.getSQLKeywords(),
configurationValues configurationValues
); );
return new JdbcEnvironmentImpl( return new JdbcEnvironmentImpl(
registry, registry,
dialectFactory.buildDialect( configurationValues, () -> dialectResolutionInfo ), dialectFactory.buildDialect( configurationValues, () -> dialectResolutionInfo ),
dbmd, metadata,
jdbcConnectionAccess jdbcConnectionAccess
); );
} }
@ -337,6 +320,25 @@ public class JdbcEnvironmentInitiator implements StandardServiceInitiator<JdbcEn
// accessing the JDBC metadata failed // accessing the JDBC metadata failed
return getJdbcEnvironmentWithDefaults( configurationValues, registry, dialectFactory ); return getJdbcEnvironmentWithDefaults( configurationValues, registry, dialectFactory );
} }
private int databaseMicroVersion(DatabaseMetaData metadata) throws SQLException {
final String version = metadata.getDatabaseProductVersion();
final String prefix =
metadata.getDatabaseMajorVersion() + "." + metadata.getDatabaseMinorVersion() + ".";
if ( version.startsWith(prefix) ) {
try {
final String substring = version.substring( prefix.length() );
final String micro = new StringTokenizer(substring," .,-:;/()[]").nextToken();
return Integer.parseInt(micro);
}
catch (NumberFormatException nfe) {
return 0;
}
}
else {
return 0;
}
}
}, },
false false
); );
@ -352,10 +354,10 @@ public class JdbcEnvironmentInitiator implements StandardServiceInitiator<JdbcEn
if ( log.isDebugEnabled() ) { if ( log.isDebugEnabled() ) {
log.debugf( log.debugf(
"Database ->\n" "Database ->\n"
+ " name : %s\n" + " name : %s\n"
+ " version : %s\n" + " version : %s\n"
+ " major : %s\n" + " major : %s\n"
+ " minor : %s", + " minor : %s",
dbmd.getDatabaseProductName(), dbmd.getDatabaseProductName(),
dbmd.getDatabaseProductVersion(), dbmd.getDatabaseProductVersion(),
dbmd.getDatabaseMajorVersion(), dbmd.getDatabaseMajorVersion(),
@ -363,10 +365,10 @@ public class JdbcEnvironmentInitiator implements StandardServiceInitiator<JdbcEn
); );
log.debugf( log.debugf(
"Driver ->\n" "Driver ->\n"
+ " name : %s\n" + " name : %s\n"
+ " version : %s\n" + " version : %s\n"
+ " major : %s\n" + " major : %s\n"
+ " minor : %s", + " minor : %s",
dbmd.getDriverName(), dbmd.getDriverName(),
dbmd.getDriverVersion(), dbmd.getDriverVersion(),
dbmd.getDriverMajorVersion(), dbmd.getDriverMajorVersion(),
@ -383,7 +385,7 @@ public class JdbcEnvironmentInitiator implements StandardServiceInitiator<JdbcEn
Integer explicitDatabaseMinorVersion, Integer explicitDatabaseMinorVersion,
String explicitDatabaseVersion) { String explicitDatabaseVersion) {
return ( isNotEmpty(explicitDatabaseVersion) || explicitDatabaseMajorVersion != null || explicitDatabaseMinorVersion != null ) return ( isNotEmpty(explicitDatabaseVersion) || explicitDatabaseMajorVersion != null || explicitDatabaseMinorVersion != null )
&& ( isNotEmpty(explicitDatabaseName) || isNotNullAndNotEmpty( configurationValues.get(AvailableSettings.DIALECT) ) ); && ( isNotEmpty(explicitDatabaseName) || isNotNullAndNotEmpty( configurationValues.get(DIALECT) ) );
} }
private static boolean isNotNullAndNotEmpty(Object o) { private static boolean isNotNullAndNotEmpty(Object o) {
@ -396,7 +398,8 @@ public class JdbcEnvironmentInitiator implements StandardServiceInitiator<JdbcEn
return new ConnectionProviderJdbcConnectionAccess( connectionProvider ); return new ConnectionProviderJdbcConnectionAccess( connectionProvider );
} }
else { else {
final MultiTenantConnectionProvider<?> multiTenantConnectionProvider = registry.getService( MultiTenantConnectionProvider.class ); final MultiTenantConnectionProvider<?> multiTenantConnectionProvider =
registry.getService( MultiTenantConnectionProvider.class );
return new MultiTenantConnectionProviderJdbcConnectionAccess( multiTenantConnectionProvider ); return new MultiTenantConnectionProviderJdbcConnectionAccess( multiTenantConnectionProvider );
} }
} }
@ -407,7 +410,8 @@ public class JdbcEnvironmentInitiator implements StandardServiceInitiator<JdbcEn
return new ConnectionProviderJdbcConnectionAccess( connectionProvider ); return new ConnectionProviderJdbcConnectionAccess( connectionProvider );
} }
else { else {
final MultiTenantConnectionProvider<?> multiTenantConnectionProvider = registry.getService( MultiTenantConnectionProvider.class ); final MultiTenantConnectionProvider<?> multiTenantConnectionProvider =
registry.getService( MultiTenantConnectionProvider.class );
return new MultiTenantConnectionProviderJdbcConnectionAccess( multiTenantConnectionProvider ); return new MultiTenantConnectionProviderJdbcConnectionAccess( multiTenantConnectionProvider );
} }
} }
@ -472,6 +476,7 @@ public class JdbcEnvironmentInitiator implements StandardServiceInitiator<JdbcEn
private final String databaseVersion; private final String databaseVersion;
private final int databaseMajorVersion; private final int databaseMajorVersion;
private final int databaseMinorVersion; private final int databaseMinorVersion;
private final int databaseMicroVersion;
private final String driverName; private final String driverName;
private final int driverMajorVersion; private final int driverMajorVersion;
private final int driverMinorVersion; private final int driverMinorVersion;
@ -483,7 +488,8 @@ public class JdbcEnvironmentInitiator implements StandardServiceInitiator<JdbcEn
String databaseName, String databaseName,
String databaseVersion, String databaseVersion,
int databaseMajorVersion, int databaseMajorVersion,
int databaseMinorVersion, int databaseMinorVersion,
int databaseMicroVersion,
String driverName, String driverName,
int driverMajorVersion, int driverMajorVersion,
int driverMinorVersion, int driverMinorVersion,
@ -494,6 +500,7 @@ public class JdbcEnvironmentInitiator implements StandardServiceInitiator<JdbcEn
this.databaseVersion = databaseVersion; this.databaseVersion = databaseVersion;
this.databaseMajorVersion = databaseMajorVersion; this.databaseMajorVersion = databaseMajorVersion;
this.databaseMinorVersion = databaseMinorVersion; this.databaseMinorVersion = databaseMinorVersion;
this.databaseMicroVersion = databaseMicroVersion;
this.driverName = driverName; this.driverName = driverName;
this.driverMajorVersion = driverMajorVersion; this.driverMajorVersion = driverMajorVersion;
this.driverMinorVersion = driverMinorVersion; this.driverMinorVersion = driverMinorVersion;
@ -525,6 +532,11 @@ public class JdbcEnvironmentInitiator implements StandardServiceInitiator<JdbcEn
return databaseMinorVersion; return databaseMinorVersion;
} }
@Override
public int getDatabaseMicroVersion() {
return databaseMicroVersion;
}
@Override @Override
public String getDriverName() { public String getDriverName() {
return driverName; return driverName;
@ -580,26 +592,19 @@ public class JdbcEnvironmentInitiator implements StandardServiceInitiator<JdbcEn
this.jdbcConnectionAccess = jdbcConnectionAccess; this.jdbcConnectionAccess = jdbcConnectionAccess;
this.jdbcServices = jdbcServices; this.jdbcServices = jdbcServices;
this.serviceRegistry = serviceRegistry; this.serviceRegistry = serviceRegistry;
final ConfigurationService configurationService = serviceRegistry.getService( ConfigurationService.class ); final ConfigurationService configuration = serviceRegistry.requireService( ConfigurationService.class );
this.jtaTrackByThread = configurationService.getSetting( JTA_TRACK_BY_THREAD, BOOLEAN, true ); this.jtaTrackByThread = configuration.getSetting( JTA_TRACK_BY_THREAD, BOOLEAN, true );
this.preferUserTransaction = getBoolean( PREFER_USER_TRANSACTION, configurationService.getSettings() ); this.preferUserTransaction = getBoolean( PREFER_USER_TRANSACTION, configuration.getSettings() );
this.connectionProviderDisablesAutoCommit = getBoolean( this.connectionProviderDisablesAutoCommit =
AvailableSettings.CONNECTION_PROVIDER_DISABLES_AUTOCOMMIT, getBoolean( CONNECTION_PROVIDER_DISABLES_AUTOCOMMIT, configuration.getSettings() );
configurationService.getSettings(),
false
);
final PhysicalConnectionHandlingMode specifiedHandlingMode = PhysicalConnectionHandlingMode.interpret( final PhysicalConnectionHandlingMode specifiedHandlingMode =
configurationService.getSettings().get( CONNECTION_HANDLING ) PhysicalConnectionHandlingMode.interpret( configuration.getSettings().get( CONNECTION_HANDLING ) );
); this.connectionHandlingMode = specifiedHandlingMode != null
? specifiedHandlingMode
: serviceRegistry.requireService(TransactionCoordinatorBuilder.class)
.getDefaultConnectionHandlingMode();
if ( specifiedHandlingMode != null ) {
this.connectionHandlingMode = specifiedHandlingMode;
}
else {
this.connectionHandlingMode = serviceRegistry.getService( TransactionCoordinatorBuilder.class )
.getDefaultConnectionHandlingMode();
}
this.jpaCompliance = new MutableJpaComplianceImpl( Collections.emptyMap(), false ); this.jpaCompliance = new MutableJpaComplianceImpl( Collections.emptyMap(), false );
this.eventManager = new EmptyEventManager(); this.eventManager = new EmptyEventManager();
} }
@ -669,7 +674,7 @@ public class JdbcEnvironmentInitiator implements StandardServiceInitiator<JdbcEn
return null; return null;
} }
@Override @Override @Deprecated
public int getFetchSize() { public int getFetchSize() {
return 0; return 0;
} }
@ -709,7 +714,7 @@ public class JdbcEnvironmentInitiator implements StandardServiceInitiator<JdbcEn
return null; return null;
} }
@Override @Override @Deprecated
public JdbcObserver getObserver() { public JdbcObserver getObserver() {
return EMPTY_JDBC_OBSERVER; return EMPTY_JDBC_OBSERVER;
} }