From 3d366a526e4e90f80edea0a0111eb31bd7810ee3 Mon Sep 17 00:00:00 2001 From: Steve Ebersole Date: Mon, 7 Oct 2013 14:38:16 -0500 Subject: [PATCH] HHH-8561 - hibernate.dialect_resolvers causes failures --- .../DatabaseInfoDialectResolverInitiator.java | 84 ---------- .../DatabaseInfoDialectResolverSet.java | 99 ----------- .../dialect/internal/DialectFactoryImpl.java | 65 ++++---- .../internal/DialectResolverInitiator.java | 9 +- .../dialect/internal/DialectResolverSet.java | 40 +---- ...andardDatabaseMetaDataDialectResolver.java | 100 ----------- ...lver.java => StandardDialectResolver.java} | 40 +++-- ...stractDatabaseMetaDataDialectResolver.java | 82 --------- .../BasicDialectResolver.java | 65 ++++---- .../spi/BasicSQLExceptionConverter.java | 9 +- .../spi/DatabaseInfoDialectResolver.java | 84 ---------- ...eMetaDataDialectResolutionInfoAdapter.java | 100 +++++++++++ .../jdbc/dialect/spi/DialectFactory.java | 6 +- .../dialect/spi/DialectResolutionInfo.java | 102 ++++++++++++ ....java => DialectResolutionInfoSource.java} | 24 +-- .../jdbc/dialect/spi/DialectResolver.java | 24 ++- .../jdbc/internal/JdbcServicesImpl.java | 23 ++- .../service/StandardServiceInitiators.java | 20 +-- .../hibernate/dialect/TestingDialects.java | 42 +---- .../dialect/resolver/DialectFactoryTest.java | 78 ++++++--- .../dialect/resolver/DialectResolverTest.java | 29 ++-- .../TestingDialectResolutionInfo.java | 96 +++++++++++ ....java => StandardDialectResolverTest.java} | 23 ++- .../schemagen/JpaSchemaGenerator.java | 156 ++++++++---------- 24 files changed, 599 insertions(+), 801 deletions(-) delete mode 100644 hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/internal/DatabaseInfoDialectResolverInitiator.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/internal/DatabaseInfoDialectResolverSet.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/internal/StandardDatabaseMetaDataDialectResolver.java rename hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/internal/{StandardDatabaseInfoDialectResolver.java => StandardDialectResolver.java} (81%) delete mode 100644 hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/spi/AbstractDatabaseMetaDataDialectResolver.java rename hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/{internal => spi}/BasicDialectResolver.java (50%) delete mode 100644 hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/spi/DatabaseInfoDialectResolver.java create mode 100644 hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/spi/DatabaseMetaDataDialectResolutionInfoAdapter.java create mode 100644 hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/spi/DialectResolutionInfo.java rename hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/spi/{DatabaseMetaDataDialectResolver.java => DialectResolutionInfoSource.java} (52%) create mode 100644 hibernate-core/src/test/java/org/hibernate/dialect/resolver/TestingDialectResolutionInfo.java rename hibernate-core/src/test/java/org/hibernate/engine/jdbc/dialect/internal/{StandardDatabaseMetaDataDialectResolverTest.java => StandardDialectResolverTest.java} (84%) diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/internal/DatabaseInfoDialectResolverInitiator.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/internal/DatabaseInfoDialectResolverInitiator.java deleted file mode 100644 index 3fb14158d0..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/internal/DatabaseInfoDialectResolverInitiator.java +++ /dev/null @@ -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 { - /** - * Singleton access - */ - public static final DatabaseInfoDialectResolverInitiator INSTANCE = new DatabaseInfoDialectResolverInitiator(); - - @Override - public Class 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 ); - } - } - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/internal/DatabaseInfoDialectResolverSet.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/internal/DatabaseInfoDialectResolverSet.java deleted file mode 100644 index d9149a9195..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/internal/DatabaseInfoDialectResolverSet.java +++ /dev/null @@ -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 delegateResolvers; - - /** - * Constructs a DatabaseInfoDialectResolverSet - */ - public DatabaseInfoDialectResolverSet() { - this( new ArrayList() ); - } - - /** - * Constructs a DatabaseInfoDialectResolverSet - * - * @param delegateResolvers The set of delegate resolvers - */ - public DatabaseInfoDialectResolverSet(List 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 ); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/internal/DialectFactoryImpl.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/internal/DialectFactoryImpl.java index 55c766facf..5d0d8ebb37 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/internal/DialectFactoryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/internal/DialectFactoryImpl.java @@ -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; } } diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/internal/DialectResolverInitiator.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/internal/DialectResolverInitiator.java index befec6fe51..268d8a0bad 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/internal/DialectResolverInitiator.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/internal/DialectResolverInitiator.java @@ -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 resolvers; - /** - * Deprecated - */ public DialectResolverSet() { this( new ArrayList() ); - LOG.debug( "DialectResolverSet is deprecated" ); } - /** - * Deprecated - * - * @param resolvers The delegate resolvers - */ public DialectResolverSet(List 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; } diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/internal/StandardDatabaseMetaDataDialectResolver.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/internal/StandardDatabaseMetaDataDialectResolver.java deleted file mode 100644 index ca2406fe07..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/internal/StandardDatabaseMetaDataDialectResolver.java +++ /dev/null @@ -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 ) ); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/internal/StandardDatabaseInfoDialectResolver.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/internal/StandardDialectResolver.java similarity index 81% rename from hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/internal/StandardDatabaseInfoDialectResolver.java rename to hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/internal/StandardDialectResolver.java index a62ccfce65..0e3a843fee 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/internal/StandardDatabaseInfoDialectResolver.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/internal/StandardDialectResolver.java @@ -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: diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/spi/AbstractDatabaseMetaDataDialectResolver.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/spi/AbstractDatabaseMetaDataDialectResolver.java deleted file mode 100644 index 5226dfe8dd..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/spi/AbstractDatabaseMetaDataDialectResolver.java +++ /dev/null @@ -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} - *

