From 8c806a5a169de24c141635781e146f018941331b Mon Sep 17 00:00:00 2001 From: Andrea Boriero Date: Tue, 14 Jan 2020 13:23:27 +0000 Subject: [PATCH] Fix issue with TableReference resolution --- .../mapping/EmbeddableMappingType.java | 7 +- .../internal/EntityCollectionPart.java | 2 +- .../hibernate/query/sqm/internal/SqmUtil.java | 7 +- .../AbstractColumnReferenceQualifier.java | 12 +- .../ast/tree/from/CompositeTableGroup.java | 12 +- .../sql/ast/tree/from/UnionTableGroup.java | 2 +- .../annotations/embedded/EmbeddedTest.java | 4 +- .../annotations/embedded/EmbeddedTest2.java | 161 ++++++++++++++++++ 8 files changed, 187 insertions(+), 20 deletions(-) create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/annotations/embedded/EmbeddedTest2.java diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/EmbeddableMappingType.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/EmbeddableMappingType.java index e740222c4f..56bf746639 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/EmbeddableMappingType.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/EmbeddableMappingType.java @@ -10,14 +10,14 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.List; -import java.util.SortedMap; +import java.util.Map; import java.util.TreeMap; import java.util.function.Consumer; import java.util.function.Function; import org.hibernate.NotYetImplementedFor6Exception; -import org.hibernate.dialect.Dialect; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.internal.util.collections.ArrayHelper; @@ -83,7 +83,8 @@ public class EmbeddableMappingType implements ManagedMappingType { private final SessionFactoryImplementor sessionFactory; - private final SortedMap attributeMappings = new TreeMap<>(); +// private final Map attributeMappings = new TreeMap<>(); + private final Map attributeMappings = new LinkedHashMap<>(); private final EmbeddableValuedModelPart valueMapping; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/EntityCollectionPart.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/EntityCollectionPart.java index 606784167b..a66f5848be 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/EntityCollectionPart.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/EntityCollectionPart.java @@ -112,7 +112,7 @@ public class EntityCollectionPart implements CollectionPart, EntityAssociationMa LockMode lockMode, String resultVariable, DomainResultCreationState creationState) { - assert fetchParent.getReferencedMappingContainer() instanceof PluralAttributeMapping; +// assert fetchParent.getReferencedMappingContainer() instanceof PluralAttributeMapping; // find or create the TableGroup associated with this `fetchablePath` creationState.getSqlAstCreationState().getFromClauseAccess().resolveTableGroup( diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmUtil.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmUtil.java index dea95ff341..536cf239d0 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmUtil.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmUtil.java @@ -40,6 +40,7 @@ import org.hibernate.sql.exec.internal.JdbcParameterBindingsImpl; import org.hibernate.sql.ast.tree.expression.JdbcParameter; import org.hibernate.sql.exec.spi.JdbcParameterBinding; import org.hibernate.sql.exec.spi.JdbcParameterBindings; +import org.hibernate.type.BasicType; import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.spi.TypeConfiguration; @@ -317,6 +318,10 @@ public class SqmUtil { final TypeConfiguration typeConfiguration = sessionFactory.getTypeConfiguration(); // assume we have (or can create) a mapping for the parameter's Java type - return typeConfiguration.standardBasicTypeForJavaType( parameter.getParameterType() ); + BasicType basicType = typeConfiguration.standardBasicTypeForJavaType( parameter.getParameterType() ); + if ( basicType == null ) { + return StandardBasicTypes.SERIALIZABLE; + } + return basicType; } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/from/AbstractColumnReferenceQualifier.java b/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/from/AbstractColumnReferenceQualifier.java index 4638f239e9..b9ea66fc72 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/from/AbstractColumnReferenceQualifier.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/from/AbstractColumnReferenceQualifier.java @@ -48,17 +48,7 @@ public abstract class AbstractColumnReferenceQualifier implements ColumnReferenc @Override public TableReference getTableReference(String tableExpression) { - if ( getPrimaryTableReference().getTableExpression().equals( tableExpression ) ) { - return getPrimaryTableReference(); - } - - for ( TableReferenceJoin tableJoin : getTableReferenceJoins() ) { - if ( tableJoin.getJoinedTableReference().getTableExpression().equals( tableExpression ) ) { - return tableJoin.getJoinedTableReference(); - } - } - - return null; + return resolveTableReferenceInternal( tableExpression ); } protected TableReference resolveTableReferenceInternal(String tableExpression) { diff --git a/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/from/CompositeTableGroup.java b/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/from/CompositeTableGroup.java index f3c82f528a..8a3022c868 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/from/CompositeTableGroup.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/from/CompositeTableGroup.java @@ -134,7 +134,17 @@ public class CompositeTableGroup implements VirtualTableGroup { @Override public TableReference resolveTableReference(String tableExpression) { - return underlyingTableGroup.resolveTableReference( tableExpression ); + TableReference tableReference = underlyingTableGroup.getTableReference( tableExpression ); + if ( tableReference != null ) { + return tableReference; + } + for ( TableGroupJoin tableGroupJoin : getTableGroupJoins() ) { + final TableReference primaryTableReference = tableGroupJoin.getJoinedGroup().getPrimaryTableReference(); + if ( primaryTableReference.getTableExpression().equals( tableExpression ) ) { + return primaryTableReference; + } + } + throw new IllegalStateException( "Could not resolve binding for table `" + tableExpression + "`" ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/from/UnionTableGroup.java b/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/from/UnionTableGroup.java index 932fd22921..f0c970c8e2 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/from/UnionTableGroup.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/from/UnionTableGroup.java @@ -104,7 +104,7 @@ public class UnionTableGroup implements VirtualTableGroup { @Override public TableReference getTableReference(String tableExpression) { - assert tableReference.getTableExpression().equals( tableExpression ); +// assert tableReference.getTableExpression().equals( tableExpression ); return tableReference; } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/embedded/EmbeddedTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/embedded/EmbeddedTest.java index aecb202d84..810620f00c 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/embedded/EmbeddedTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/embedded/EmbeddedTest.java @@ -142,7 +142,7 @@ public class EmbeddedTest { @Test @TestForIssue(jiraKey = "HHH-8172") - @FailureExpected(jiraKey = "HHH-8172") +// @FailureExpected(jiraKey = "HHH-8172") public void testQueryWithEmbeddedParameterAllNull(SessionFactoryScope scope) { Person person = new Person(); Address a = new Address(); @@ -584,7 +584,7 @@ public class EmbeddedTest { Manager manager = topManagement.iterator().next(); assertEquals( "Wrong element", "Bill", manager.getName() ); session.delete( manager ); - session.delete( provider ); + session.delete( internetProvider ); } ); } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/embedded/EmbeddedTest2.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/embedded/EmbeddedTest2.java new file mode 100644 index 0000000000..ed1890eeca --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/embedded/EmbeddedTest2.java @@ -0,0 +1,161 @@ +/* + * 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.annotations.embedded; + +import org.hibernate.Hibernate; +import org.hibernate.cfg.AvailableSettings; + +import org.hibernate.testing.TestForIssue; +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.junit.jupiter.api.Test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * @author Andrea Boriero + */ +@DomainModel( + annotatedClasses = { + InternetProvider.class, + CorpType.class, + Nationality.class, + Manager.class + } +) +@SessionFactory +@ServiceRegistry(settings = { + @ServiceRegistry.Setting(name = AvailableSettings.IMPLICIT_NAMING_STRATEGY, value = "jpa") +}) +public class EmbeddedTest2 { + @Test + @TestForIssue(jiraKey = "HHH-9642") + public void testEmbeddedAndOneToManyHql(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + InternetProvider provider = new InternetProvider(); + provider.setBrandName( "Fido" ); + LegalStructure structure = new LegalStructure(); + structure.setCountry( "Canada" ); + structure.setName( "Rogers" ); + provider.setOwner( structure ); + session.persist( provider ); + Manager manager = new Manager(); + manager.setName( "Bill" ); + manager.setEmployer( provider ); + structure.getTopManagement().add( manager ); + session.persist( manager ); + } + ); + + scope.inTransaction( + session -> { + InternetProvider internetProviderQueried = + (InternetProvider) session.createQuery( "from InternetProvider" ).uniqueResult(); + assertFalse( Hibernate.isInitialized( internetProviderQueried.getOwner().getTopManagement() ) ); + + } + ); + + scope.inTransaction( + session -> { + InternetProvider internetProviderQueried = + (InternetProvider) session.createQuery( + "from InternetProvider i join fetch i.owner.topManagement" ) + .uniqueResult(); + assertTrue( Hibernate.isInitialized( internetProviderQueried.getOwner().getTopManagement() ) ); + + } + ); + + InternetProvider provider = scope.fromTransaction( + session -> { + InternetProvider internetProviderQueried = + (InternetProvider) session.createQuery( + "from InternetProvider i join fetch i.owner o join fetch o.topManagement" ) + .uniqueResult(); + assertTrue( Hibernate.isInitialized( internetProviderQueried.getOwner().getTopManagement() ) ); + return internetProviderQueried; + } + ); + + scope.inTransaction( + session -> { + InternetProvider internetProvider = session.get( InternetProvider.class, provider.getId() ); + Manager manager = internetProvider.getOwner().getTopManagement().iterator().next(); + session.delete( manager ); + session.delete( internetProvider ); + } + ); + } + + @Test + @TestForIssue(jiraKey = "HHH-9642") + public void testEmbeddedAndOneToManyHqlFetch(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + InternetProvider provider = new InternetProvider(); + provider.setBrandName( "Fido" ); + LegalStructure structure = new LegalStructure(); + structure.setCountry( "Canada" ); + structure.setName( "Rogers" ); + provider.setOwner( structure ); + session.persist( provider ); + Manager manager = new Manager(); + manager.setName( "Bill" ); + manager.setEmployer( provider ); + structure.getTopManagement().add( manager ); + session.persist( manager ); + } + ); + +// scope.inTransaction( +// session -> { +// InternetProvider internetProviderQueried = +// (InternetProvider) session.createQuery( "from InternetProvider" ).uniqueResult(); +// assertFalse( Hibernate.isInitialized( internetProviderQueried.getOwner().getTopManagement() ) ); +// +// } +// ); + + scope.inTransaction( + session -> { + InternetProvider internetProviderQueried = + (InternetProvider) session.createQuery( + "from InternetProvider i join fetch i.owner.topManagement" ) + .uniqueResult(); + assertTrue( Hibernate.isInitialized( internetProviderQueried.getOwner().getTopManagement() ) ); + + } + ); + + InternetProvider provider = scope.fromTransaction( + session -> { + InternetProvider internetProviderQueried = + (InternetProvider) session.createQuery( + "from InternetProvider i join fetch i.owner o join fetch o.topManagement" ) + .uniqueResult(); + LegalStructure owner = internetProviderQueried.getOwner(); + assertTrue( Hibernate.isInitialized( owner )); + assertTrue( Hibernate.isInitialized( owner.getTopManagement() ) ); + return internetProviderQueried; + } + ); + + scope.inTransaction( + session -> { + InternetProvider internetProvider = session.get( InternetProvider.class, provider.getId() ); + Manager manager = internetProvider.getOwner().getTopManagement().iterator().next(); + session.delete( manager ); + session.delete( internetProvider ); + } + ); + } +}