From cdde935263489e1b4a2ef070dd914a4b75efcd42 Mon Sep 17 00:00:00 2001 From: Francois van Delft Date: Thu, 6 Feb 2020 16:13:49 +0100 Subject: [PATCH 1/4] HHH-13843: make schema migration faster --- .../DatabaseInformationCachedImpl.java | 60 +++++++++++++++++++ .../internal/AbstractSchemaMigrator.java | 8 +-- .../internal/GroupedSchemaMigratorImpl.java | 18 ++++++ .../IndividuallySchemaMigratorImpl.java | 5 ++ .../CheckForExistingForeignKeyTest.java | 8 +++ 5 files changed, 94 insertions(+), 5 deletions(-) create mode 100644 hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/DatabaseInformationCachedImpl.java diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/DatabaseInformationCachedImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/DatabaseInformationCachedImpl.java new file mode 100644 index 000000000000..ec93d5e0b480 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/DatabaseInformationCachedImpl.java @@ -0,0 +1,60 @@ +/* + * 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 . + */ +package org.hibernate.tool.schema.extract.internal; + +import java.sql.SQLException; + +import org.hibernate.boot.model.relational.Namespace; +import org.hibernate.boot.model.relational.QualifiedTableName; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.hibernate.resource.transaction.spi.DdlTransactionIsolator; +import org.hibernate.service.ServiceRegistry; +import org.hibernate.tool.schema.extract.spi.NameSpaceTablesInformation; +import org.hibernate.tool.schema.extract.spi.TableInformation; + +/** + * Will cache all database information by reading the tableinformation from the name space in one call. + * Schema migration becomes much faster when this object is used. + * NOTE: superclass already caches the sequence information, so perhaps cache can also be coded in superlcass + * @author francois + */ +public class DatabaseInformationCachedImpl extends DatabaseInformationImpl { + private NameSpaceTablesInformation defaultNameSpaceTablesInformation = null; + private final Namespace defaultNamespace; + + /** + * + * @param serviceRegistry ServiceRegistry + * @param jdbcEnvironment JdbcEnvironment + * @param ddlTransactionIsolator DdlTransactionIsolator + * @param defaultNamespace NameSpace + */ + public DatabaseInformationCachedImpl( + ServiceRegistry serviceRegistry, + JdbcEnvironment jdbcEnvironment, + DdlTransactionIsolator ddlTransactionIsolator, Namespace defaultNamespace) + throws SQLException { + super(serviceRegistry, jdbcEnvironment, ddlTransactionIsolator, defaultNamespace.getName()); + this.defaultNamespace = defaultNamespace; + } + + @Override + public TableInformation getTableInformation(QualifiedTableName qualifiedTableName) { + + if (defaultNameSpaceTablesInformation == null) { + // Load table information from the whole space in one go (expected to be used in case of schemaMigration, so (almost) all + // tables are likely to be retrieved) + defaultNameSpaceTablesInformation = getTablesInformation(defaultNamespace); + } + TableInformation tableInformation = defaultNameSpaceTablesInformation.getTableInformation(qualifiedTableName.getTableName().getText()); + if (tableInformation != null) { + return tableInformation; + } + return super.getTableInformation(qualifiedTableName); // result of this call can of course also be cached, does not seem to be in scope now + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/AbstractSchemaMigrator.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/AbstractSchemaMigrator.java index e38b3034b076..1bc023b90740 100644 --- a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/AbstractSchemaMigrator.java +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/AbstractSchemaMigrator.java @@ -93,11 +93,7 @@ public void doMigration(Metadata metadata, ExecutionOptions options, TargetDescr final JdbcContext jdbcContext = tool.resolveJdbcContext( options.getConfigurationValues() ); final DdlTransactionIsolator ddlTransactionIsolator = tool.getDdlTransactionIsolator( jdbcContext ); try { - final DatabaseInformation databaseInformation = Helper.buildDatabaseInformation( - tool.getServiceRegistry(), - ddlTransactionIsolator, - metadata.getDatabase().getDefaultNamespace().getName() - ); + final DatabaseInformation databaseInformation = getDatabaseInformation(ddlTransactionIsolator, metadata.getDatabase().getDefaultNamespace()); final GenerationTarget[] targets = tool.buildGenerationTargets( targetDescriptor, @@ -139,6 +135,8 @@ public void doMigration(Metadata metadata, ExecutionOptions options, TargetDescr } } + protected abstract DatabaseInformation getDatabaseInformation(DdlTransactionIsolator ddlTransactionIsolator, Namespace namespace); + protected abstract NameSpaceTablesInformation performTablesMigration( Metadata metadata, DatabaseInformation existingDatabase, diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/GroupedSchemaMigratorImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/GroupedSchemaMigratorImpl.java index aada23b2aac0..141ed4b7b8ac 100644 --- a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/GroupedSchemaMigratorImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/GroupedSchemaMigratorImpl.java @@ -6,14 +6,18 @@ */ package org.hibernate.tool.schema.internal; +import java.sql.SQLException; import java.util.Set; import org.hibernate.boot.Metadata; import org.hibernate.boot.model.naming.Identifier; import org.hibernate.boot.model.relational.Namespace; import org.hibernate.dialect.Dialect; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; import org.hibernate.engine.jdbc.internal.Formatter; import org.hibernate.mapping.Table; +import org.hibernate.resource.transaction.spi.DdlTransactionIsolator; +import org.hibernate.tool.schema.extract.internal.DatabaseInformationCachedImpl; import org.hibernate.tool.schema.extract.spi.DatabaseInformation; import org.hibernate.tool.schema.extract.spi.NameSpaceTablesInformation; import org.hibernate.tool.schema.extract.spi.TableInformation; @@ -35,6 +39,20 @@ public GroupedSchemaMigratorImpl( super( tool, schemaFilter ); } + protected DatabaseInformation getDatabaseInformation(DdlTransactionIsolator ddlTransactionIsolator, Namespace namespace) { + final JdbcEnvironment jdbcEnvironment = tool.getServiceRegistry().getService( JdbcEnvironment.class ); + try { + return new DatabaseInformationCachedImpl( + tool.getServiceRegistry(), + jdbcEnvironment, + ddlTransactionIsolator, + namespace); + } + catch (SQLException e) { + throw jdbcEnvironment.getSqlExceptionHelper().convert( e, "Unable to build DatabaseInformationCached" ); + } + } + @Override protected NameSpaceTablesInformation performTablesMigration( Metadata metadata, diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/IndividuallySchemaMigratorImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/IndividuallySchemaMigratorImpl.java index 0f2ae8a6dd0e..73d19ba319b9 100644 --- a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/IndividuallySchemaMigratorImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/IndividuallySchemaMigratorImpl.java @@ -14,6 +14,7 @@ import org.hibernate.dialect.Dialect; import org.hibernate.engine.jdbc.internal.Formatter; import org.hibernate.mapping.Table; +import org.hibernate.resource.transaction.spi.DdlTransactionIsolator; import org.hibernate.tool.schema.extract.spi.DatabaseInformation; import org.hibernate.tool.schema.extract.spi.NameSpaceTablesInformation; import org.hibernate.tool.schema.extract.spi.TableInformation; @@ -35,6 +36,10 @@ public IndividuallySchemaMigratorImpl( super( tool, schemaFilter ); } + protected DatabaseInformation getDatabaseInformation(DdlTransactionIsolator ddlTransactionIsolator, Namespace namespace) { + return Helper.buildDatabaseInformation(tool.getServiceRegistry(), ddlTransactionIsolator, namespace.getName()); + } + @Override protected NameSpaceTablesInformation performTablesMigration( Metadata metadata, diff --git a/hibernate-core/src/test/java/org/hibernate/test/tool/schema/internal/CheckForExistingForeignKeyTest.java b/hibernate-core/src/test/java/org/hibernate/test/tool/schema/internal/CheckForExistingForeignKeyTest.java index a0608944ba62..0c1008d48974 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/tool/schema/internal/CheckForExistingForeignKeyTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/tool/schema/internal/CheckForExistingForeignKeyTest.java @@ -18,6 +18,7 @@ import org.hibernate.mapping.Column; import org.hibernate.mapping.ForeignKey; import org.hibernate.mapping.Table; +import org.hibernate.resource.transaction.spi.DdlTransactionIsolator; import org.hibernate.tool.schema.extract.internal.ColumnInformationImpl; import org.hibernate.tool.schema.extract.internal.ForeignKeyInformationImpl; import org.hibernate.tool.schema.extract.internal.TableInformationImpl; @@ -49,6 +50,13 @@ public SchemaMigrator() { super( null, null ); } + @Override + protected DatabaseInformation getDatabaseInformation( + DdlTransactionIsolator ddlTransactionIsolator, Namespace namespace) + { + return null; + } + /** * Needed implementation. Not used in test. */ From 8782b16abff0ac565048b1324be5d95ff14aa5f7 Mon Sep 17 00:00:00 2001 From: Francois van Delft Date: Fri, 7 Feb 2020 10:46:38 +0100 Subject: [PATCH 2/4] HHH-13843: processed first review comment. I'm in doubt on whether a method for creating a new DatabaseInformationImpl-instance should be created in the Helper-class. Perhaps that class should only contain a "default" method, and not give anything to choose. Alternative is to embed the caching mechanism into the existing DatabaseInformationImpl-class, and use a "setter" or constructor to enable/disable the caching mechanism. --- .../internal/DatabaseInformationCachedImpl.java | 16 ++++++++-------- .../schema/internal/AbstractSchemaMigrator.java | 5 ++++- .../internal/IndividuallySchemaMigratorImpl.java | 4 ---- .../internal/CheckForExistingForeignKeyTest.java | 8 -------- 4 files changed, 12 insertions(+), 21 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/DatabaseInformationCachedImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/DatabaseInformationCachedImpl.java index ec93d5e0b480..8820403e5517 100644 --- a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/DatabaseInformationCachedImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/DatabaseInformationCachedImpl.java @@ -19,11 +19,11 @@ /** * Will cache all database information by reading the tableinformation from the name space in one call. * Schema migration becomes much faster when this object is used. - * NOTE: superclass already caches the sequence information, so perhaps cache can also be coded in superlcass + * NOTE: superclass already caches the sequence information, so perhaps cache can also be coded in superclass * @author francois */ public class DatabaseInformationCachedImpl extends DatabaseInformationImpl { - private NameSpaceTablesInformation defaultNameSpaceTablesInformation = null; + private NameSpaceTablesInformation defaultNameSpaceTablesInformation; private final Namespace defaultNamespace; /** @@ -34,22 +34,22 @@ public class DatabaseInformationCachedImpl extends DatabaseInformationImpl { * @param defaultNamespace NameSpace */ public DatabaseInformationCachedImpl( - ServiceRegistry serviceRegistry, - JdbcEnvironment jdbcEnvironment, - DdlTransactionIsolator ddlTransactionIsolator, Namespace defaultNamespace) - throws SQLException { + ServiceRegistry serviceRegistry, + JdbcEnvironment jdbcEnvironment, + DdlTransactionIsolator ddlTransactionIsolator, Namespace defaultNamespace) + throws SQLException { super(serviceRegistry, jdbcEnvironment, ddlTransactionIsolator, defaultNamespace.getName()); this.defaultNamespace = defaultNamespace; } @Override public TableInformation getTableInformation(QualifiedTableName qualifiedTableName) { - if (defaultNameSpaceTablesInformation == null) { - // Load table information from the whole space in one go (expected to be used in case of schemaMigration, so (almost) all + // Load table information from the whole namespace in one go (expected to be used in case of schemaMigration, so (almost) all // tables are likely to be retrieved) defaultNameSpaceTablesInformation = getTablesInformation(defaultNamespace); } + TableInformation tableInformation = defaultNameSpaceTablesInformation.getTableInformation(qualifiedTableName.getTableName().getText()); if (tableInformation != null) { return tableInformation; diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/AbstractSchemaMigrator.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/AbstractSchemaMigrator.java index 1bc023b90740..6b731499662b 100644 --- a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/AbstractSchemaMigrator.java +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/AbstractSchemaMigrator.java @@ -135,7 +135,10 @@ public void doMigration(Metadata metadata, ExecutionOptions options, TargetDescr } } - protected abstract DatabaseInformation getDatabaseInformation(DdlTransactionIsolator ddlTransactionIsolator, Namespace namespace); + protected DatabaseInformation getDatabaseInformation(DdlTransactionIsolator ddlTransactionIsolator, Namespace namespace) + { + return Helper.buildDatabaseInformation(tool.getServiceRegistry(), ddlTransactionIsolator, namespace.getName()); + } protected abstract NameSpaceTablesInformation performTablesMigration( Metadata metadata, diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/IndividuallySchemaMigratorImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/IndividuallySchemaMigratorImpl.java index 73d19ba319b9..3e5ae24abe02 100644 --- a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/IndividuallySchemaMigratorImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/IndividuallySchemaMigratorImpl.java @@ -36,10 +36,6 @@ public IndividuallySchemaMigratorImpl( super( tool, schemaFilter ); } - protected DatabaseInformation getDatabaseInformation(DdlTransactionIsolator ddlTransactionIsolator, Namespace namespace) { - return Helper.buildDatabaseInformation(tool.getServiceRegistry(), ddlTransactionIsolator, namespace.getName()); - } - @Override protected NameSpaceTablesInformation performTablesMigration( Metadata metadata, diff --git a/hibernate-core/src/test/java/org/hibernate/test/tool/schema/internal/CheckForExistingForeignKeyTest.java b/hibernate-core/src/test/java/org/hibernate/test/tool/schema/internal/CheckForExistingForeignKeyTest.java index 0c1008d48974..a0608944ba62 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/tool/schema/internal/CheckForExistingForeignKeyTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/tool/schema/internal/CheckForExistingForeignKeyTest.java @@ -18,7 +18,6 @@ import org.hibernate.mapping.Column; import org.hibernate.mapping.ForeignKey; import org.hibernate.mapping.Table; -import org.hibernate.resource.transaction.spi.DdlTransactionIsolator; import org.hibernate.tool.schema.extract.internal.ColumnInformationImpl; import org.hibernate.tool.schema.extract.internal.ForeignKeyInformationImpl; import org.hibernate.tool.schema.extract.internal.TableInformationImpl; @@ -50,13 +49,6 @@ public SchemaMigrator() { super( null, null ); } - @Override - protected DatabaseInformation getDatabaseInformation( - DdlTransactionIsolator ddlTransactionIsolator, Namespace namespace) - { - return null; - } - /** * Needed implementation. Not used in test. */ From 3b1ae576b25b64a2029568926a39c688b0bc389f Mon Sep 17 00:00:00 2001 From: Francois van Delft Date: Fri, 7 Feb 2020 11:07:06 +0100 Subject: [PATCH 3/4] HHH-13843: Code style. => sorry --- .../hibernate/tool/schema/internal/AbstractSchemaMigrator.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/AbstractSchemaMigrator.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/AbstractSchemaMigrator.java index 6b731499662b..7413fe67dde3 100644 --- a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/AbstractSchemaMigrator.java +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/AbstractSchemaMigrator.java @@ -135,8 +135,7 @@ public void doMigration(Metadata metadata, ExecutionOptions options, TargetDescr } } - protected DatabaseInformation getDatabaseInformation(DdlTransactionIsolator ddlTransactionIsolator, Namespace namespace) - { + protected DatabaseInformation getDatabaseInformation(DdlTransactionIsolator ddlTransactionIsolator, Namespace namespace) { return Helper.buildDatabaseInformation(tool.getServiceRegistry(), ddlTransactionIsolator, namespace.getName()); } From 9cc6b7b6dec8d0fce90925e4298a09211110fe29 Mon Sep 17 00:00:00 2001 From: Francois van Delft Date: Fri, 7 Feb 2020 12:52:10 +0100 Subject: [PATCH 4/4] HHH-13843: Remove unused import --- .../tool/schema/internal/IndividuallySchemaMigratorImpl.java | 1 - 1 file changed, 1 deletion(-) diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/IndividuallySchemaMigratorImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/IndividuallySchemaMigratorImpl.java index 3e5ae24abe02..0f2ae8a6dd0e 100644 --- a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/IndividuallySchemaMigratorImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/IndividuallySchemaMigratorImpl.java @@ -14,7 +14,6 @@ import org.hibernate.dialect.Dialect; import org.hibernate.engine.jdbc.internal.Formatter; import org.hibernate.mapping.Table; -import org.hibernate.resource.transaction.spi.DdlTransactionIsolator; import org.hibernate.tool.schema.extract.spi.DatabaseInformation; import org.hibernate.tool.schema.extract.spi.NameSpaceTablesInformation; import org.hibernate.tool.schema.extract.spi.TableInformation;