- * 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; -} diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/internal/BasicDialectResolver.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/spi/BasicDialectResolver.java similarity index 50% rename from hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/internal/BasicDialectResolver.java rename to hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/spi/BasicDialectResolver.java index b96c41ee28..0cb8e56e1d 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/internal/BasicDialectResolver.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/spi/BasicDialectResolver.java @@ -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 HHH-7965 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(); } diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/spi/BasicSQLExceptionConverter.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/spi/BasicSQLExceptionConverter.java index ea554a052d..02f31fc993 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/spi/BasicSQLExceptionConverter.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/spi/BasicSQLExceptionConverter.java @@ -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 "???"; diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/spi/DatabaseInfoDialectResolver.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/spi/DatabaseInfoDialectResolver.java deleted file mode 100644 index a532e35389..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/spi/DatabaseInfoDialectResolver.java +++ /dev/null @@ -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(); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/spi/DatabaseMetaDataDialectResolutionInfoAdapter.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/spi/DatabaseMetaDataDialectResolutionInfoAdapter.java new file mode 100644 index 0000000000..183f80e80b --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/spi/DatabaseMetaDataDialectResolutionInfoAdapter.java @@ -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}. + *

+ * 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() ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/spi/DialectFactory.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/spi/DialectFactory.java index 876666d6da..86c3141c24 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/spi/DialectFactory.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/spi/DialectFactory.java @@ -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; } diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/spi/DialectResolutionInfo.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/spi/DialectResolutionInfo.java new file mode 100644 index 0000000000..d1ed985c32 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/spi/DialectResolutionInfo.java @@ -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. + *

