From 69564cd7c8c20e5ef57bc02664cbe16fc2308213 Mon Sep 17 00:00:00 2001 From: Steve Ebersole Date: Fri, 5 Mar 2021 14:42:21 -0600 Subject: [PATCH] HHH-14478 : Allow DialectResolvers to be discovered by ServiceLoader --- .../org/hibernate/cfg/AvailableSettings.java | 106 +++++++++++------- .../java/org/hibernate/dialect/Database.java | 50 +++++---- .../java/org/hibernate/dialect/H2Dialect.java | 7 +- .../internal/DialectResolverInitiator.java | 22 ++-- .../dialect/internal/DialectResolverSet.java | 25 ++--- .../internal/StandardDialectResolver.java | 2 + .../dialect/spi/DialectResolutionInfo.java | 18 ++- .../spi/DialectResolutionInfoSource.java | 7 +- .../internal/JdbcEnvironmentInitiator.java | 10 +- .../org/hibernate/jpa/AvailableSettings.java | 12 +- .../HibernateSchemaManagementTool.java | 8 +- hibernate-core/src/main/javadoc/package.html | 2 +- .../internal/StandardDialectResolverTest.java | 2 +- .../dialect/resolver/DialectFactoryTest.java | 66 +++++------ .../dialect/resolver/DialectResolverTest.java | 2 +- .../DiscoveredDialectResolverTests.java | 64 +++++++++++ .../TestingDialectResolutionInfo.java | 25 +++-- .../orm/junit/DomainModelExtension.java | 8 +- 18 files changed, 272 insertions(+), 164 deletions(-) rename hibernate-core/src/test/java/org/hibernate/{ => orm/test}/dialect/resolver/DialectFactoryTest.java (79%) rename hibernate-core/src/test/java/org/hibernate/{ => orm/test}/dialect/resolver/DialectResolverTest.java (99%) create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/dialect/resolver/DiscoveredDialectResolverTests.java rename hibernate-core/src/test/java/org/hibernate/{ => orm/test}/dialect/resolver/TestingDialectResolutionInfo.java (75%) diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java b/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java index 7757ffac41..65833798fe 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java @@ -15,6 +15,7 @@ import org.hibernate.boot.MetadataBuilder; import org.hibernate.boot.registry.classloading.internal.TcclLookupPrecedence; import org.hibernate.boot.spi.SessionFactoryOptions; import org.hibernate.cache.spi.TimestampsCacheFactory; +import org.hibernate.engine.jdbc.dialect.spi.DialectResolver; import org.hibernate.jpa.spi.JpaCompliance; import org.hibernate.query.ImmutableEntityUpdateQueryHandlingMode; import org.hibernate.query.hql.HqlTranslator; @@ -427,6 +428,59 @@ public interface AvailableSettings extends org.hibernate.jpa.AvailableSettings { */ String DIALECT_RESOLVERS = "hibernate.dialect_resolvers"; + /** + * Specifies the name of the database provider in cases where a Connection to the underlying database is + * not available (aka, mainly in generating scripts). In such cases, a value for this setting + * *must* be specified. + *

+ * The value of this setting is expected to match the value returned by + * {@link java.sql.DatabaseMetaData#getDatabaseProductName()} for the target database. + *

+ * Additionally specifying {@value #DIALECT_DB_MAJOR_VERSION} and/or {@value #DIALECT_DB_MINOR_VERSION} + * may be required to understand exactly how to generate the required schema commands. + * + * @see #DIALECT_DB_VERSION + * @see #DIALECT_DB_MAJOR_VERSION + * @see #DIALECT_DB_MINOR_VERSION + */ + String DIALECT_DB_NAME = "javax.persistence.database-product-name"; + + /** + * Specifies the name of the database provider in cases where a Connection to the underlying database is + * not available (aka, mainly in generating scripts). This value is used to help more precisely determine + * how to perform schema generation tasks for the underlying database in cases where + * {@value #DIALECT_DB_NAME} does not provide enough distinction. + *

+ * The value of this setting is expected to match the value returned by + * {@link java.sql.DatabaseMetaData#getDatabaseProductVersion()} for the target database. + * + * @see #DIALECT_DB_NAME + */ + String DIALECT_DB_VERSION = "javax.persistence.database-product-version"; + + /** + * Specifies the major version of the underlying database, as would be returned by + * {@link java.sql.DatabaseMetaData#getDatabaseMajorVersion} for the target database. This value is used to + * help more precisely determine how to perform schema generation tasks for the underlying database in cases + * where {@value #DIALECT_DB_NAME} does not provide enough distinction. + + * @see #DIALECT_DB_NAME + * @see #DIALECT_DB_MINOR_VERSION + */ + String DIALECT_DB_MAJOR_VERSION = "javax.persistence.database-major-version"; + + /** + * Specifies the minor version of the underlying database, as would be returned by + * {@link java.sql.DatabaseMetaData#getDatabaseMinorVersion} for the target database. + * + * This setting is used in Dialect resolution + * + * @see #DIALECT_DB_NAME + * @see #DIALECT_DB_MAJOR_VERSION + * @see DialectResolver + */ + String DIALECT_DB_MINOR_VERSION = "javax.persistence.database-minor-version"; + /** * Defines the default storage engine for the relational databases that support multiple storage engines. * This property must be set either as an Environment variable or JVM System Property. @@ -1356,63 +1410,33 @@ public interface AvailableSettings extends org.hibernate.jpa.AvailableSettings { /** * Allows passing a specific {@link java.sql.Connection} instance to be used by SchemaManagementTool. *

- * May also be used to determine the values for {@value #HBM2DDL_DB_NAME}, - * {@value #HBM2DDL_DB_MAJOR_VERSION} and {@value #HBM2DDL_DB_MINOR_VERSION}. + * May also be used to determine the values for {@value #DIALECT_DB_NAME}, + * {@value #DIALECT_DB_MAJOR_VERSION} and {@value #DIALECT_DB_MINOR_VERSION}. */ String HBM2DDL_CONNECTION = "javax.persistence.schema-generation-connection"; /** - * Specifies the name of the database provider in cases where a Connection to the underlying database is - * not available (aka, mainly in generating scripts). In such cases, a value for this setting - * *must* be specified. - *

- * The value of this setting is expected to match the value returned by - * {@link java.sql.DatabaseMetaData#getDatabaseProductName()} for the target database. - *

- * Additionally specifying {@value #HBM2DDL_DB_MAJOR_VERSION} and/or {@value #HBM2DDL_DB_MINOR_VERSION} - * may be required to understand exactly how to generate the required schema commands. - * - * @see #HBM2DDL_DB_MAJOR_VERSION - * @see #HBM2DDL_DB_MINOR_VERSION + * @deprecated Use {@link #DIALECT_DB_NAME} instead */ - @SuppressWarnings("JavaDoc") - String HBM2DDL_DB_NAME = "javax.persistence.database-product-name"; + @Deprecated + String HBM2DDL_DB_NAME = DIALECT_DB_NAME; /** - * Specifies the name of the database provider in cases where a Connection to the underlying database is - * not available (aka, mainly in generating scripts). This value is used to help more precisely determine - * how to perform schema generation tasks for the underlying database in cases where - * {@value #HBM2DDL_DB_NAME} does not provide enough distinction. - *

- * The value of this setting is expected to match the value returned by - * {@link java.sql.DatabaseMetaData#getDatabaseProductVersion()} for the target database. - * - * @see #HBM2DDL_DB_NAME + * @deprecated Use {@link #DIALECT_DB_VERSION} instead */ - @SuppressWarnings("JavaDoc") + @Deprecated String HBM2DDL_DB_VERSION = "javax.persistence.database-product-version"; /** - * Specifies the major version of the underlying database, as would be returned by - * {@link java.sql.DatabaseMetaData#getDatabaseMajorVersion} for the target database. This value is used to - * help more precisely determine how to perform schema generation tasks for the underlying database in cases - * where {@value #HBM2DDL_DB_NAME} does not provide enough distinction. - - * @see #HBM2DDL_DB_NAME - * @see #HBM2DDL_DB_MINOR_VERSION + * @deprecated Use {@link #DIALECT_DB_MAJOR_VERSION} instead */ + @Deprecated String HBM2DDL_DB_MAJOR_VERSION = "javax.persistence.database-major-version"; /** - * Specifies the minor version of the underlying database, as would be returned by - * {@link java.sql.DatabaseMetaData#getDatabaseMinorVersion} for the target database. This value is used to - * help more precisely determine how to perform schema generation tasks for the underlying database in cases - * where the combination of {@value #HBM2DDL_DB_NAME} and {@value #HBM2DDL_DB_MAJOR_VERSION} does not provide - * enough distinction. - * - * @see #HBM2DDL_DB_NAME - * @see #HBM2DDL_DB_MAJOR_VERSION + * @deprecated Use {@link #DIALECT_DB_MINOR_VERSION} instead */ + @Deprecated String HBM2DDL_DB_MINOR_VERSION = "javax.persistence.database-minor-version"; /** diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/Database.java b/hibernate-core/src/main/java/org/hibernate/dialect/Database.java index 6cec1a7e2d..6143fe0dd6 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/Database.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/Database.java @@ -14,6 +14,8 @@ import java.sql.Statement; import org.hibernate.engine.jdbc.dialect.spi.BasicSQLExceptionConverter; import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo; +import static org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo.NO_VERSION; + /** * A list of relational database systems for which Hibernate can resolve a {@link Dialect}. * @@ -55,20 +57,25 @@ public enum Database { @Override public Dialect createDialect(DialectResolutionInfo info) { String databaseVersion = info.getDatabaseVersion(); - if ( databaseVersion == null ) { - return new DB2Dialect( info ); - } - //See https://www.ibm.com/support/knowledgecenter/SSEPEK_12.0.0/java/src/tpc/imjcc_c0053013.html - switch ( databaseVersion.substring( 0, 3 ) ) { - case "SQL": // Linux, UNIX, Windows - return new DB2Dialect( info ); - case "DSN": // z/OS - return new DB2zDialect( info ); - case "QSQ": // i - return new DB2iDialect( info ); - default: - return null; + if ( databaseVersion != null ) { + //See https://www.ibm.com/support/knowledgecenter/SSEPEK_12.0.0/java/src/tpc/imjcc_c0053013.html + switch ( databaseVersion.substring( 0, 3 ) ) { + case "SQL": { + // Linux, UNIX, Windows + return new DB2Dialect( info ); + } + case "DSN": { + // z/OS + return new DB2zDialect( info ); + } + case "QSQ": { + // i + return new DB2iDialect( info ); + } + } } + + return new DB2Dialect( info ); } @Override public boolean productNameMatches(String databaseName) { @@ -332,15 +339,18 @@ public enum Database { return "org.postgresql.Driver"; } private String getVersion(DatabaseMetaData databaseMetaData) { - try (Statement statement = databaseMetaData.getConnection().createStatement() ) { - final ResultSet rs = statement.executeQuery( "select version()" ); - if ( rs.next() ) { - return rs.getString( 1 ); + if ( databaseMetaData != null ) { + try ( Statement statement = databaseMetaData.getConnection().createStatement() ) { + final ResultSet rs = statement.executeQuery( "select version()" ); + if ( rs.next() ) { + return rs.getString( 1 ); + } + } + catch (SQLException e) { + throw BasicSQLExceptionConverter.INSTANCE.convert( e ); } } - catch (SQLException e) { - throw BasicSQLExceptionConverter.INSTANCE.convert( e ); - } + return ""; } }, diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java index b85e6f8281..761e7234d4 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java @@ -127,7 +127,12 @@ public class H2Dialect extends Dialect { } private static int parseBuildId(DialectResolutionInfo info) { - String[] bits = info.getDatabaseVersion().split("[. ]"); + final String databaseVersion = info.getDatabaseVersion(); + if ( databaseVersion == null ) { + return 0; + } + + final String[] bits = databaseVersion.split("[. ]"); return bits.length > 2 ? Integer.parseInt( bits[2] ) : 0; } 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 0ed491c03b..d52906ec9a 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 @@ -6,6 +6,7 @@ */ package org.hibernate.engine.jdbc.dialect.internal; +import java.util.Collection; import java.util.Map; import org.hibernate.HibernateException; @@ -18,7 +19,7 @@ import org.hibernate.service.spi.ServiceException; import org.hibernate.service.spi.ServiceRegistryImplementor; /** - * Standard initiator for the standard {@link DialectResolver} service + * Standard initiator for the {@link DialectResolver} service * * @author Steve Ebersole */ @@ -36,25 +37,25 @@ public class DialectResolverInitiator implements StandardServiceInitiator configurationValues) { final String resolverImplNames = (String) configurationValues.get( AvailableSettings.DIALECT_RESOLVERS ); + final ClassLoaderService classLoaderService = registry.getService( ClassLoaderService.class ); if ( StringHelper.isNotEmpty( resolverImplNames ) ) { - final ClassLoaderService classLoaderService = registry.getService( ClassLoaderService.class ); for ( String resolverImplName : StringHelper.split( ", \n\r\f\t", resolverImplNames ) ) { try { - resolver.addResolver( + resolverSet.addResolver( (DialectResolver) classLoaderService.classForName( resolverImplName ).newInstance() ); } @@ -66,5 +67,8 @@ public class DialectResolverInitiator implements StandardServiceInitiator resolvers = classLoaderService.loadJavaServices( DialectResolver.class ); + resolverSet.addDiscoveredResolvers( resolvers ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/internal/DialectResolverSet.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/internal/DialectResolverSet.java index a283f72126..ad409e0324 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/internal/DialectResolverSet.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/internal/DialectResolverSet.java @@ -8,6 +8,7 @@ package org.hibernate.engine.jdbc.dialect.internal; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.List; import org.hibernate.dialect.Dialect; @@ -60,23 +61,15 @@ public class DialectResolverSet implements DialectResolver { 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(DialectResolver resolver) { - resolvers.add( resolver ); + public void addResolver(DialectResolver... resolvers) { + this.resolvers.addAll( Arrays.asList( resolvers ) ); } - /** - * 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. - */ - public void addResolverAtFirst(DialectResolver resolver) { - resolvers.add( 0, resolver ); + public void addResolverAtFirst(DialectResolver... resolvers) { + this.resolvers.addAll( 0, Arrays.asList( resolvers ) ); + } + + public void addDiscoveredResolvers(Collection resolvers) { + this.resolvers.addAll( 0, resolvers ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/internal/StandardDialectResolver.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/internal/StandardDialectResolver.java index 8dcd9215c8..2b51d98644 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/internal/StandardDialectResolver.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/internal/StandardDialectResolver.java @@ -17,6 +17,8 @@ import org.hibernate.engine.jdbc.dialect.spi.DialectResolver; * @author Steve Ebersole */ public final class StandardDialectResolver implements DialectResolver { + public StandardDialectResolver() { + } @Override public Dialect resolveDialect(DialectResolutionInfo info) { 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 index 06a28da1d8..c1b8ac10f6 100644 --- 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 @@ -12,14 +12,12 @@ package org.hibernate.engine.jdbc.dialect.spi; *

* 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; + int NO_VERSION = -9999; /** * Obtain access to the database name, as returned from {@link java.sql.DatabaseMetaData#getDatabaseProductName()} @@ -29,7 +27,7 @@ public interface DialectResolutionInfo { * * @see java.sql.DatabaseMetaData#getDatabaseProductName() */ - public String getDatabaseName(); + String getDatabaseName(); /** * Obtain access to the database version, as returned from {@link java.sql.DatabaseMetaData#getDatabaseProductVersion()} @@ -39,7 +37,7 @@ public interface DialectResolutionInfo { * * @see java.sql.DatabaseMetaData#getDatabaseProductVersion() */ - public String getDatabaseVersion(); + String getDatabaseVersion(); /** * Obtain access to the database major version, as returned from @@ -49,7 +47,7 @@ public interface DialectResolutionInfo { * * @see java.sql.DatabaseMetaData#getDatabaseMajorVersion() */ - public int getDatabaseMajorVersion(); + int getDatabaseMajorVersion(); /** * Obtain access to the database minor version, as returned from @@ -59,7 +57,7 @@ public interface DialectResolutionInfo { * * @see java.sql.DatabaseMetaData#getDatabaseMinorVersion() */ - public int getDatabaseMinorVersion(); + int getDatabaseMinorVersion(); /** * Obtain access to the name of the JDBC driver, as returned from {@link java.sql.DatabaseMetaData#getDriverName()} @@ -69,7 +67,7 @@ public interface DialectResolutionInfo { * * @see java.sql.DatabaseMetaData#getDriverName() */ - public String getDriverName(); + String getDriverName(); /** * Obtain access to the major version of the JDBC driver, as returned from @@ -79,7 +77,7 @@ public interface DialectResolutionInfo { * * @see java.sql.DatabaseMetaData#getDriverMajorVersion() */ - public int getDriverMajorVersion(); + int getDriverMajorVersion(); /** * Obtain access to the minor version of the JDBC driver, as returned from @@ -89,7 +87,7 @@ public interface DialectResolutionInfo { * * @see java.sql.DatabaseMetaData#getDriverMinorVersion() */ - public int getDriverMinorVersion(); + int getDriverMinorVersion(); /** * Obtain access to the underlying object of the given type. diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/spi/DialectResolutionInfoSource.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/spi/DialectResolutionInfoSource.java index 154b6e70c2..65de46fe4b 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/spi/DialectResolutionInfoSource.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/dialect/spi/DialectResolutionInfoSource.java @@ -8,14 +8,11 @@ package org.hibernate.engine.jdbc.dialect.spi; /** * Contract for the source of DialectResolutionInfo. - * - * @author Steve Ebersole */ +@FunctionalInterface public interface DialectResolutionInfoSource { /** * Get the DialectResolutionInfo - * - * @return The DialectResolutionInfo */ - public DialectResolutionInfo getDialectResolutionInfo(); + DialectResolutionInfo getDialectResolutionInfo(); } diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/JdbcEnvironmentInitiator.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/JdbcEnvironmentInitiator.java index 2b2220bbc3..61e7723fa4 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/JdbcEnvironmentInitiator.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/JdbcEnvironmentInitiator.java @@ -62,28 +62,28 @@ public class JdbcEnvironmentInitiator implements StandardServiceInitiator new DialectResolutionInfo() { @Override public String getDatabaseName() { - return (String) configurationValues.get( AvailableSettings.HBM2DDL_DB_NAME ); + return (String) configurationValues.get( AvailableSettings.DIALECT_DB_NAME ); } @Override public String getDatabaseVersion() { - return (String) configurationValues.getOrDefault( AvailableSettings.HBM2DDL_DB_VERSION, "0" ); + return (String) configurationValues.getOrDefault( AvailableSettings.DIALECT_DB_VERSION, "0" ); } @Override public int getDatabaseMajorVersion() { - return (Integer) configurationValues.getOrDefault( AvailableSettings.HBM2DDL_DB_MAJOR_VERSION, 0 ); + return (Integer) configurationValues.getOrDefault( AvailableSettings.DIALECT_DB_MAJOR_VERSION, 0 ); } @Override public int getDatabaseMinorVersion() { - return (Integer) configurationValues.getOrDefault( AvailableSettings.HBM2DDL_DB_MINOR_VERSION, 0 ); + return (Integer) configurationValues.getOrDefault( AvailableSettings.DIALECT_DB_MINOR_VERSION, 0 ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/AvailableSettings.java b/hibernate-core/src/main/java/org/hibernate/jpa/AvailableSettings.java index 1bff9be018..cb9acc2bad 100644 --- a/hibernate-core/src/main/java/org/hibernate/jpa/AvailableSettings.java +++ b/hibernate-core/src/main/java/org/hibernate/jpa/AvailableSettings.java @@ -200,22 +200,22 @@ public interface AvailableSettings { String SCHEMA_GEN_CONNECTION = org.hibernate.cfg.AvailableSettings.HBM2DDL_CONNECTION; /** - * @deprecated (since 5.2) use {@link org.hibernate.cfg.AvailableSettings#HBM2DDL_DB_NAME} instead + * @deprecated (since 5.2) use {@link org.hibernate.cfg.AvailableSettings#DIALECT_DB_NAME} instead */ @Deprecated - String SCHEMA_GEN_DB_NAME = org.hibernate.cfg.AvailableSettings.HBM2DDL_DB_NAME; + String SCHEMA_GEN_DB_NAME = org.hibernate.cfg.AvailableSettings.DIALECT_DB_NAME; /** - * @deprecated (since 5.2) use {@link org.hibernate.cfg.AvailableSettings#HBM2DDL_DB_MAJOR_VERSION} instead + * @deprecated (since 5.2) use {@link org.hibernate.cfg.AvailableSettings#DIALECT_DB_MAJOR_VERSION} instead */ @Deprecated - String SCHEMA_GEN_DB_MAJOR_VERSION = org.hibernate.cfg.AvailableSettings.HBM2DDL_DB_MAJOR_VERSION; + String SCHEMA_GEN_DB_MAJOR_VERSION = org.hibernate.cfg.AvailableSettings.DIALECT_DB_MAJOR_VERSION; /** - * @deprecated (since 5.2) use {@link org.hibernate.cfg.AvailableSettings#HBM2DDL_DB_MINOR_VERSION} instead + * @deprecated (since 5.2) use {@link org.hibernate.cfg.AvailableSettings#DIALECT_DB_MINOR_VERSION} instead */ @Deprecated - String SCHEMA_GEN_DB_MINOR_VERSION = org.hibernate.cfg.AvailableSettings.HBM2DDL_DB_MINOR_VERSION; + String SCHEMA_GEN_DB_MINOR_VERSION = org.hibernate.cfg.AvailableSettings.DIALECT_DB_MINOR_VERSION; /** * @deprecated (since 5.2) use {@link org.hibernate.cfg.AvailableSettings#HBM2DDL_LOAD_SCRIPT_SOURCE} instead diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/HibernateSchemaManagementTool.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/HibernateSchemaManagementTool.java index 04593a3be3..10e5e57795 100644 --- a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/HibernateSchemaManagementTool.java +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/HibernateSchemaManagementTool.java @@ -198,11 +198,11 @@ public class HibernateSchemaManagementTool implements SchemaManagementTool, Serv } // see if a specific Dialect override has been provided... - final String explicitDbName = (String) configurationValues.get( AvailableSettings.HBM2DDL_DB_NAME ); + final String explicitDbName = (String) configurationValues.get( AvailableSettings.DIALECT_DB_NAME ); if ( StringHelper.isNotEmpty( explicitDbName ) ) { - final String explicitDbVersion = (String) configurationValues.get( AvailableSettings.HBM2DDL_DB_VERSION ); - final String explicitDbMajor = (String) configurationValues.get( AvailableSettings.HBM2DDL_DB_MAJOR_VERSION ); - final String explicitDbMinor = (String) configurationValues.get( AvailableSettings.HBM2DDL_DB_MINOR_VERSION ); + final String explicitDbVersion = (String) configurationValues.get( AvailableSettings.DIALECT_DB_VERSION ); + final String explicitDbMajor = (String) configurationValues.get( AvailableSettings.DIALECT_DB_MAJOR_VERSION ); + final String explicitDbMinor = (String) configurationValues.get( AvailableSettings.DIALECT_DB_MINOR_VERSION ); final Dialect indicatedDialect = serviceRegistry.getService( DialectResolver.class ).resolveDialect( new DialectResolutionInfo() { diff --git a/hibernate-core/src/main/javadoc/package.html b/hibernate-core/src/main/javadoc/package.html index 6fbfa14362..d321c4c99e 100644 --- a/hibernate-core/src/main/javadoc/package.html +++ b/hibernate-core/src/main/javadoc/package.html @@ -57,4 +57,4 @@ for details. Complete Hibernate documentation may be found online at http://docs.jboss.org/hibernate/. - \ No newline at end of file + diff --git a/hibernate-core/src/test/java/org/hibernate/engine/jdbc/dialect/internal/StandardDialectResolverTest.java b/hibernate-core/src/test/java/org/hibernate/engine/jdbc/dialect/internal/StandardDialectResolverTest.java index 055bca8ec7..4d35967c85 100644 --- a/hibernate-core/src/test/java/org/hibernate/engine/jdbc/dialect/internal/StandardDialectResolverTest.java +++ b/hibernate-core/src/test/java/org/hibernate/engine/jdbc/dialect/internal/StandardDialectResolverTest.java @@ -7,7 +7,7 @@ package org.hibernate.engine.jdbc.dialect.internal; import org.hibernate.dialect.*; -import org.hibernate.dialect.resolver.TestingDialectResolutionInfo; +import org.hibernate.orm.test.dialect.resolver.TestingDialectResolutionInfo; import org.hibernate.testing.junit4.BaseUnitTestCase; import org.junit.Test; diff --git a/hibernate-core/src/test/java/org/hibernate/dialect/resolver/DialectFactoryTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/dialect/resolver/DialectFactoryTest.java similarity index 79% rename from hibernate-core/src/test/java/org/hibernate/dialect/resolver/DialectFactoryTest.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/dialect/resolver/DialectFactoryTest.java index 1f07396cf3..86627e4ae6 100644 --- a/hibernate-core/src/test/java/org/hibernate/dialect/resolver/DialectFactoryTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/dialect/resolver/DialectFactoryTest.java @@ -4,7 +4,7 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or . */ -package org.hibernate.dialect.resolver; +package org.hibernate.orm.test.dialect.resolver; import org.hibernate.HibernateException; import org.hibernate.boot.registry.BootstrapServiceRegistry; @@ -109,42 +109,42 @@ public class DialectFactoryTest extends BaseUnitTestCase { testDetermination( "HSQL Database Engine", HSQLDialect.class, resolver ); testDetermination( "H2", H2Dialect.class, resolver ); testDetermination( "MySQL", MySQLDialect.class, resolver ); - testDetermination( "MySQL", 5, 0, MySQL5Dialect.class, resolver ); - testDetermination( "MySQL", 5, 5, MySQL55Dialect.class, resolver ); - testDetermination( "MySQL", 5, 6, MySQL55Dialect.class, resolver ); - testDetermination( "MySQL", 5, 7, MySQL57Dialect.class, resolver ); - testDetermination( "MySQL", 8, 0, MySQL8Dialect.class, resolver ); - testDetermination( "MariaDB", "MariaDB connector/J", 10, 3, MariaDB103Dialect.class, resolver ); - testDetermination( "MariaDB", "MariaDB connector/J", 10, 2, MariaDB102Dialect.class, resolver ); - testDetermination( "MariaDB", "MariaDB connector/J", 10, 1, MariaDB10Dialect.class, resolver ); - testDetermination( "MariaDB", "MariaDB connector/J", 10, 0, MariaDB10Dialect.class, resolver ); - testDetermination( "MariaDB", "MariaDB connector/J", 5, 5, MariaDB53Dialect.class, resolver ); + testDetermination( "MySQL", 5, 0, MySQLDialect.class, resolver ); + testDetermination( "MySQL", 5, 5, MySQLDialect.class, resolver ); + testDetermination( "MySQL", 5, 6, MySQLDialect.class, resolver ); + testDetermination( "MySQL", 5, 7, MySQLDialect.class, resolver ); + testDetermination( "MySQL", 8, 0, MySQLDialect.class, resolver ); + testDetermination( "MariaDB", "MariaDB connector/J", 10, 3, MariaDBDialect.class, resolver ); + testDetermination( "MariaDB", "MariaDB connector/J", 10, 2, MariaDBDialect.class, resolver ); + testDetermination( "MariaDB", "MariaDB connector/J", 10, 1, MariaDBDialect.class, resolver ); + testDetermination( "MariaDB", "MariaDB connector/J", 10, 0, MariaDBDialect.class, resolver ); + testDetermination( "MariaDB", "MariaDB connector/J", 5, 5, MariaDBDialect.class, resolver ); testDetermination( "MariaDB", "MariaDB connector/J", 5, 2, MariaDBDialect.class, resolver ); - testDetermination( "PostgreSQL", PostgreSQL81Dialect.class, resolver ); - testDetermination( "PostgreSQL", 8, 2, PostgreSQL82Dialect.class, resolver ); - testDetermination( "PostgreSQL", 8, 3, PostgreSQL82Dialect.class, resolver ); - testDetermination( "PostgreSQL", 9, 0, PostgreSQL9Dialect.class, resolver ); - testDetermination( "PostgreSQL", 9, 1, PostgreSQL9Dialect.class, resolver ); - testDetermination( "PostgreSQL", 9, 2, PostgreSQL92Dialect.class, resolver ); - testDetermination( "PostgreSQL", 9, 3, PostgreSQL92Dialect.class, resolver ); - testDetermination( "PostgreSQL", 9, 4, PostgreSQL94Dialect.class, resolver ); - testDetermination( "PostgreSQL", 9, 5, PostgreSQL95Dialect.class, resolver ); - testDetermination( "PostgreSQL", 9, 6, PostgreSQL95Dialect.class, resolver ); + testDetermination( "PostgreSQL", PostgreSQLDialect.class, resolver ); + testDetermination( "PostgreSQL", 8, 2, PostgreSQLDialect.class, resolver ); + testDetermination( "PostgreSQL", 8, 3, PostgreSQLDialect.class, resolver ); + testDetermination( "PostgreSQL", 9, 0, PostgreSQLDialect.class, resolver ); + testDetermination( "PostgreSQL", 9, 1, PostgreSQLDialect.class, resolver ); + testDetermination( "PostgreSQL", 9, 2, PostgreSQLDialect.class, resolver ); + testDetermination( "PostgreSQL", 9, 3, PostgreSQLDialect.class, resolver ); + testDetermination( "PostgreSQL", 9, 4, PostgreSQLDialect.class, resolver ); + testDetermination( "PostgreSQL", 9, 5, PostgreSQLDialect.class, resolver ); + testDetermination( "PostgreSQL", 9, 6, PostgreSQLDialect.class, resolver ); testDetermination( "PostgreSQL", 10, 0, PostgreSQLDialect.class, resolver ); testDetermination( "EnterpriseDB", 9, 2, PostgresPlusDialect.class, resolver ); testDetermination( "Apache Derby", 10, 4, DerbyDialect.class, resolver ); - testDetermination( "Apache Derby", 10, 5, DerbyTenFiveDialect.class, resolver ); - testDetermination( "Apache Derby", 10, 6, DerbyTenSixDialect.class, resolver ); - testDetermination( "Apache Derby", 11, 5, DerbyTenSevenDialect.class, resolver ); + testDetermination( "Apache Derby", 10, 5, DerbyDialect.class, resolver ); + testDetermination( "Apache Derby", 10, 6, DerbyDialect.class, resolver ); + testDetermination( "Apache Derby", 11, 5, DerbyDialect.class, resolver ); testDetermination( "Ingres", IngresDialect.class, resolver ); testDetermination( "ingres", IngresDialect.class, resolver ); testDetermination( "INGRES", IngresDialect.class, resolver ); testDetermination( "Microsoft SQL Server Database", SQLServerDialect.class, resolver ); testDetermination( "Microsoft SQL Server", SQLServerDialect.class, resolver ); - testDetermination( "Sybase SQL Server", SybaseASE15Dialect.class, resolver ); - testDetermination( "Adaptive Server Enterprise", SybaseASE15Dialect.class, resolver ); + testDetermination( "Sybase SQL Server", SybaseASEDialect.class, resolver ); + testDetermination( "Adaptive Server Enterprise", SybaseASEDialect.class, resolver ); testDetermination( "Adaptive Server Anywhere", SybaseAnywhereDialect.class, resolver ); - testDetermination( "Informix Dynamic Server", Informix10Dialect.class, resolver ); + testDetermination( "Informix Dynamic Server", InformixDialect.class, resolver ); testDetermination( "DB2/NT", DB2Dialect.class, resolver ); testDetermination( "DB2/LINUX", DB2Dialect.class, resolver ); testDetermination( "DB2/6000", DB2Dialect.class, resolver ); @@ -152,12 +152,12 @@ public class DialectFactoryTest extends BaseUnitTestCase { testDetermination( "DB2/SUN", DB2Dialect.class, resolver ); testDetermination( "DB2/LINUX390", DB2Dialect.class, resolver ); testDetermination( "DB2/AIX64", DB2Dialect.class, resolver ); - testDetermination( "DB2 UDB for AS/400", DB2400Dialect.class, resolver ); - testDetermination( "DB2 UDB for AS/400", 7, 3, DB2400V7R3Dialect.class, resolver ); - testDetermination( "Oracle", 8, Oracle8iDialect.class, resolver ); - testDetermination( "Oracle", 9, Oracle9iDialect.class, resolver ); - testDetermination( "Oracle", 10, Oracle10gDialect.class, resolver ); - testDetermination( "Oracle", 11, Oracle10gDialect.class, resolver ); + testDetermination( "DB2 UDB for AS/400", DB2Dialect.class, resolver ); + testDetermination( "DB2 UDB for AS/400", 7, 3, DB2Dialect.class, resolver ); + testDetermination( "Oracle", 8, OracleDialect.class, resolver ); + testDetermination( "Oracle", 9, OracleDialect.class, resolver ); + testDetermination( "Oracle", 10, OracleDialect.class, resolver ); + testDetermination( "Oracle", 11, OracleDialect.class, resolver ); } @Test diff --git a/hibernate-core/src/test/java/org/hibernate/dialect/resolver/DialectResolverTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/dialect/resolver/DialectResolverTest.java similarity index 99% rename from hibernate-core/src/test/java/org/hibernate/dialect/resolver/DialectResolverTest.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/dialect/resolver/DialectResolverTest.java index a214940d12..73c9361fa2 100644 --- a/hibernate-core/src/test/java/org/hibernate/dialect/resolver/DialectResolverTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/dialect/resolver/DialectResolverTest.java @@ -4,7 +4,7 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or . */ -package org.hibernate.dialect.resolver; +package org.hibernate.orm.test.dialect.resolver; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/dialect/resolver/DiscoveredDialectResolverTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/dialect/resolver/DiscoveredDialectResolverTests.java new file mode 100644 index 0000000000..16a83b303d --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/dialect/resolver/DiscoveredDialectResolverTests.java @@ -0,0 +1,64 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html + */ +package org.hibernate.orm.test.dialect.resolver; + +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.dialect.Dialect; +import org.hibernate.dialect.H2Dialect; +import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo; +import org.hibernate.engine.jdbc.dialect.spi.DialectResolver; +import org.hibernate.engine.spi.SessionFactoryImplementor; + +import org.hibernate.testing.orm.junit.BootstrapServiceRegistry; +import org.hibernate.testing.orm.junit.BootstrapServiceRegistry.JavaService; +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.ServiceRegistry; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.hibernate.testing.orm.junit.Setting; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.instanceOf; + +/** + * Tests discovery of DialectResolvers via Java's {@link java.util.ServiceLoader} + */ +@BootstrapServiceRegistry( + javaServices = @JavaService( + role = DialectResolver.class, + impl = DiscoveredDialectResolverTests.CustomDialectResolverImpl.class + ) +) +@ServiceRegistry( + // force discovery + settings = @Setting( name = AvailableSettings.DIALECT, value = "" ) +) +@DomainModel +@SessionFactory +public class DiscoveredDialectResolverTests { + @Test + public void testRegistration(SessionFactoryScope scope) { + final SessionFactoryImplementor sessionFactory = scope.getSessionFactory(); + + final Dialect dialect = sessionFactory.getJdbcServices().getDialect(); + assertThat( dialect, instanceOf( CustomDialect.class ) ); + } + + public static class CustomDialectResolverImpl implements DialectResolver { + public CustomDialectResolverImpl() { + } + + @Override + public Dialect resolveDialect(DialectResolutionInfo info) { + return new CustomDialect(); + } + } + + public static class CustomDialect extends H2Dialect { + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/dialect/resolver/TestingDialectResolutionInfo.java b/hibernate-core/src/test/java/org/hibernate/orm/test/dialect/resolver/TestingDialectResolutionInfo.java similarity index 75% rename from hibernate-core/src/test/java/org/hibernate/dialect/resolver/TestingDialectResolutionInfo.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/dialect/resolver/TestingDialectResolutionInfo.java index 40e2fdd044..d8c57b7d37 100644 --- a/hibernate-core/src/test/java/org/hibernate/dialect/resolver/TestingDialectResolutionInfo.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/dialect/resolver/TestingDialectResolutionInfo.java @@ -4,12 +4,12 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or . */ -package org.hibernate.dialect.resolver; +package org.hibernate.orm.test.dialect.resolver; import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo; /** -* @author Steve Ebersole + * DialectResolutionInfo implementation used in testing */ public class TestingDialectResolutionInfo implements DialectResolutionInfo { private final String databaseName; @@ -58,17 +58,28 @@ public class TestingDialectResolutionInfo implements DialectResolutionInfo { @Override public String getDatabaseVersion() { - return databaseMajorVersion + "." + databaseMinorVersion; + if ( databaseMajorVersion == NO_VERSION ) { + if ( databaseMinorVersion == NO_VERSION ) { + return null; + } + return Integer.toString( databaseMinorVersion ); + } + else { + if ( databaseMinorVersion == NO_VERSION ) { + return Integer.toString( databaseMajorVersion ); + } + return databaseMajorVersion + "." + databaseMinorVersion; + } } @Override public int getDatabaseMajorVersion() { - return databaseMajorVersion; + return databaseMajorVersion == NO_VERSION ? 0 : databaseMajorVersion; } @Override public int getDatabaseMinorVersion() { - return databaseMinorVersion; + return databaseMinorVersion == NO_VERSION ? 0 : databaseMinorVersion; } @Override @@ -78,11 +89,11 @@ public class TestingDialectResolutionInfo implements DialectResolutionInfo { @Override public int getDriverMajorVersion() { - return driverMajorVersion; + return driverMajorVersion == NO_VERSION ? 0 : driverMajorVersion; } @Override public int getDriverMinorVersion() { - return driverMinorVersion; + return driverMinorVersion == NO_VERSION ? 0 : driverMinorVersion; } } diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/orm/junit/DomainModelExtension.java b/hibernate-testing/src/main/java/org/hibernate/testing/orm/junit/DomainModelExtension.java index 6964c91fd3..7c3cea6067 100644 --- a/hibernate-testing/src/main/java/org/hibernate/testing/orm/junit/DomainModelExtension.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/orm/junit/DomainModelExtension.java @@ -76,16 +76,16 @@ public class DomainModelExtension throw new RuntimeException( "Unable to determine how to handle given ExtensionContext : " + context.getDisplayName() ); } - final Optional testDomainAnnotationWrapper = AnnotationSupport.findAnnotation( + final Optional domainModelAnnotationWrapper = AnnotationSupport.findAnnotation( context.getElement().get(), DomainModel.class ); - if ( !testDomainAnnotationWrapper.isPresent() ) { - throw new RuntimeException( "Could not locate @TestDomain annotation : " + context.getDisplayName() ); + if ( !domainModelAnnotationWrapper.isPresent() ) { + throw new RuntimeException( "Could not locate @DomainModel annotation : " + context.getDisplayName() ); } - final DomainModel domainModelAnnotation = testDomainAnnotationWrapper.get(); + final DomainModel domainModelAnnotation = domainModelAnnotationWrapper.get(); final MetadataSources metadataSources = new MetadataSources( serviceRegistry );