From 1361b5108ce7dd21612430996cab8680428aa172 Mon Sep 17 00:00:00 2001 From: Andrea Boriero Date: Wed, 18 Nov 2020 12:55:18 +0100 Subject: [PATCH] Re-enabled additional tests and fixed IdClass issues --- .../internal/MappingModelCreationHelper.java | 7 ++- .../NonAggregatedIdentifierMappingImpl.java | 45 ++++++++++++++--- .../entity/AbstractEntityPersister.java | 24 +++++++-- .../id/idclass/IdClassNamingStrategyTest.java | 50 ------------------- .../test}/id/IdClassManyToOneCascadeTest.java | 2 +- .../id/idClass/IdClassNamingStrategyTest.java | 47 +++++++++++++++++ .../idclass => test/id/idClass}/MyEntity.java | 2 +- .../id/idClass}/MyEntityId.java | 2 +- 8 files changed, 113 insertions(+), 66 deletions(-) delete mode 100644 hibernate-core/src/test/java/org/hibernate/id/idclass/IdClassNamingStrategyTest.java rename hibernate-core/src/test/java/org/hibernate/{ => orm/test}/id/IdClassManyToOneCascadeTest.java (98%) create mode 100644 hibernate-core/src/test/java/org/hibernate/test/id/idClass/IdClassNamingStrategyTest.java rename hibernate-core/src/test/java/org/hibernate/{id/idclass => test/id/idClass}/MyEntity.java (95%) rename hibernate-core/src/test/java/org/hibernate/{id/idclass => test/id/idClass}/MyEntityId.java (96%) diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/MappingModelCreationHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/MappingModelCreationHelper.java index 1b4725e29c..aa0189492a 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/MappingModelCreationHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/MappingModelCreationHelper.java @@ -166,8 +166,11 @@ public class MappingModelCreationHelper { final StateArrayContributorMetadataAccess attributeMetadataAccess = getStateArrayContributorMetadataAccess( propertyAccess ); - final Component bootIdDescriptor = (Component) bootEntityDescriptor.getIdentifier(); final Component idClass = bootEntityDescriptor.getIdentifierMapper(); + Component bootIdDescriptor = bootEntityDescriptor.getDeclaredIdentifierMapper(); + if ( bootIdDescriptor == null ) { + bootIdDescriptor = (Component) bootEntityDescriptor.getIdentifier(); + } final List idAttributeMappings = new ArrayList<>( bootIdDescriptor.getPropertySpan() ); //noinspection unchecked @@ -253,8 +256,8 @@ public class MappingModelCreationHelper { attributeMetadataAccess, rootTableName, rootTableKeyColumnNames, + bootIdDescriptor, bootCompositeDescriptor, - bootEntityDescriptor.getDeclaredIdentifierMapper(), creationProcess ); }, diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/NonAggregatedIdentifierMappingImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/NonAggregatedIdentifierMappingImpl.java index a9c7da9c63..41927e7d30 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/NonAggregatedIdentifierMappingImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/NonAggregatedIdentifierMappingImpl.java @@ -10,15 +10,20 @@ import java.io.Serializable; import java.util.Collection; import java.util.List; +import org.hibernate.engine.spi.EntityKey; +import org.hibernate.engine.spi.PersistenceContext; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.internal.util.MutableInteger; import org.hibernate.mapping.Component; +import org.hibernate.mapping.ManyToOne; +import org.hibernate.mapping.Property; import org.hibernate.metamodel.internal.AbstractCompositeIdentifierMapping; import org.hibernate.metamodel.mapping.EmbeddableMappingType; import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.SingularAttributeMapping; import org.hibernate.metamodel.mapping.StateArrayContributorMetadataAccess; +import org.hibernate.persister.entity.EntityPersister; import org.hibernate.proxy.HibernateProxy; import org.hibernate.type.ComponentType; @@ -76,21 +81,47 @@ public class NonAggregatedIdentifierMappingImpl extends AbstractCompositeIdentif if ( entity instanceof HibernateProxy ) { return ( (HibernateProxy) entity ).getHibernateLazyInitializer().getIdentifier(); } - final Serializable disassemble = bootIdClassDescriptor.getType().disassemble( entity, session, null ); - return bootCidDescriptor.getType().assemble( disassemble, session, null ); + final Serializable disassemble = bootCidDescriptor.getType().disassemble( entity, session, null ); + return bootIdClassDescriptor.getType().assemble( disassemble, session, null ); } @Override public void setIdentifier(Object entity, Object id, SharedSessionContractImplementor session) { final SessionFactoryImplementor factory = session.getFactory(); - final Object[] propertyValues = ( (ComponentType) bootCidDescriptor.getType() ) + final Object[] propertyValues = ( (ComponentType) bootIdClassDescriptor.getType() ) .getPropertyValues( id, session ); final MutableInteger index = new MutableInteger(); getAttributes().forEach( - attribute -> - attribute.getPropertyAccess() - .getSetter() - .set( entity, propertyValues[index.getAndIncrement()], factory ) + attribute -> { + final int position = index.getAndIncrement(); + Object propertyValue = propertyValues[position]; + final Property property = bootIdClassDescriptor.getProperty( position ); + if ( attribute instanceof ToOneAttributeMapping && !( property.getValue() instanceof ManyToOne ) ) { + final ToOneAttributeMapping toOneAttributeMapping = (ToOneAttributeMapping) attribute; + final EntityPersister entityPersister = toOneAttributeMapping.getEntityMappingType() + .getEntityPersister(); + final EntityKey entityKey = session.generateEntityKey( + propertyValue, + entityPersister + ); + final PersistenceContext persistenceContext = session.getPersistenceContext(); + // it is conceivable there is a proxy, so check that first + propertyValue = persistenceContext.getProxy( entityKey ); + if ( propertyValue == null ) { + // otherwise look for an initialized version + propertyValue = persistenceContext.getEntity( entityKey ); + if ( propertyValue == null ) { + // get the association out of the entity itself + propertyValue = factory.getMetamodel() + .findEntityDescriptor( entity.getClass() ) + .getPropertyValue( entity, toOneAttributeMapping.getAttributeName() ); + } + } + } + attribute.getPropertyAccess() + .getSetter() + .set( entity, propertyValue, factory ); + } ); } diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java index f31efc45f9..d2cbc1e3c2 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java @@ -112,6 +112,7 @@ import org.hibernate.internal.util.collections.LockModeEnumMap; import org.hibernate.jdbc.Expectation; import org.hibernate.jdbc.Expectations; import org.hibernate.jdbc.TooManyRowsAffectedException; +import org.hibernate.loader.PropertyPath; import org.hibernate.loader.ast.internal.MultiIdLoaderStandard; import org.hibernate.loader.ast.internal.Preparable; import org.hibernate.loader.ast.internal.SingleIdEntityLoaderDynamicBatch; @@ -158,6 +159,7 @@ import org.hibernate.metamodel.mapping.StateArrayContributorMetadata; import org.hibernate.metamodel.mapping.internal.BasicEntityIdentifierMappingImpl; import org.hibernate.metamodel.mapping.internal.CompoundNaturalIdMapping; import org.hibernate.metamodel.mapping.internal.DiscriminatedAssociationAttributeMapping; +import org.hibernate.metamodel.mapping.internal.EmbeddedAttributeMapping; import org.hibernate.metamodel.mapping.internal.EntityDiscriminatorMappingImpl; import org.hibernate.metamodel.mapping.internal.EntityRowIdMappingImpl; import org.hibernate.metamodel.mapping.internal.EntityVersionMappingImpl; @@ -5309,8 +5311,8 @@ public abstract class AbstractEntityPersister else { final Object[] values = new Object[ getNumberOfAttributeMappings() ]; for ( int i = 0; i < attributeMappings.size(); i++ ) { - AttributeMapping attributeMapping = attributeMappings.get( i ); - AttributeMetadataAccess attributeMetadataAccess = attributeMapping.getAttributeMetadataAccess(); + final AttributeMapping attributeMapping = attributeMappings.get( i ); + final AttributeMetadataAccess attributeMetadataAccess = attributeMapping.getAttributeMetadataAccess(); values[ i ] = attributeMetadataAccess .resolveAttributeMetadata( this ) .getPropertyAccess() @@ -5334,13 +5336,27 @@ public abstract class AbstractEntityPersister @Override public Object getPropertyValue(Object object, String propertyName) { for ( int i = 0; i < attributeMappings.size(); i++ ) { - if ( attributeMappings.get( i ).getAttributeName().equals( propertyName ) ) { - return attributeMappings.get( i ).getAttributeMetadataAccess() + final AttributeMapping attributeMapping = attributeMappings.get( i ); + final String attributeName = attributeMapping.getAttributeName(); + if ( attributeName.equals( propertyName ) ) { + return attributeMapping.getAttributeMetadataAccess() .resolveAttributeMetadata( this ) .getPropertyAccess() .getGetter() .get( object ); } + else if ( attributeName.equals( PropertyPath.IDENTIFIER_MAPPER_PROPERTY ) && attributeMapping instanceof EmbeddedAttributeMapping ) { + final EmbeddedAttributeMapping embeddedAttributeMapping = (EmbeddedAttributeMapping) attributeMapping; + final AttributeMapping mapping = embeddedAttributeMapping.getMappedType() + .findAttributeMapping( propertyName ); + if ( mapping != null ) { + return mapping.getAttributeMetadataAccess() + .resolveAttributeMetadata( this ) + .getPropertyAccess() + .getGetter() + .get( object ); + } + } } return null; } diff --git a/hibernate-core/src/test/java/org/hibernate/id/idclass/IdClassNamingStrategyTest.java b/hibernate-core/src/test/java/org/hibernate/id/idclass/IdClassNamingStrategyTest.java deleted file mode 100644 index ca3ca493b3..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/id/idclass/IdClassNamingStrategyTest.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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.id.idclass; - -import org.hibernate.boot.model.naming.ImplicitNamingStrategyComponentPathImpl; -import org.hibernate.cfg.Configuration; - -import org.hibernate.testing.TestForIssue; -import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; -import org.junit.Test; - -public class IdClassNamingStrategyTest extends BaseCoreFunctionalTestCase { - - @Override - protected Class[] getAnnotatedClasses() { - return new Class[] { MyEntity.class }; - } - - @Override - protected void configure(Configuration configuration) { - /* - * With this implicit naming strategy, we got the following mapping: - * - * create table MyEntity ( - * id_idA bigint not null, - * id_idB bigint not null, - * _identifierMapper_idA bigint not null, <-- ?? - * _identifierMapper_idB bigint not null, <-- ?? - * notes varchar(255), - * primary key (id_idA, id_idB) - * ) - */ - configuration.setImplicitNamingStrategy( new ImplicitNamingStrategyComponentPathImpl() ); - } - - @Test - @TestForIssue(jiraKey = "HHH-14241") - public void test() { - inTransaction( ( session ) -> { - MyEntity entity = new MyEntity(); - entity.setId( new MyEntityId( 739L, 777L ) ); - - session.persist( entity ); - } ); - } -} diff --git a/hibernate-core/src/test/java/org/hibernate/id/IdClassManyToOneCascadeTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/id/IdClassManyToOneCascadeTest.java similarity index 98% rename from hibernate-core/src/test/java/org/hibernate/id/IdClassManyToOneCascadeTest.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/id/IdClassManyToOneCascadeTest.java index 35da3f7153..b67c0f5ccb 100644 --- a/hibernate-core/src/test/java/org/hibernate/id/IdClassManyToOneCascadeTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/id/IdClassManyToOneCascadeTest.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.id; +package org.hibernate.orm.test.id; import java.io.Serializable; import javax.persistence.Entity; diff --git a/hibernate-core/src/test/java/org/hibernate/test/id/idClass/IdClassNamingStrategyTest.java b/hibernate-core/src/test/java/org/hibernate/test/id/idClass/IdClassNamingStrategyTest.java new file mode 100644 index 0000000000..32e7bb5697 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/id/idClass/IdClassNamingStrategyTest.java @@ -0,0 +1,47 @@ +/* + * 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.test.id.idClass; + +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.hibernate.cfg.AvailableSettings.IMPLICIT_NAMING_STRATEGY; + +@DomainModel( + annotatedClasses = MyEntity.class +) +@SessionFactory +/* + * With this implicit naming strategy, we got the following mapping: + * + * create table MyEntity ( + * id_idA bigint not null, + * id_idB bigint not null, + * _identifierMapper_idA bigint not null, <-- ?? + * _identifierMapper_idB bigint not null, <-- ?? + * notes varchar(255), + * primary key (id_idA, id_idB) + * ) + */ +@ServiceRegistry(settings = @ServiceRegistry.Setting(name = IMPLICIT_NAMING_STRATEGY, value = "component-path")) +public class IdClassNamingStrategyTest { + + @Test + @TestForIssue(jiraKey = "HHH-14241") + public void test(SessionFactoryScope scope) { + scope.inTransaction( (session) -> { + MyEntity entity = new MyEntity(); + entity.setId( new MyEntityId( 739L, 777L ) ); + + session.persist( entity ); + } ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/id/idclass/MyEntity.java b/hibernate-core/src/test/java/org/hibernate/test/id/idClass/MyEntity.java similarity index 95% rename from hibernate-core/src/test/java/org/hibernate/id/idclass/MyEntity.java rename to hibernate-core/src/test/java/org/hibernate/test/id/idClass/MyEntity.java index 924b898ce1..1bc1ea6dfa 100644 --- a/hibernate-core/src/test/java/org/hibernate/id/idclass/MyEntity.java +++ b/hibernate-core/src/test/java/org/hibernate/test/id/idClass/MyEntity.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.id.idclass; +package org.hibernate.test.id.idClass; import javax.persistence.Entity; import javax.persistence.Id; diff --git a/hibernate-core/src/test/java/org/hibernate/id/idclass/MyEntityId.java b/hibernate-core/src/test/java/org/hibernate/test/id/idClass/MyEntityId.java similarity index 96% rename from hibernate-core/src/test/java/org/hibernate/id/idclass/MyEntityId.java rename to hibernate-core/src/test/java/org/hibernate/test/id/idClass/MyEntityId.java index 4915db393c..175d3e2515 100644 --- a/hibernate-core/src/test/java/org/hibernate/id/idclass/MyEntityId.java +++ b/hibernate-core/src/test/java/org/hibernate/test/id/idClass/MyEntityId.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.id.idclass; +package org.hibernate.test.id.idClass; import java.io.Serializable; import java.util.Objects;