HHH-8561 - hibernate.dialect_resolvers causes failures

This commit is contained in:
Steve Ebersole 2013-10-07 14:38:16 -05:00
parent 4428464d09
commit 3d366a526e
24 changed files with 599 additions and 801 deletions

View File

@ -1,84 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.engine.jdbc.dialect.internal;
import java.util.Map;
import org.hibernate.HibernateException;
import org.hibernate.boot.registry.StandardServiceInitiator;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.jdbc.dialect.spi.DatabaseInfoDialectResolver;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.service.spi.ServiceException;
import org.hibernate.service.spi.ServiceRegistryImplementor;
/**
* Initiator for the DatabaseInfoDialectResolver service
*
* @author Steve Ebersole
*/
public class DatabaseInfoDialectResolverInitiator implements StandardServiceInitiator<DatabaseInfoDialectResolver> {
/**
* Singleton access
*/
public static final DatabaseInfoDialectResolverInitiator INSTANCE = new DatabaseInfoDialectResolverInitiator();
@Override
public Class<DatabaseInfoDialectResolver> getServiceInitiated() {
return DatabaseInfoDialectResolver.class;
}
@Override
public DatabaseInfoDialectResolver initiateService(Map configurationValues, ServiceRegistryImplementor registry) {
final DatabaseInfoDialectResolverSet resolver = new DatabaseInfoDialectResolverSet();
applyCustomReslvers( resolver, configurationValues, registry );
resolver.addResolver( StandardDatabaseInfoDialectResolver.INSTANCE );
return resolver;
}
private void applyCustomReslvers(
DatabaseInfoDialectResolverSet resolver,
Map configurationValues,
ServiceRegistryImplementor registry) {
final String resolverImplNames = (String) configurationValues.get( AvailableSettings.DIALECT_RESOLVERS );
if ( StringHelper.isNotEmpty( resolverImplNames ) ) {
final ClassLoaderService classLoaderService = registry.getService( ClassLoaderService.class );
for ( String resolverImplName : StringHelper.split( ", \n\r\f\t", resolverImplNames ) ) {
try {
resolver.addResolver(
(DatabaseInfoDialectResolver) classLoaderService.classForName( resolverImplName ).newInstance()
);
}
catch (HibernateException e) {
throw e;
}
catch (Exception e) {
throw new ServiceException( "Unable to instantiate named dialect resolver [" + resolverImplName + "]", e );
}
}
}
}
}

View File

@ -1,99 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.engine.jdbc.dialect.internal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.dialect.spi.DatabaseInfoDialectResolver;
/**
* Implements the DatabaseInfoDialectResolver as a chain, allowing multiple delegate DatabaseInfoDialectResolver
* implementations to coordinate resolution
*
* @author Steve Ebersole
*/
public class DatabaseInfoDialectResolverSet implements DatabaseInfoDialectResolver {
private List<DatabaseInfoDialectResolver> delegateResolvers;
/**
* Constructs a DatabaseInfoDialectResolverSet
*/
public DatabaseInfoDialectResolverSet() {
this( new ArrayList<DatabaseInfoDialectResolver>() );
}
/**
* Constructs a DatabaseInfoDialectResolverSet
*
* @param delegateResolvers The set of delegate resolvers
*/
public DatabaseInfoDialectResolverSet(List<DatabaseInfoDialectResolver> delegateResolvers) {
this.delegateResolvers = delegateResolvers;
}
/**
* Constructs a DatabaseInfoDialectResolverSet
*
* @param delegateResolvers The set of delegate resolvers
*/
@SuppressWarnings("UnusedDeclaration")
public DatabaseInfoDialectResolverSet(DatabaseInfoDialectResolver... delegateResolvers) {
this( Arrays.asList( delegateResolvers ) );
}
@Override
public Dialect resolve(DatabaseInfo databaseInfo) {
for ( DatabaseInfoDialectResolver resolver : delegateResolvers ) {
final Dialect dialect = resolver.resolve( databaseInfo );
if ( dialect != null ) {
return dialect;
}
}
return null;
}
/**
* Add a resolver at the end of the underlying resolver list. The resolver added by this method is at lower
* priority than any other existing resolvers.
*
* @param resolver The resolver to add.
*/
public void addResolver(DatabaseInfoDialectResolver resolver) {
delegateResolvers.add( resolver );
}
/**
* Add a resolver at the beginning of the underlying resolver list. The resolver added by this method is at higher
* priority than any other existing resolvers.
*
* @param resolver The resolver to add.
*/
@SuppressWarnings("UnusedDeclaration")
public void addResolverAtFirst(DatabaseInfoDialectResolver resolver) {
delegateResolvers.add( 0, resolver );
}
}

View File