+ * 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(); + + +} diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/spi/DatabaseMetaDataDialectResolver.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/spi/DialectResolutionInfoSource.java similarity index 52% rename from hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/spi/DatabaseMetaDataDialectResolver.java rename to hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/spi/DialectResolutionInfoSource.java index e9ee437b55..235c024cc6 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/spi/DatabaseMetaDataDialectResolver.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/spi/DialectResolutionInfoSource.java @@ -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(); } diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/spi/DialectResolver.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/spi/DialectResolver.java index 0fca0dfcc6..001029f415 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/spi/DialectResolver.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/spi/DialectResolver.java @@ -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); } diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/JdbcServicesImpl.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/JdbcServicesImpl.java index c233c790d5..f3c39a0a95 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/JdbcServicesImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/JdbcServicesImpl.java @@ -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 ); diff --git a/hibernate-core/src/main/java/org/hibernate/service/StandardServiceInitiators.java b/hibernate-core/src/main/java/org/hibernate/service/StandardServiceInitiators.java index 6874c2a6be..64f8944e96 100644 --- a/hibernate-core/src/main/java/org/hibernate/service/StandardServiceInitiators.java +++ b/hibernate-core/src/main/java/org/hibernate/service/StandardServiceInitiators.java @@ -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 ); diff --git a/hibernate-core/src/test/java/org/hibernate/dialect/TestingDialects.java b/hibernate-core/src/test/java/org/hibernate/dialect/TestingDialects.java index 4f1db81f3c..c077251f7c 100644 --- a/hibernate-core/src/test/java/org/hibernate/dialect/TestingDialects.java +++ b/hibernate-core/src/test/java/org/hibernate/dialect/TestingDialects.java @@ -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 ); diff --git a/hibernate-core/src/test/java/org/hibernate/dialect/resolver/DialectFactoryTest.java b/hibernate-core/src/test/java/org/hibernate/dialect/resolver/DialectFactoryTest.java index dfc2fec6f6..2f12c72f8e 100644 --- a/hibernate-core/src/test/java/org/hibernate/dialect/resolver/DialectFactoryTest.java +++ b/hibernate-core/src/test/java/org/hibernate/dialect/resolver/DialectFactoryTest.java @@ -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() ); } } diff --git a/hibernate-core/src/test/java/org/hibernate/dialect/resolver/DialectResolverTest.java b/hibernate-core/src/test/java/org/hibernate/dialect/resolver/DialectResolverTest.java index ba49a7e109..77b9f4daaf 100644 --- a/hibernate-core/src/test/java/org/hibernate/dialect/resolver/DialectResolverTest.java +++ b/hibernate-core/src/test/java/org/hibernate/dialect/resolver/DialectResolverTest.java @@ -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() ); } } + } diff --git a/hibernate-core/src/test/java/org/hibernate/dialect/resolver/TestingDialectResolutionInfo.java b/hibernate-core/src/test/java/org/hibernate/dialect/resolver/TestingDialectResolutionInfo.java new file mode 100644 index 0000000000..762b1e9fde --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/dialect/resolver/TestingDialectResolutionInfo.java @@ -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; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/engine/jdbc/dialect/internal/StandardDatabaseMetaDataDialectResolverTest.java b/hibernate-core/src/test/java/org/hibernate/engine/jdbc/dialect/internal/StandardDialectResolverTest.java similarity index 84% rename from hibernate-core/src/test/java/org/hibernate/engine/jdbc/dialect/internal/StandardDatabaseMetaDataDialectResolverTest.java rename to hibernate-core/src/test/java/org/hibernate/engine/jdbc/dialect/internal/StandardDialectResolverTest.java index 6d918518ab..5c8cea3a4c 100644 --- a/hibernate-core/src/test/java/org/hibernate/engine/jdbc/dialect/internal/StandardDatabaseMetaDataDialectResolverTest.java +++ b/hibernate-core/src/test/java/org/hibernate/engine/jdbc/dialect/internal/StandardDialectResolverTest.java @@ -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 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 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 ); diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/schemagen/JpaSchemaGenerator.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/schemagen/JpaSchemaGenerator.java index 32079a3e2e..c3230cdaa8 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/schemagen/JpaSchemaGenerator.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/internal/schemagen/JpaSchemaGenerator.java @@ -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(