mirror of
https://github.com/hibernate/hibernate-orm
synced 2025-02-08 20:24:46 +00:00
Fix up Dialect auto-detection
- make it work for DriverManagerConnectionProviderImpl - improve logging and some confusing exceptions - make it respect explicit database setting properties
This commit is contained in:
parent
95930820af
commit
f6eaaca824
@ -9,6 +9,7 @@
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface StrategyCreator<T> {
|
||||
T create(Class<? extends T> strategyClass);
|
||||
}
|
||||
|
@ -8,7 +8,9 @@
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.Driver;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
@ -22,6 +24,7 @@
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.dialect.Database;
|
||||
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
|
||||
import org.hibernate.internal.CoreLogging;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
@ -101,10 +104,51 @@ private PooledConnections buildPool(Map configurationValues, ServiceRegistryImpl
|
||||
private static ConnectionCreator buildCreator(Map configurationValues, ServiceRegistryImplementor serviceRegistry) {
|
||||
final ConnectionCreatorBuilder connectionCreatorBuilder = new ConnectionCreatorBuilder( serviceRegistry );
|
||||
|
||||
final String driverClassName = (String) configurationValues.get( AvailableSettings.DRIVER );
|
||||
connectionCreatorBuilder.setDriver( loadDriverIfPossible( driverClassName, serviceRegistry ) );
|
||||
|
||||
final String url = (String) configurationValues.get( AvailableSettings.URL );
|
||||
|
||||
String driverClassName = (String) configurationValues.get( AvailableSettings.DRIVER );
|
||||
boolean success = false;
|
||||
if ( driverClassName != null ) {
|
||||
connectionCreatorBuilder.setDriver( loadDriverIfPossible( driverClassName, serviceRegistry ) );
|
||||
success = true;
|
||||
}
|
||||
else if ( url != null ) {
|
||||
//try to guess the driver class from the JDBC URL
|
||||
for ( Database database: Database.values() ) {
|
||||
if ( database.matchesUrl( url ) ) {
|
||||
driverClassName = database.getDriverClassName( url );
|
||||
if ( driverClassName != null ) {
|
||||
try {
|
||||
connectionCreatorBuilder.setDriver( loadDriverIfPossible(driverClassName, serviceRegistry) );
|
||||
success = true;
|
||||
}
|
||||
catch (Exception e) {
|
||||
//swallow it, since this was not
|
||||
//an explicit setting by the user
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( success ) {
|
||||
log.loadedDriver( driverClassName );
|
||||
}
|
||||
else {
|
||||
//we're hoping that the driver is already loaded
|
||||
log.noDriver( AvailableSettings.DRIVER );
|
||||
StringBuilder list = new StringBuilder();
|
||||
Enumeration<Driver> drivers = DriverManager.getDrivers();
|
||||
while ( drivers.hasMoreElements() ) {
|
||||
if ( list.length() != 0) {
|
||||
list.append(", ");
|
||||
}
|
||||
list.append( drivers.nextElement().getClass().getName() );
|
||||
}
|
||||
log.loadedDrivers( list.toString() );
|
||||
}
|
||||
|
||||
if ( url == null ) {
|
||||
final String msg = log.jdbcUrlNotSpecified( AvailableSettings.URL );
|
||||
log.error( msg );
|
||||
@ -112,7 +156,7 @@ private static ConnectionCreator buildCreator(Map configurationValues, ServiceRe
|
||||
}
|
||||
connectionCreatorBuilder.setUrl( url );
|
||||
|
||||
log.usingDriver( driverClassName, url );
|
||||
log.usingUrl( url );
|
||||
|
||||
final Properties connectionProps = ConnectionProviderInitiator.getConnectionProperties( configurationValues );
|
||||
|
||||
@ -217,7 +261,6 @@ protected void finalize() throws Throwable {
|
||||
|
||||
/**
|
||||
* Exposed to facilitate testing only.
|
||||
* @return
|
||||
*/
|
||||
public Properties getConnectionProperties() {
|
||||
BasicConnectionCreator connectionCreator = (BasicConnectionCreator) this.state.pool.connectionCreator;
|
||||
|
@ -6,10 +6,12 @@
|
||||
*/
|
||||
package org.hibernate.engine.jdbc.dialect.internal;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.annotations.common.util.StringHelper;
|
||||
import org.hibernate.boot.registry.selector.spi.StrategySelectionException;
|
||||
import org.hibernate.boot.registry.selector.spi.StrategySelector;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
@ -48,7 +50,7 @@ public void setDialectResolver(DialectResolver dialectResolver) {
|
||||
public Dialect buildDialect(Map configValues, DialectResolutionInfoSource resolutionInfoSource) throws HibernateException {
|
||||
final Object dialectReference = configValues.get( AvailableSettings.DIALECT );
|
||||
if ( !isEmpty( dialectReference ) ) {
|
||||
return constructDialect( dialectReference );
|
||||
return constructDialect( dialectReference, resolutionInfoSource );
|
||||
}
|
||||
else {
|
||||
return determineDialect( resolutionInfoSource );
|
||||
@ -68,10 +70,32 @@ private boolean isEmpty(Object dialectReference) {
|
||||
return true;
|
||||
}
|
||||
|
||||
private Dialect constructDialect(Object dialectReference) {
|
||||
final Dialect dialect;
|
||||
private Dialect constructDialect(Object dialectReference, DialectResolutionInfoSource resolutionInfoSource) {
|
||||
try {
|
||||
dialect = strategySelector.resolveStrategy( Dialect.class, dialectReference );
|
||||
Dialect dialect = strategySelector.resolveStrategy(
|
||||
Dialect.class,
|
||||
dialectReference,
|
||||
(Dialect) null,
|
||||
(dialectClass) -> {
|
||||
try {
|
||||
try {
|
||||
if (resolutionInfoSource != null) {
|
||||
return dialectClass.getConstructor(DialectResolutionInfo.class).newInstance(
|
||||
resolutionInfoSource.getDialectResolutionInfo()
|
||||
);
|
||||
}
|
||||
}
|
||||
catch (NoSuchMethodException nsme) {}
|
||||
return dialectClass.newInstance();
|
||||
}
|
||||
catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
|
||||
throw new StrategySelectionException(
|
||||
String.format( "Could not instantiate named dialect class [%s]", dialectClass.getName() ),
|
||||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
if ( dialect == null ) {
|
||||
throw new HibernateException( "Unable to construct requested dialect [" + dialectReference + "]" );
|
||||
}
|
||||
@ -100,7 +124,6 @@ private Dialect determineDialect(DialectResolutionInfoSource resolutionInfoSourc
|
||||
throw new HibernateException(
|
||||
"Unable to determine Dialect without JDBC metadata "
|
||||
+ "(please set 'javax.persistence.jdbc.url', 'hibernate.connection.url', or 'hibernate.dialect')"
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
@ -109,9 +132,9 @@ private Dialect determineDialect(DialectResolutionInfoSource resolutionInfoSourc
|
||||
|
||||
if ( dialect == null ) {
|
||||
throw new HibernateException(
|
||||
"Unable to determine Dialect to use [name=" + info.getDatabaseName() +
|
||||
", majorVersion=" + info.getDatabaseMajorVersion() +
|
||||
"]; user must register resolver or explicitly set 'hibernate.dialect'"
|
||||
"Unable to determine Dialect for " + info.getDatabaseName() + " "
|
||||
+ info.getDatabaseMajorVersion() + "." + info.getDatabaseMinorVersion()
|
||||
+ " (please set 'hibernate.dialect' or register a Dialect resolver)"
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,6 @@
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
@ -22,7 +21,6 @@
|
||||
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
||||
import org.hibernate.engine.jdbc.env.spi.SQLStateType;
|
||||
import org.hibernate.engine.jdbc.spi.TypeInfo;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.tool.schema.extract.spi.SequenceInformation;
|
||||
|
||||
/**
|
||||
@ -201,8 +199,13 @@ public Builder apply(DatabaseMetaData databaseMetaData) throws SQLException {
|
||||
doesDataDefinitionCauseTransactionCommit = databaseMetaData.dataDefinitionCausesTransactionCommit();
|
||||
extraKeywords = parseKeywords( databaseMetaData.getSQLKeywords() );
|
||||
sqlStateType = SQLStateType.interpretReportedSQLStateType( databaseMetaData.getSQLStateType() );
|
||||
lobLocatorUpdateCopy = databaseMetaData.locatorsUpdateCopy();
|
||||
typeInfoSet = new LinkedHashSet<TypeInfo>();
|
||||
try {
|
||||
lobLocatorUpdateCopy = databaseMetaData.locatorsUpdateCopy();
|
||||
}
|
||||
catch (SQLException sql) {
|
||||
//ignore, the database might not support this at all
|
||||
}
|
||||
typeInfoSet = new LinkedHashSet<>();
|
||||
typeInfoSet.addAll( TypeInfo.extractTypeInfo( databaseMetaData ) );
|
||||
return this;
|
||||
}
|
||||
|
@ -14,6 +14,7 @@
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.MultiTenancyStrategy;
|
||||
import org.hibernate.boot.registry.StandardServiceInitiator;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
|
||||
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
|
||||
@ -62,7 +63,48 @@ public JdbcEnvironment initiateService(Map configurationValues, ServiceRegistryI
|
||||
true
|
||||
);
|
||||
|
||||
if ( useJdbcMetadata ) {
|
||||
if ( configurationValues.containsKey( AvailableSettings.HBM2DDL_DB_NAME ) ) {
|
||||
return new JdbcEnvironmentImpl( registry, dialectFactory.buildDialect(
|
||||
configurationValues,
|
||||
() -> new DialectResolutionInfo() {
|
||||
@Override
|
||||
public String getDatabaseName() {
|
||||
return (String) configurationValues.get( AvailableSettings.HBM2DDL_DB_NAME );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDatabaseVersion() {
|
||||
return (String) configurationValues.getOrDefault( AvailableSettings.HBM2DDL_DB_VERSION, "0" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDatabaseMajorVersion() {
|
||||
return (Integer) configurationValues.getOrDefault( AvailableSettings.HBM2DDL_DB_MAJOR_VERSION, 0 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDatabaseMinorVersion() {
|
||||
return (Integer) configurationValues.getOrDefault( AvailableSettings.HBM2DDL_DB_MINOR_VERSION, 0 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDriverName() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDriverMajorVersion() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDriverMinorVersion() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
) );
|
||||
}
|
||||
else if ( useJdbcMetadata ) {
|
||||
final JdbcConnectionAccess jdbcConnectionAccess = buildJdbcConnectionAccess( configurationValues, registry );
|
||||
try {
|
||||
final Connection connection = jdbcConnectionAccess.obtainConnection();
|
||||
@ -96,26 +138,19 @@ public JdbcEnvironment initiateService(Map configurationValues, ServiceRegistryI
|
||||
|
||||
Dialect dialect = dialectFactory.buildDialect(
|
||||
configurationValues,
|
||||
new DialectResolutionInfoSource() {
|
||||
@Override
|
||||
public DialectResolutionInfo getDialectResolutionInfo() {
|
||||
try {
|
||||
return new DatabaseMetaDataDialectResolutionInfoAdapter( connection.getMetaData() );
|
||||
}
|
||||
catch ( SQLException sqlException ) {
|
||||
throw new HibernateException(
|
||||
"Unable to access java.sql.DatabaseMetaData to determine appropriate Dialect to use",
|
||||
sqlException
|
||||
);
|
||||
}
|
||||
() -> {
|
||||
try {
|
||||
return new DatabaseMetaDataDialectResolutionInfoAdapter( connection.getMetaData() );
|
||||
}
|
||||
catch ( SQLException sqlException ) {
|
||||
throw new HibernateException(
|
||||
"Unable to access java.sql.DatabaseMetaData to determine appropriate Dialect to use",
|
||||
sqlException
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
return new JdbcEnvironmentImpl(
|
||||
registry,
|
||||
dialect,
|
||||
dbmd
|
||||
);
|
||||
return new JdbcEnvironmentImpl( registry, dialect, dbmd );
|
||||
}
|
||||
catch (SQLException e) {
|
||||
log.unableToObtainConnectionMetadata( e.getMessage() );
|
||||
|
@ -9,8 +9,6 @@
|
||||
import java.sql.SQLException;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
|
||||
|
||||
import org.jboss.logging.BasicLogger;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.jboss.logging.annotations.Cause;
|
||||
@ -48,12 +46,24 @@ public interface ConnectionPoolingLogger extends BasicLogger {
|
||||
@Message(value = "Autocommit mode: %s", id = 10001003)
|
||||
void autoCommitMode(boolean autocommit);
|
||||
|
||||
@Message(value = "JDBC URL was not specified by property %s", id = 10001004)
|
||||
String jdbcUrlNotSpecified(String url);
|
||||
@Message(value = "No JDBC URL specified by property %s", id = 10001004)
|
||||
String jdbcUrlNotSpecified(String property);
|
||||
|
||||
@LogMessage(level = INFO)
|
||||
@Message(value = "using driver [%s] at URL [%s]", id = 10001005)
|
||||
void usingDriver(String driverClassName, String url);
|
||||
@Message(value = "Loaded JDBC driver class: %s", id = 10001005)
|
||||
void loadedDriver(String driverClassName);
|
||||
|
||||
@LogMessage(level = INFO)
|
||||
@Message(value = "No JDBC driver class specified by %s", id = 10001010)
|
||||
void noDriver(String property);
|
||||
|
||||
@LogMessage(level = INFO)
|
||||
@Message(value = "Loaded JDBC drivers: %s", id = 10001011)
|
||||
void loadedDrivers(String loadedDrivers);
|
||||
|
||||
@LogMessage(level = INFO)
|
||||
@Message(value = "Connecting with JDBC URL [%s]", id = 10001012)
|
||||
void usingUrl(String url);
|
||||
|
||||
@LogMessage(level = WARN)
|
||||
@Message(value = "No JDBC Driver class was specified by property %s", id = 10001006)
|
||||
|
Loading…
x
Reference in New Issue
Block a user