@ -23,9 +23,6 @@
*/
package org.hibernate.engine.jdbc.dialect.internal;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.util.Map;
import org.hibernate.HibernateException;
@ -34,37 +31,44 @@ import org.hibernate.boot.registry.selector.spi.StrategySelector;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.dialect.spi.DialectFactory;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfoSource;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolver;
import org.hibernate.service.spi.InjectService;
import org.hibernate.service.spi.ServiceRegistryAwareService;
import org.hibernate.service.spi.ServiceRegistryImplementor;
/**
* Standard implementation of the {@link DialectFactory} service.
*
* @author Steve Ebersole
*/
public class DialectFactoryImpl implements DialectFactory {
public class DialectFactoryImpl implements DialectFactory, ServiceRegistryAwareService {
private StrategySelector strategySelector;
@InjectService
public void setStrategySelector(StrategySelector strategySelector) {
this.strategySelector = strategySelector;
}
private DialectResolver dialectResolver;
@InjectService
@Override
public void injectServices(ServiceRegistryImplementor serviceRegistry) {
this.strategySelector = serviceRegistry.getService( StrategySelector.class );
this.dialectResolver = serviceRegistry.getService( DialectResolver.class );
}
/**
* Intended only for use from testing.
*
* @param dialectResolver The DialectResolver to use
*/
public void setDialectResolver(DialectResolver dialectResolver) {
this.dialectResolver = dialectResolver;
}
@Override
public Dialect buildDialect(Map configValues, Connection connection) throws HibernateException {
public Dialect buildDialect(Map configValues, DialectResolutionInfoSource resolutionInfoSource) throws HibernateException {
final String dialectName = (String) configValues.get( AvailableSettings.DIALECT );
if ( !StringHelper.isEmpty( dialectName ) ) {
return constructDialect( dialectName );
}
else {
return determineDialect( connection );
return determineDialect( resolutionInfoSource );
}
}
@ -88,36 +92,29 @@ public class DialectFactoryImpl implements DialectFactory {
/**
* Determine the appropriate Dialect to use given the connection.
*
* @param connection The configured connection.
* @param resolutionInfoSource Access to DialectResolutionInfo used to resolve the Dialect.
*
* @return The appropriate dialect instance.
*
* @throws HibernateException No connection given or no resolver could make
* the determination from the given connection.
*/
private Dialect determineDialect(Connection connection) {
if ( connection == null ) {
throw new HibernateException( "Connection cannot be null when 'hibernate.dialect' not set" );
private Dialect determineDialect(DialectResolutionInfoSource resolutionInfoSource) {
if ( resolutionInfoSource == null ) {
throw new HibernateException( "Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set" );
}
try {
final DatabaseMetaData databaseMetaData = connection.getMetaData();
final Dialect dialect = dialectResolver.resolveDialect( databaseMetaData );
final DialectResolutionInfo info = resolutionInfoSource.getDialectResolutionInfo();
final Dialect dialect = dialectResolver.resolveDialect( info );
if ( dialect == null ) {
throw new HibernateException(
"Unable to determine Dialect to use [name=" + databaseMetaData.getDatabaseProductName() +
", majorVersion=" + databaseMetaData.getDatabaseMajorVersion() +
"]; user must register resolver or explicitly set 'hibernate.dialect'"
);
}
return dialect;
}
catch ( SQLException sqlException ) {
if ( dialect == null ) {
throw new HibernateException(
"Unable to access java.sql.DatabaseMetaData to determine appropriate Dialect to use",
sqlException
"Unable to determine Dialect to use [name=" + info.getDatabaseName() +
", majorVersion=" + info.getDatabaseMajorVersion() +
"]; user must register resolver or explicitly set 'hibernate.dialect'"
);
}
return dialect;
}
}

View File

@ -29,7 +29,6 @@ import org.hibernate.HibernateException;
import org.hibernate.boot.registry.StandardServiceInitiator;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.jdbc.dialect.spi.DatabaseInfoDialectResolver;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolver;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.service.spi.ServiceException;
@ -55,12 +54,10 @@ public class DialectResolverInitiator implements StandardServiceInitiator<Dialec
@Override
public DialectResolver initiateService(Map configurationValues, ServiceRegistryImplementor registry) {
final DialectResolverSet resolver = new DialectResolverSet();
applyCustomerResolvers( resolver, registry, configurationValues );
resolver.addResolver(
new StandardDatabaseMetaDataDialectResolver(
registry.getService( DatabaseInfoDialectResolver.class )
)
);
resolver.addResolver(StandardDialectResolver.INSTANCE );
return resolver;
}

View File

@ -23,68 +23,45 @@
*/
package org.hibernate.engine.jdbc.dialect.internal;
import java.sql.DatabaseMetaData;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.jboss.logging.Logger;
import org.hibernate.dialect.Dialect;
import org.hibernate.exception.JDBCConnectionException;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolver;
import org.hibernate.exception.JDBCConnectionException;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
/**
* A {@link DialectResolver} implementation which coordinates resolution by delegating to sub-resolvers.
*
* @author Tomoto Shimizu Washio
* @author Steve Ebersole
*
* @deprecated See deprecation on {@link DialectResolver}
*/
@Deprecated
public class DialectResolverSet implements DialectResolver {
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
CoreMessageLogger.class,
DialectResolverSet.class.getName()
);
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( DialectResolverSet.class );
private List<DialectResolver> resolvers;
/**
* Deprecated
*/
public DialectResolverSet() {
this( new ArrayList<DialectResolver>() );
LOG.debug( "DialectResolverSet is deprecated" );
}
/**
* Deprecated
*
* @param resolvers The delegate resolvers
*/
public DialectResolverSet(List<DialectResolver> resolvers) {
this.resolvers = resolvers;
LOG.debug( "DialectResolverSet is deprecated" );
}
/**
* Deprecated
*
* @param resolvers The delegate resolvers
*/
public DialectResolverSet(DialectResolver... resolvers) {
this( Arrays.asList( resolvers ) );
LOG.debug( "DialectResolverSet is deprecated" );
}
@Override
public Dialect resolveDialect(DatabaseMetaData metaData) throws JDBCConnectionException {
public Dialect resolveDialect(DialectResolutionInfo info) {
for ( DialectResolver resolver : resolvers ) {
try {
final Dialect dialect = resolver.resolveDialect( metaData );
final Dialect dialect = resolver.resolveDialect( info );
if ( dialect != null ) {
return dialect;
}
@ -93,9 +70,10 @@ public class DialectResolverSet implements DialectResolver {
throw e;
}
catch ( Exception e ) {
LOG.exceptionInSubResolver(e.getMessage());
LOG.exceptionInSubResolver( e.getMessage() );
}
}
return null;
}

View File

@ -1,100 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2010, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.engine.jdbc.dialect.internal;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.dialect.spi.BasicSQLExceptionConverter;
import org.hibernate.engine.jdbc.dialect.spi.AbstractDatabaseMetaDataDialectResolver;
import org.hibernate.engine.jdbc.dialect.spi.DatabaseInfoDialectResolver;
/**
* The standard Hibernate Dialect resolver.
*
* @author Steve Ebersole
*/
public class StandardDatabaseMetaDataDialectResolver extends AbstractDatabaseMetaDataDialectResolver {
private final DatabaseInfoDialectResolver infoResolver;
/**
* Constructs a StandardDatabaseMetaDataDialectResolver
*
* @param infoResolver The delegate resolver
*/
public StandardDatabaseMetaDataDialectResolver(DatabaseInfoDialectResolver infoResolver) {
this.infoResolver = infoResolver;
}
/**
* A DatabaseInfo implementation wrapping a JDBC DatabaseMetaData reference
*/
public static final class DatabaseInfoImpl implements DatabaseInfoDialectResolver.DatabaseInfo {
private final DatabaseMetaData databaseMetaData;
protected DatabaseInfoImpl(DatabaseMetaData databaseMetaData) {
this.databaseMetaData = databaseMetaData;
}
@Override
public String getDatabaseName() {
try {
return databaseMetaData.getDatabaseProductName();
}
catch (SQLException e) {
throw BasicSQLExceptionConverter.INSTANCE.convert( e );
}
}
@Override
public int getDatabaseMajorVersion() {
try {
return databaseMetaData.getDatabaseMajorVersion();
}
catch (SQLException e) {
throw BasicSQLExceptionConverter.INSTANCE.convert( e );
}
}
@Override
public int getDatabaseMinorVersion() {
try {
return databaseMetaData.getDatabaseMinorVersion();
}
catch (SQLException e) {
throw BasicSQLExceptionConverter.INSTANCE.convert( e );
}
}
}
@Override
protected Dialect resolveDialectInternal(DatabaseMetaData metaData) throws SQLException {
if ( infoResolver == null ) {
return null;
}
return infoResolver.resolve( new DatabaseInfoImpl( metaData ) );
}
}

View File

@ -52,29 +52,27 @@ import org.hibernate.dialect.SQLServer2012Dialect;
import org.hibernate.dialect.SQLServerDialect;
import org.hibernate.dialect.SybaseASE15Dialect;
import org.hibernate.dialect.SybaseAnywhereDialect;
import org.hibernate.engine.jdbc.dialect.spi.DatabaseInfoDialectResolver;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolver;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.jboss.logging.Logger;
/**
* The standard DatabaseInfoDialectResolver implementation
* The standard DialectResolver implementation
*
* @author Steve Ebersole
*/
public class StandardDatabaseInfoDialectResolver implements DatabaseInfoDialectResolver {
public class StandardDialectResolver implements DialectResolver {
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( StandardDialectResolver.class );
/**
* Singleton access
*/
public static final StandardDatabaseInfoDialectResolver INSTANCE = new StandardDatabaseInfoDialectResolver();
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
CoreMessageLogger.class,
StandardDatabaseInfoDialectResolver.class.getName()
);
public static final StandardDialectResolver INSTANCE = new StandardDialectResolver();
@Override
public Dialect resolve(DatabaseInfo databaseInfo) {
final String databaseName = databaseInfo.getDatabaseName();
public Dialect resolveDialect(DialectResolutionInfo info) {
final String databaseName = info.getDatabaseName();
if ( "CUBRID".equalsIgnoreCase( databaseName ) ) {
return new CUBRIDDialect();
@ -89,7 +87,7 @@ public class StandardDatabaseInfoDialectResolver implements DatabaseInfoDialectR
}
if ( "MySQL".equals( databaseName ) ) {
final int majorVersion = databaseInfo.getDatabaseMajorVersion();
final int majorVersion = info.getDatabaseMajorVersion();
if (majorVersion >= 5 ) {
return new MySQL5Dialect();
@ -99,8 +97,8 @@ public class StandardDatabaseInfoDialectResolver implements DatabaseInfoDialectR
}
if ( "PostgreSQL".equals( databaseName ) ) {
final int majorVersion = databaseInfo.getDatabaseMajorVersion();
final int minorVersion = databaseInfo.getDatabaseMinorVersion();
final int majorVersion = info.getDatabaseMajorVersion();
final int minorVersion = info.getDatabaseMinorVersion();
if ( majorVersion == 9 ) {
return new PostgreSQL9Dialect();
@ -118,8 +116,8 @@ public class StandardDatabaseInfoDialectResolver implements DatabaseInfoDialectR
}
if ( "Apache Derby".equals( databaseName ) ) {
final int majorVersion = databaseInfo.getDatabaseMajorVersion();
final int minorVersion = databaseInfo.getDatabaseMinorVersion();
final int majorVersion = info.getDatabaseMajorVersion();
final int minorVersion = info.getDatabaseMinorVersion();
if ( majorVersion > 10 || ( majorVersion == 10 && minorVersion >= 7 ) ) {
return new DerbyTenSevenDialect();
@ -136,8 +134,8 @@ public class StandardDatabaseInfoDialectResolver implements DatabaseInfoDialectR
}
if ( "ingres".equalsIgnoreCase( databaseName ) ) {
final int majorVersion = databaseInfo.getDatabaseMajorVersion();
final int minorVersion = databaseInfo.getDatabaseMinorVersion();
final int majorVersion = info.getDatabaseMajorVersion();
final int minorVersion = info.getDatabaseMinorVersion();
switch ( majorVersion ) {
case 9:
@ -154,7 +152,7 @@ public class StandardDatabaseInfoDialectResolver implements DatabaseInfoDialectR
}
if ( databaseName.startsWith( "Microsoft SQL Server" ) ) {
final int majorVersion = databaseInfo.getDatabaseMajorVersion();
final int majorVersion = info.getDatabaseMajorVersion();
switch ( majorVersion ) {
case 8:
@ -192,7 +190,7 @@ public class StandardDatabaseInfoDialectResolver implements DatabaseInfoDialectR
}
if ( "Oracle".equals( databaseName ) ) {
final int majorVersion = databaseInfo.getDatabaseMajorVersion();
final int majorVersion = info.getDatabaseMajorVersion();
switch ( majorVersion ) {
case 11:

View File

@ -1,82 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2010, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.engine.jdbc.dialect.spi;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import org.jboss.logging.Logger;
import org.hibernate.JDBCException;
import org.hibernate.dialect.Dialect;
import org.hibernate.exception.JDBCConnectionException;
import org.hibernate.internal.CoreMessageLogger;
/**
* A templated resolver impl which delegates to the {@link #resolveDialectInternal} method
* and handles any thrown {@link SQLException SQL errors}.
*
* @author Steve Ebersole
*/
public abstract class AbstractDatabaseMetaDataDialectResolver implements DialectResolver {
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
CoreMessageLogger.class,
AbstractDatabaseMetaDataDialectResolver.class.getName()
);
/**
* {@inheritDoc}
* <p/>
* Here we template the resolution, delegating to {@link #resolveDialectInternal} and handling
* {@link java.sql.SQLException}s properly.
*/
@Override
public final Dialect resolveDialect(DatabaseMetaData metaData) {
try {
return resolveDialectInternal( metaData );
}
catch ( SQLException sqlException ) {
final JDBCException jdbcException = BasicSQLExceptionConverter.INSTANCE.convert( sqlException );
if (jdbcException instanceof JDBCConnectionException) {
throw jdbcException;
}
LOG.warnf( "%s : %s", BasicSQLExceptionConverter.MSG, sqlException.getMessage() );
return null;
}
catch ( Throwable t ) {
LOG.unableToExecuteResolver( this, t.getMessage() );
return null;
}
}
/**
* Perform the actual resolution without caring about handling {@link SQLException}s.
*
* @param metaData The database metadata
* @return The resolved dialect, or null if we could not resolve.
* @throws SQLException Indicates problems accessing the metadata.
*/
protected abstract Dialect resolveDialectInternal(DatabaseMetaData metaData) throws SQLException;
}

View File

@ -21,64 +21,69 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.engine.jdbc.dialect.internal;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
package org.hibernate.engine.jdbc.dialect.spi;
import org.hibernate.HibernateException;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.dialect.spi.AbstractDatabaseMetaDataDialectResolver;
import static org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo.NO_VERSION;
/**
* Intended as support for custom resolvers.
* Intended as support for custom resolvers which match a single db name (with optional version info).
*
* @author Steve Ebersole
*
* @deprecated Purpose has shifted to new {@link org.hibernate.engine.jdbc.dialect.spi.DatabaseInfoDialectResolver}
* contract. See <a href="https://hibernate.onjira.com/browse/HHH-7965">HHH-7965</a> for details.
*/
@Deprecated
public class BasicDialectResolver extends AbstractDatabaseMetaDataDialectResolver {
/**
* Constant indicating no version info was given
*/
public static final int VERSION_INSENSITIVE_VERSION = -9999;
public class BasicDialectResolver implements DialectResolver {
private final String nameToMatch;
private final int majorVersionToMatch;
private final int minorVersionToMatch;
private final String matchingName;
private final int matchingVersion;
private final Class dialectClass;
/**
* Constructs a BasicDialectResolver
*
* @param matchingName The name of the driver to match on
* @param nameToMatch The name of the driver to match on
* @param dialectClass The Dialect class to use on match
*/
public BasicDialectResolver(String matchingName, Class dialectClass) {
this( matchingName, VERSION_INSENSITIVE_VERSION, dialectClass );
public BasicDialectResolver(String nameToMatch, Class dialectClass) {
this( nameToMatch, NO_VERSION, dialectClass );
}
/**
* Constructs a BasicDialectResolver
*
* @param matchingName The name of the driver to match on
* @param matchingVersion The version of the driver to match on
* @param nameToMatch The name of the driver to match on
* @param majorVersionToMatch The version of the driver to match on
* @param dialectClass The Dialect class to use on match
*/
public BasicDialectResolver(String matchingName, int matchingVersion, Class dialectClass) {
this.matchingName = matchingName;
this.matchingVersion = matchingVersion;
public BasicDialectResolver(String nameToMatch, int majorVersionToMatch, Class dialectClass) {
this( nameToMatch, majorVersionToMatch, NO_VERSION, dialectClass );
}
/**
* Constructs a BasicDialectResolver
*
* @param nameToMatch The name of the driver to match on
* @param majorVersionToMatch The version of the driver to match on
* @param dialectClass The Dialect class to use on match
*/
public BasicDialectResolver(String nameToMatch, int majorVersionToMatch, int minorVersionToMatch, Class dialectClass) {
this.nameToMatch = nameToMatch;
this.majorVersionToMatch = majorVersionToMatch;
this.minorVersionToMatch = minorVersionToMatch;
this.dialectClass = dialectClass;
}
@Override
protected final Dialect resolveDialectInternal(DatabaseMetaData metaData) throws SQLException {
final String databaseName = metaData.getDatabaseProductName();
final int databaseMajorVersion = metaData.getDatabaseMajorVersion();
public final Dialect resolveDialect(DialectResolutionInfo info) {
final String databaseName = info.getDatabaseName();
final int databaseMajorVersion = info.getDatabaseMajorVersion();
final int databaseMinorVersion = info.getDatabaseMinorVersion();
if ( matchingName.equalsIgnoreCase( databaseName )
&& ( matchingVersion == VERSION_INSENSITIVE_VERSION || matchingVersion == databaseMajorVersion ) ) {
if ( nameToMatch.equalsIgnoreCase( databaseName )
&& ( majorVersionToMatch == NO_VERSION || majorVersionToMatch == databaseMajorVersion )
&& ( minorVersionToMatch == NO_VERSION || majorVersionToMatch == databaseMinorVersion ) ) {
try {
return (Dialect) dialectClass.newInstance();
}

View File

@ -29,6 +29,7 @@ import org.jboss.logging.Logger;
import org.hibernate.JDBCException;
import org.hibernate.exception.internal.SQLStateConverter;
import org.hibernate.exception.spi.ViolatedConstraintNameExtracter;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
/**
@ -39,10 +40,7 @@ import org.hibernate.internal.CoreMessageLogger;
* @author Steve Ebersole
*/
public class BasicSQLExceptionConverter {
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
CoreMessageLogger.class,
BasicSQLExceptionConverter.class.getName()
);
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( BasicSQLExceptionConverter.class );
/**
* Singleton access
@ -67,9 +65,6 @@ public class BasicSQLExceptionConverter {
}
private static class ConstraintNameExtracter implements ViolatedConstraintNameExtracter {
/**
* {@inheritDoc}
*/
@Override
public String extractConstraintName(SQLException sqle) {
return "???";

View File

@ -1,84 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.engine.jdbc.dialect.spi;
import org.hibernate.dialect.Dialect;
import org.hibernate.service.Service;
/**
* A contract for resolving database name, major version and minor version to Dialect
*
* @author Steve Ebersole
*/
public interface DatabaseInfoDialectResolver extends Service {
/**
* Determine the {@link Dialect} to use based on the given information. Implementations are
* expected to return the {@link Dialect} instance to use, or {@code null} if the they did not locate a match.
*
* @param databaseInfo Access to the needed database information
*
* @return The dialect to use, or null.
*/
public Dialect resolve(DatabaseInfo databaseInfo);
/**
* Essentially a "parameter object" for {@link DatabaseInfoDialectResolver#resolve}
*/
public static interface DatabaseInfo {
/**
* Constant used to indicate that no version is defined
*/
public static final int NO_VERSION = -9999;
/**
* Obtain access to the database name, as returned from {@link java.sql.DatabaseMetaData#getDatabaseProductName()}
* for the target database
*
* @return The database name
*/
public String getDatabaseName();
/**
* Obtain access to the database major version, as returned from
* {@link java.sql.DatabaseMetaData#getDatabaseMajorVersion()} for the target database; {@value #NO_VERSION}
* indicates no version information was supplied
*
* @return The major version
*
* @see #NO_VERSION
*/
public int getDatabaseMajorVersion();
/**
* Obtain access to the database minor version, as returned from
* {@link java.sql.DatabaseMetaData#getDatabaseMinorVersion()} for the target database; {@value #NO_VERSION}
* indicates no version information was supplied
*
* @return The minor version
*
* @see #NO_VERSION
*/
public int getDatabaseMinorVersion();
}
}

View File

@ -0,0 +1,100 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.engine.jdbc.dialect.spi;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import org.hibernate.engine.jdbc.dialect.spi.BasicSQLExceptionConverter;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
/**
* An implementation of DialectResolutionInfo that delegates calls to a wrapped {@link DatabaseMetaData}.
* <p/>
* All {@link SQLException}s resulting from calls on the DatabaseMetaData are converted to the Hibernate
* {@link org.hibernate.JDBCException} hierarchy.
*
* @author Steve Ebersole
*/
public class DatabaseMetaDataDialectResolutionInfoAdapter implements DialectResolutionInfo {
private final DatabaseMetaData databaseMetaData;
public DatabaseMetaDataDialectResolutionInfoAdapter(DatabaseMetaData databaseMetaData) {
this.databaseMetaData = databaseMetaData;
}
@Override
public String getDatabaseName() {
try {
return databaseMetaData.getDatabaseProductName();
}
catch (SQLException e) {
throw BasicSQLExceptionConverter.INSTANCE.convert( e );
}
}
@Override
public int getDatabaseMajorVersion() {
try {
return interpretVersion( databaseMetaData.getDatabaseMajorVersion() );
}
catch (SQLException e) {
throw BasicSQLExceptionConverter.INSTANCE.convert( e );
}
}
private static int interpretVersion(int result) {
return result < 0 ? NO_VERSION : result;
}
@Override
public int getDatabaseMinorVersion() {
try {
return interpretVersion( databaseMetaData.getDatabaseMinorVersion() );
}
catch (SQLException e) {
throw BasicSQLExceptionConverter.INSTANCE.convert( e );
}
}
@Override
public String getDriverName() {
try {
return databaseMetaData.getDriverName();
}
catch (SQLException e) {
throw BasicSQLExceptionConverter.INSTANCE.convert( e );
}
}
@Override
public int getDriverMajorVersion() {
return interpretVersion( databaseMetaData.getDriverMajorVersion() );
}
@Override
public int getDriverMinorVersion() {
return interpretVersion( databaseMetaData.getDriverMinorVersion() );
}
}

View File

@ -23,7 +23,6 @@
*/
package org.hibernate.engine.jdbc.dialect.spi;
import java.sql.Connection;
import java.util.Map;
import org.hibernate.HibernateException;
@ -46,11 +45,12 @@ public interface DialectFactory extends Service {
* the determination from the given connection.
*
* @param configValues The configuration properties.
* @param connection The configured connection.
* @param resolutionInfoSource Access to DialectResolutionInfo used to resolve the Dialect to use if not
* explicitly named
*
* @return The appropriate dialect instance.
*
* @throws HibernateException No dialect specified and no resolver could make the determination.
*/
public Dialect buildDialect(Map configValues, Connection connection) throws HibernateException;
public Dialect buildDialect(Map configValues, DialectResolutionInfoSource resolutionInfoSource) throws HibernateException;
}

View File

@ -0,0 +1,102 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.engine.jdbc.dialect.spi;
/**
* Exposes information about the database and JDBC driver that can be used in resolving the appropriate Dialect
* to use.
* <p/>
* The information here mimics part of the JDBC {@link java.sql.DatabaseMetaData} contract, specifically the portions
* about database and driver names and versions.
*
* @author Steve Ebersole
*/
public interface DialectResolutionInfo {
/**
* Constant used to indicate that no version is defined
*/
public static final int NO_VERSION = -9999;
/**
* Obtain access to the database name, as returned from {@link java.sql.DatabaseMetaData#getDatabaseProductName()}
* for the target database
*
* @return The database name
*
* @see java.sql.DatabaseMetaData#getDatabaseProductName()
*/
public String getDatabaseName();
/**
* Obtain access to the database major version, as returned from
* {@link java.sql.DatabaseMetaData#getDatabaseMajorVersion()} for the target database.
*
* @return The database major version, or {@value #NO_VERSION} to indicate "no version information"
*
* @see java.sql.DatabaseMetaData#getDatabaseMajorVersion()
*/
public int getDatabaseMajorVersion();
/**
* Obtain access to the database minor version, as returned from
* {@link java.sql.DatabaseMetaData#getDatabaseMinorVersion()} for the target database.
*
* @return The database minor version, or {@value #NO_VERSION} to indicate "no version information"
*
* @see java.sql.DatabaseMetaData#getDatabaseMinorVersion()
*/
public int getDatabaseMinorVersion();
/**
* Obtain access to the name of the JDBC driver, as returned from {@link java.sql.DatabaseMetaData#getDriverName()}
* for the target database
*
* @return The JDBC driver name
*
* @see java.sql.DatabaseMetaData#getDriverName()
*/
public String getDriverName();
/**
* Obtain access to the major version of the JDBC driver, as returned from
* {@link java.sql.DatabaseMetaData#getDriverMajorVersion()} ()} for the target database.
*
* @return The JDBC driver major version, or {@value #NO_VERSION} to indicate "no version information"
*
* @see java.sql.DatabaseMetaData#getDriverMajorVersion()
*/
public int getDriverMajorVersion();
/**
* Obtain access to the minor version of the JDBC driver, as returned from
* {@link java.sql.DatabaseMetaData#getDriverMinorVersion()} for the target database.
*
* @return The JDBC driver minor version, or {@value #NO_VERSION} to indicate "no version information"
*
* @see java.sql.DatabaseMetaData#getDriverMinorVersion()
*/
public int getDriverMinorVersion();
}

View File

@ -23,30 +23,16 @@
*/
package org.hibernate.engine.jdbc.dialect.spi;
import java.sql.DatabaseMetaData;
import org.hibernate.dialect.Dialect;
import org.hibernate.exception.JDBCConnectionException;
import org.hibernate.service.Service;
/**
* Contract for determining the {@link Dialect} to use based on a JDBC {@link java.sql.Connection}.
* Contract for the source of DialectResolutionInfo.
*
* @author Tomoto Shimizu Washio
* @author Steve Ebersole
*/
public interface DatabaseMetaDataDialectResolver extends Service {
public interface DialectResolutionInfoSource {
/**
* Determine the {@link org.hibernate.dialect.Dialect} to use based on the given JDBC {@link java.sql.DatabaseMetaData}. Implementations are
* expected to return the {@link org.hibernate.dialect.Dialect} instance to use, or null if the {@link java.sql.DatabaseMetaData} does not match
* the criteria handled by this impl.
* Get the DialectResolutionInfo
*
* @param metaData The JDBC metadata.
*
* @return The dialect to use, or null.
*
* @throws org.hibernate.exception.JDBCConnectionException Indicates a 'non transient connection problem', which indicates that
* we should stop resolution attempts.
* @return The DialectResolutionInfo
*/
public Dialect resolveDialect(DatabaseMetaData metaData) throws JDBCConnectionException;
public DialectResolutionInfo getDialectResolutionInfo();
}

View File

@ -23,15 +23,23 @@
*/
package org.hibernate.engine.jdbc.dialect.spi;
import org.hibernate.dialect.Dialect;
import org.hibernate.service.Service;
/**
* Deprecated
* Contract for determining the {@link Dialect} to use based on information about the database / driver.
*
* @deprecated Deprecated in favor of {@link DatabaseMetaDataDialectResolver} to account for resolving by name versus
* by DatabaseMetaData
*
* @see DatabaseMetaDataDialectResolver
* @see DatabaseInfoDialectResolver
* @author Tomoto Shimizu Washio
* @author Steve Ebersole
*/
@Deprecated
public interface DialectResolver extends DatabaseMetaDataDialectResolver {
public interface DialectResolver extends Service {
/**
* Determine the {@link Dialect} to use based on the given information. Implementations are expected to return
* the {@link Dialect} instance to use, or {@code null} if the they did not locate a match.
*
* @param info Access to the information about the database/driver needed to perform the resolution
*
* @return The dialect to use, or null.
*/
public Dialect resolveDialect(DialectResolutionInfo info);
}

View File

@ -36,11 +36,16 @@ import java.util.Set;
import org.jboss.logging.Logger;
import org.hibernate.HibernateException;
import org.hibernate.MultiTenancyStrategy;
import org.hibernate.cfg.Environment;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.LobCreationContext;
import org.hibernate.engine.jdbc.LobCreator;
import org.hibernate.engine.jdbc.dialect.spi.BasicSQLExceptionConverter;
import org.hibernate.engine.jdbc.dialect.spi.DatabaseMetaDataDialectResolutionInfoAdapter;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfoSource;
import org.hibernate.engine.jdbc.spi.ExtractedDatabaseMetaData;
import org.hibernate.engine.jdbc.spi.JdbcConnectionAccess;
import org.hibernate.engine.jdbc.spi.JdbcServices;
@ -162,7 +167,23 @@ public class JdbcServicesImpl implements JdbcServices, ServiceRegistryAwareServi
lobLocatorUpdateCopy = meta.locatorsUpdateCopy();
typeInfoSet.addAll( TypeInfo.extractTypeInfo( meta ) );
dialect = dialectFactory.buildDialect( configValues, connection );
dialect = dialectFactory.buildDialect(
configValues,
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
);
}
}
}
);
catalogName = connection.getCatalog();
final SchemaNameResolver schemaNameResolver = determineExplicitSchemaNameResolver( configValues );

View File

@ -29,24 +29,23 @@ import java.util.List;
import org.hibernate.boot.registry.StandardServiceInitiator;
import org.hibernate.cache.internal.RegionFactoryInitiator;
import org.hibernate.engine.jdbc.batch.internal.BatchBuilderInitiator;
import org.hibernate.engine.jdbc.dialect.internal.DatabaseInfoDialectResolverInitiator;
import org.hibernate.engine.jdbc.internal.JdbcServicesInitiator;
import org.hibernate.engine.transaction.internal.TransactionFactoryInitiator;
import org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformResolverInitiator;
import org.hibernate.id.factory.internal.MutableIdentifierGeneratorFactoryInitiator;
import org.hibernate.persister.internal.PersisterClassResolverInitiator;
import org.hibernate.persister.internal.PersisterFactoryInitiator;
import org.hibernate.engine.config.internal.ConfigurationServiceInitiator;
import org.hibernate.service.internal.SessionFactoryServiceRegistryFactoryInitiator;
import org.hibernate.engine.jdbc.batch.internal.BatchBuilderInitiator;
import org.hibernate.engine.jdbc.connections.internal.ConnectionProviderInitiator;
import org.hibernate.engine.jdbc.connections.internal.MultiTenantConnectionProviderInitiator;
import org.hibernate.engine.jdbc.cursor.internal.RefCursorSupportInitiator;
import org.hibernate.engine.jdbc.dialect.internal.DialectFactoryInitiator;
import org.hibernate.engine.jdbc.dialect.internal.DialectResolverInitiator;
import org.hibernate.jmx.internal.JmxServiceInitiator;
import org.hibernate.engine.jdbc.internal.JdbcServicesInitiator;
import org.hibernate.engine.jndi.internal.JndiServiceInitiator;
import org.hibernate.engine.transaction.internal.TransactionFactoryInitiator;
import org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformInitiator;
import org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformResolverInitiator;
import org.hibernate.id.factory.internal.MutableIdentifierGeneratorFactoryInitiator;
import org.hibernate.jmx.internal.JmxServiceInitiator;
import org.hibernate.persister.internal.PersisterClassResolverInitiator;
import org.hibernate.persister.internal.PersisterFactoryInitiator;
import org.hibernate.service.internal.SessionFactoryServiceRegistryFactoryInitiator;
import org.hibernate.tool.hbm2ddl.ImportSqlCommandExtractorInitiator;
/**
@ -71,7 +70,6 @@ public class StandardServiceInitiators {
serviceInitiators.add( ConnectionProviderInitiator.INSTANCE );
serviceInitiators.add( MultiTenantConnectionProviderInitiator.INSTANCE );
serviceInitiators.add( DatabaseInfoDialectResolverInitiator.INSTANCE );
serviceInitiators.add( DialectResolverInitiator.INSTANCE );
serviceInitiators.add( DialectFactoryInitiator.INSTANCE );
serviceInitiators.add( BatchBuilderInitiator.INSTANCE );

View File

@ -22,12 +22,10 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import org.hibernate.HibernateException;
import org.hibernate.engine.jdbc.dialect.internal.BasicDialectResolver;
import org.hibernate.engine.jdbc.dialect.spi.AbstractDatabaseMetaDataDialectResolver;
import org.hibernate.engine.jdbc.dialect.spi.BasicDialectResolver;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolver;
/**
* @author Steve Ebersole
@ -46,10 +44,11 @@ public class TestingDialects {
public static class MySpecialDB2Dialect extends Dialect {
}
public static class MyDialectResolver1 extends AbstractDatabaseMetaDataDialectResolver {
protected Dialect resolveDialectInternal(DatabaseMetaData metaData) throws SQLException {
String databaseName = metaData.getDatabaseProductName();
int databaseMajorVersion = metaData.getDatabaseMajorVersion();
public static class MyDialectResolver1 implements DialectResolver {
@Override
public Dialect resolveDialect(DialectResolutionInfo info) {
String databaseName = info.getDatabaseName();
int databaseMajorVersion = info.getDatabaseMajorVersion();
if ( "MyDatabase1".equals( databaseName ) ) {
return new MyDialect1();
}
@ -71,31 +70,6 @@ public class TestingDialects {
}
}
public static class ErrorDialectResolver1 extends AbstractDatabaseMetaDataDialectResolver {
public Dialect resolveDialectInternal(DatabaseMetaData metaData) throws SQLException {
String databaseName = metaData.getDatabaseProductName();
if ( databaseName.equals( "ConnectionErrorDatabase1" ) ) {
throw new SQLException( "Simulated connection error", "08001" );
}
else {
throw new SQLException();
}
}
}
public static class ErrorDialectResolver2 extends AbstractDatabaseMetaDataDialectResolver {
public Dialect resolveDialectInternal(DatabaseMetaData metaData) throws SQLException {
String databaseName = metaData.getDatabaseProductName();
if ( databaseName.equals( "ErrorDatabase1" ) ) {
throw new SQLException();
}
if ( databaseName.equals( "ErrorDatabase2" ) ) {
throw new HibernateException( "This is a trap!" );
}
return null;
}
}
public static class MyOverridingDialectResolver1 extends BasicDialectResolver {
public MyOverridingDialectResolver1() {
super( "DB2/MySpecialPlatform", MySpecialDB2Dialect.class );

View File

@ -23,10 +23,6 @@
*/
package org.hibernate.dialect.resolver;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;
import java.sql.Connection;
import java.util.Collections;
import java.util.HashMap;
@ -34,8 +30,10 @@ import java.util.Map;
import java.util.Properties;
import org.hibernate.HibernateException;
import org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl;
import org.hibernate.boot.registry.selector.internal.StrategySelectorBuilder;
import org.hibernate.boot.registry.BootstrapServiceRegistry;
import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.boot.registry.selector.spi.StrategySelectionException;
import org.hibernate.cfg.Environment;
import org.hibernate.dialect.DB2400Dialect;
@ -44,6 +42,7 @@ import org.hibernate.dialect.DerbyDialect;
import org.hibernate.dialect.DerbyTenFiveDialect;
import org.hibernate.dialect.DerbyTenSevenDialect;
import org.hibernate.dialect.DerbyTenSixDialect;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.H2Dialect;
import org.hibernate.dialect.HSQLDialect;
import org.hibernate.dialect.InformixDialect;
@ -64,28 +63,35 @@ import org.hibernate.dialect.SybaseAnywhereDialect;
import org.hibernate.dialect.TestingDialects;
import org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl;
import org.hibernate.engine.jdbc.dialect.internal.DialectResolverSet;
import org.hibernate.engine.jdbc.dialect.internal.StandardDatabaseInfoDialectResolver;
import org.hibernate.engine.jdbc.dialect.internal.StandardDatabaseMetaDataDialectResolver;
import org.hibernate.engine.jdbc.dialect.internal.StandardDialectResolver;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfoSource;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolver;
import org.hibernate.testing.junit4.BaseUnitTestCase;
import org.hibernate.service.spi.ServiceRegistryImplementor;
import org.junit.Before;
import org.junit.Test;
import org.hibernate.testing.junit4.BaseUnitTestCase;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;
/**
* @author Steve Ebersole
*/
public class DialectFactoryTest extends BaseUnitTestCase {
private StandardServiceRegistry registry;
private DialectFactoryImpl dialectFactory;
@Before
public void setUp() {
final BootstrapServiceRegistry bootReg = new BootstrapServiceRegistryBuilder().with( DialectFactoryTest.class.getClassLoader() ).build();
registry = new StandardServiceRegistryBuilder( bootReg ).build();
dialectFactory = new DialectFactoryImpl();
dialectFactory.setStrategySelector(
new StrategySelectorBuilder().buildSelector( new ClassLoaderServiceImpl( getClass().getClassLoader() ) )
);
dialectFactory.setDialectResolver(
new StandardDatabaseMetaDataDialectResolver( StandardDatabaseInfoDialectResolver.INSTANCE )
);
dialectFactory.injectServices( (ServiceRegistryImplementor) registry );
}
@Test
@ -143,7 +149,7 @@ public class DialectFactoryTest extends BaseUnitTestCase {
@Test
public void testPreregisteredDialects() {
DialectResolver resolver = new StandardDatabaseMetaDataDialectResolver( StandardDatabaseInfoDialectResolver.INSTANCE );
DialectResolver resolver = StandardDialectResolver.INSTANCE;
testDetermination( "HSQL Database Engine", HSQLDialect.class, resolver );
testDetermination( "H2", H2Dialect.class, resolver );
testDetermination( "MySQL", MySQLDialect.class, resolver );
@ -184,8 +190,6 @@ public class DialectFactoryTest extends BaseUnitTestCase {
DialectResolverSet resolvers = new DialectResolverSet();
resolvers.addResolver( new TestingDialects.MyDialectResolver1() );
resolvers.addResolver( new TestingDialects.MyDialectResolver2() );
resolvers.addResolver( new TestingDialects.ErrorDialectResolver1() );
resolvers.addResolver( new TestingDialects.ErrorDialectResolver2() );
resolvers.addResolver( new TestingDialects.MyOverridingDialectResolver1() );
//DialectFactory.registerDialectResolver( "org.hibernate.dialect.NoSuchDialectResolver" );
//DialectFactory.registerDialectResolver( "java.lang.Object" );
@ -217,7 +221,15 @@ public class DialectFactoryTest extends BaseUnitTestCase {
public void testDialectNotFound() {
Map properties = Collections.EMPTY_MAP;
try {
dialectFactory.buildDialect( properties, Mocks.createConnection( "NoSuchDatabase", 666 ) );
dialectFactory.buildDialect(
properties,
new DialectResolutionInfoSource() {
@Override
public DialectResolutionInfo getDialectResolutionInfo() {
return TestingDialectResolutionInfo.forDatabaseInfo( "NoSuchDatabase", 666 );
}
}
);
fail();
}
catch ( HibernateException e ) {
@ -225,18 +237,30 @@ public class DialectFactoryTest extends BaseUnitTestCase {
}
}
private void testDetermination(String databaseName, Class clazz, DialectResolver resolver) {
testDetermination( databaseName, -9999, clazz, resolver );
private void testDetermination(String databaseName, Class expected, DialectResolver resolver) {
testDetermination( databaseName, -9999, expected, resolver );
}
private void testDetermination(String databaseName, int databaseMajorVersion, Class clazz, DialectResolver resolver) {
testDetermination( databaseName, databaseMajorVersion, -9999, clazz, resolver );
private void testDetermination(String databaseName, int databaseMajorVersion, Class expected, DialectResolver resolver) {
testDetermination( databaseName, databaseMajorVersion, -9999, expected, resolver );
}
private void testDetermination(String databaseName, int majorVersion, int minorVersion, Class clazz, DialectResolver resolver) {
private void testDetermination(
final String databaseName,
final int majorVersion,
final int minorVersion,
Class expected,
DialectResolver resolver) {
dialectFactory.setDialectResolver( resolver );
Properties properties = new Properties();
Connection conn = Mocks.createConnection( databaseName, majorVersion, minorVersion );
assertEquals( clazz, dialectFactory.buildDialect( properties, conn ).getClass() );
Dialect resolved = dialectFactory.buildDialect(
new Properties(),
new DialectResolutionInfoSource() {
@Override
public DialectResolutionInfo getDialectResolutionInfo() {
return TestingDialectResolutionInfo.forDatabaseInfo( databaseName, majorVersion, minorVersion );
}
}
);
assertEquals( expected, resolved.getClass() );
}
}

View File

@ -22,17 +22,18 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect.resolver;
import java.sql.SQLException;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.TestingDialects;
import org.hibernate.engine.jdbc.dialect.internal.DialectResolverSet;
import org.hibernate.engine.jdbc.dialect.spi.BasicDialectResolver;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolver;
import org.hibernate.exception.JDBCConnectionException;
import org.junit.Test;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.Mocks;
import org.hibernate.dialect.TestingDialects;
import org.hibernate.exception.JDBCConnectionException;
import org.hibernate.engine.jdbc.dialect.internal.BasicDialectResolver;
import org.hibernate.engine.jdbc.dialect.internal.DialectResolverSet;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolver;
import org.hibernate.testing.junit4.BaseUnitTestCase;
import static org.junit.Assert.assertEquals;
@ -63,23 +64,12 @@ public class DialectResolverTest extends BaseUnitTestCase {
public void testErrorAndOrder() throws Exception {
DialectResolverSet resolvers = new DialectResolverSet();
resolvers.addResolverAtFirst( new TestingDialects.MyDialectResolver1() );
resolvers.addResolver( new TestingDialects.ErrorDialectResolver1() );
resolvers.addResolverAtFirst( new TestingDialects.ErrorDialectResolver1() );
resolvers.addResolver( new TestingDialects.MyDialectResolver2() );
// Non-connection errors are suppressed.
testDetermination( resolvers, "MyDatabase1", 1, TestingDialects.MyDialect1.class );
testDetermination( resolvers, "MyTrickyDatabase1", 1, TestingDialects.MyDialect1.class );
testDetermination( resolvers, "NoSuchDatabase", 1, null );
// Connection errors are reported
try {
testDetermination( resolvers, "ConnectionErrorDatabase1", 1, null );
fail();
}
catch ( JDBCConnectionException e ) {
// expected
}
}
@Test
@ -105,7 +95,7 @@ public class DialectResolverTest extends BaseUnitTestCase {
String databaseName,
int version,
Class dialectClass) throws SQLException {
Dialect dialect = resolver.resolveDialect( Mocks.createConnection( databaseName, version ).getMetaData() );
Dialect dialect = resolver.resolveDialect( TestingDialectResolutionInfo.forDatabaseInfo( databaseName, version ) );
if ( dialectClass == null ) {
assertEquals( null, dialect );
}
@ -113,4 +103,5 @@ public class DialectResolverTest extends BaseUnitTestCase {
assertEquals( dialectClass, dialect.getClass() );
}
}
}

View File

@ -0,0 +1,96 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.dialect.resolver;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
/**
* @author Steve Ebersole
*/
public class TestingDialectResolutionInfo implements DialectResolutionInfo {
private final String databaseName;
private final int databaseMajorVersion;
private final int databaseMinorVersion;
private final String driverName;
private final int driverMajorVersion;
private final int driverMinorVersion;
TestingDialectResolutionInfo(
String databaseName,
int databaseMajorVersion,
int databaseMinorVersion,
String driverName,
int driverMajorVersion,
int driverMinorVersion) {
this.databaseName = databaseName;
this.databaseMajorVersion = databaseMajorVersion;
this.databaseMinorVersion = databaseMinorVersion;
this.driverName = driverName;
this.driverMajorVersion = driverMajorVersion;
this.driverMinorVersion = driverMinorVersion;
}
public static TestingDialectResolutionInfo forDatabaseInfo(String name) {
return forDatabaseInfo( name, NO_VERSION );
}
public static TestingDialectResolutionInfo forDatabaseInfo(String name, int majorVersion) {
return forDatabaseInfo( name, majorVersion, NO_VERSION );
}
public static TestingDialectResolutionInfo forDatabaseInfo(String name, int majorVersion, int minorVersion) {
return new TestingDialectResolutionInfo( name, majorVersion, minorVersion, null, NO_VERSION, NO_VERSION );
}
@Override
public String getDatabaseName() {
return databaseName;
}
@Override
public int getDatabaseMajorVersion() {
return databaseMajorVersion;
}
@Override
public int getDatabaseMinorVersion() {
return databaseMinorVersion;
}
@Override
public String getDriverName() {
return driverName;
}
@Override
public int getDriverMajorVersion() {
return driverMajorVersion;
}
@Override
public int getDriverMinorVersion() {
return driverMinorVersion;
}
}

View File

@ -26,8 +26,6 @@ package org.hibernate.engine.jdbc.dialect.internal;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
@ -39,15 +37,18 @@ import org.hibernate.dialect.PostgreSQL9Dialect;
import org.hibernate.dialect.SQLServer2005Dialect;
import org.hibernate.dialect.SQLServer2008Dialect;
import org.hibernate.dialect.SQLServerDialect;
import org.hibernate.dialect.resolver.DialectResolverTest;
import org.hibernate.dialect.resolver.TestingDialectResolutionInfo;
import org.hibernate.testing.junit4.BaseUnitTestCase;
import org.junit.Test;
/**
* Unit test of the {@link StandardDatabaseMetaDataDialectResolver} class.
* Unit test of the {@link StandardDialectResolver} class.
*
* @author Bryan Turner
*/
public class StandardDatabaseMetaDataDialectResolverTest extends BaseUnitTestCase {
public class StandardDialectResolverTest extends BaseUnitTestCase {
@Test
public void testResolveDialectInternalForSQLServer2000()
@ -131,15 +132,13 @@ public class StandardDatabaseMetaDataDialectResolverTest extends BaseUnitTestCas
}
private static void runDialectTest(
String productName, int majorVersion, int minorVersion,
Class<? extends Dialect> expectedDialect) throws SQLException {
DatabaseMetaData metaData = mock( DatabaseMetaData.class );
when( metaData.getDatabaseProductName() ).thenReturn( productName );
when( metaData.getDatabaseMajorVersion() ).thenReturn( majorVersion );
when( metaData.getDatabaseMinorVersion() ).thenReturn( minorVersion );
String productName,
int majorVersion,
int minorVersion,
Class<? extends Dialect> expectedDialect) {
TestingDialectResolutionInfo info = TestingDialectResolutionInfo.forDatabaseInfo( productName, majorVersion, minorVersion );
Dialect dialect = new StandardDatabaseMetaDataDialectResolver( StandardDatabaseInfoDialectResolver.INSTANCE )
.resolveDialectInternal( metaData );
Dialect dialect = StandardDialectResolver.INSTANCE.resolveDialect( info );
StringBuilder builder = new StringBuilder( productName ).append( " " )
.append( majorVersion );

View File

@ -30,7 +30,6 @@ import java.io.Writer;
import java.net.MalformedURLException;
import java.net.URL;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
@ -43,12 +42,13 @@ import org.jboss.logging.Logger;
import org.hibernate.HibernateException;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.boot.registry.selector.spi.StrategySelector;
import org.hibernate.cfg.Configuration;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.engine.jdbc.dialect.spi.DatabaseInfoDialectResolver;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolver;
import org.hibernate.engine.jdbc.dialect.spi.DatabaseMetaDataDialectResolutionInfoAdapter;
import org.hibernate.engine.jdbc.dialect.spi.DialectFactory;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfoSource;
import org.hibernate.engine.jdbc.spi.JdbcConnectionAccess;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.jdbc.spi.SqlStatementLogger;
@ -98,7 +98,7 @@ public class JpaSchemaGenerator {
/**
* Perform the generation, as indicated by the settings
*
* @param hibernateConfiguration
* @param hibernateConfiguration The hibernate configuration
*/
public void execute(Configuration hibernateConfiguration) {
// First, determine the actions (if any) to be performed ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -423,97 +423,75 @@ public class JpaSchemaGenerator {
}
private static Dialect determineDialect(
JdbcConnectionContext jdbcConnectionContext,
Configuration hibernateConfiguration,
final JdbcConnectionContext jdbcConnectionContext,
final Configuration hibernateConfiguration,
ServiceRegistry serviceRegistry) {
final String explicitDbName = hibernateConfiguration.getProperty( AvailableSettings.SCHEMA_GEN_DB_NAME );
final String explicitDbMajor = hibernateConfiguration.getProperty( AvailableSettings.SCHEMA_GEN_DB_MAJOR_VERSION );
final String explicitDbMinor = hibernateConfiguration.getProperty( AvailableSettings.SCHEMA_GEN_DB_MINOR_VERSION );
if ( StringHelper.isNotEmpty( explicitDbName ) ) {
serviceRegistry.getService( DatabaseInfoDialectResolver.class ).resolve(
new DatabaseInfoDialectResolver.DatabaseInfo() {
@Override
public String getDatabaseName() {
return explicitDbName;
return serviceRegistry.getService( DialectFactory.class ).buildDialect(
hibernateConfiguration.getProperties(),
new DialectResolutionInfoSource() {
@Override
public DialectResolutionInfo getDialectResolutionInfo() {
// if the application supplied database name/version info, use that
final String explicitDbName = hibernateConfiguration.getProperty( AvailableSettings.SCHEMA_GEN_DB_NAME );
if ( StringHelper.isNotEmpty( explicitDbName ) ) {
final String explicitDbMajor = hibernateConfiguration.getProperty( AvailableSettings.SCHEMA_GEN_DB_MAJOR_VERSION );
final String explicitDbMinor = hibernateConfiguration.getProperty( AvailableSettings.SCHEMA_GEN_DB_MINOR_VERSION );
return new DialectResolutionInfo() {
@Override
public String getDatabaseName() {
return explicitDbName;
}
@Override
public int getDatabaseMajorVersion() {
return StringHelper.isEmpty( explicitDbMajor )
? NO_VERSION
: Integer.parseInt( explicitDbMajor );
}
@Override
public int getDatabaseMinorVersion() {
return StringHelper.isEmpty( explicitDbMinor )
? NO_VERSION
: Integer.parseInt( explicitDbMinor );
}
@Override
public String getDriverName() {
return null;
}
@Override
public int getDriverMajorVersion() {
return NO_VERSION;
}
@Override
public int getDriverMinorVersion() {
return NO_VERSION;
}
};
}
@Override
public int getDatabaseMajorVersion() {
return StringHelper.isEmpty( explicitDbMajor )
? NO_VERSION
: Integer.parseInt( explicitDbMajor );
// otherwise look at the connection, if provided (if not provided the call to
// getJdbcConnection will already throw a meaningful exception)
try {
return new DatabaseMetaDataDialectResolutionInfoAdapter(
jdbcConnectionContext.getJdbcConnection().getMetaData()
);
}
@Override
public int getDatabaseMinorVersion() {
return StringHelper.isEmpty( explicitDbMinor )
? NO_VERSION
: Integer.parseInt( explicitDbMinor );
catch ( SQLException sqlException ) {
throw new HibernateException(
"Unable to access java.sql.DatabaseMetaData to determine appropriate Dialect to use",
sqlException
);
}
}
);
}
return buildDialect( hibernateConfiguration, serviceRegistry, jdbcConnectionContext );
}
private static Dialect buildDialect(
Configuration hibernateConfiguration,
ServiceRegistry serviceRegistry,
JdbcConnectionContext jdbcConnectionContext) {
// todo : a lot of copy/paste from the DialectFactory impl...
final String dialectName = hibernateConfiguration.getProperty( org.hibernate.cfg.AvailableSettings.DIALECT );
if ( dialectName != null ) {
return constructDialect( dialectName, serviceRegistry );
}
else {
return determineDialectBasedOnJdbcMetadata( jdbcConnectionContext, serviceRegistry );
}
}
private static Dialect constructDialect(String dialectName, ServiceRegistry serviceRegistry) {
final Dialect dialect;
final StrategySelector strategySelector = serviceRegistry.getService( StrategySelector.class );
try {
dialect = strategySelector.resolveStrategy( Dialect.class, dialectName );
if ( dialect == null ) {
throw new HibernateException( "Unable to construct requested dialect [" + dialectName + "]" );
}
return dialect;
}
catch (HibernateException e) {
throw e;
}
catch (Exception e) {
throw new HibernateException( "Unable to construct requested dialect [" + dialectName+ "]", e );
}
}
private static Dialect determineDialectBasedOnJdbcMetadata(
JdbcConnectionContext jdbcConnectionContext,
ServiceRegistry serviceRegistry) {
final DialectResolver dialectResolver = serviceRegistry.getService( DialectResolver.class );
try {
final DatabaseMetaData databaseMetaData = jdbcConnectionContext.getJdbcConnection().getMetaData();
final Dialect dialect = dialectResolver.resolveDialect( databaseMetaData );
if ( dialect == null ) {
throw new HibernateException(
"Unable to determine Dialect to use [name=" + databaseMetaData.getDatabaseProductName() +
", majorVersion=" + databaseMetaData.getDatabaseMajorVersion() +
"]; user must register resolver or explicitly set 'hibernate.dialect'"
);
}
return dialect;
}
catch ( SQLException sqlException ) {
throw new HibernateException(
"Unable to access java.sql.DatabaseMetaData to determine appropriate Dialect to use",
sqlException
);
}
}
);
}
private static void doGeneration(