From d3a7e989f336e3ce14b61e394facbf4ca391f33d Mon Sep 17 00:00:00 2001 From: Steve Ebersole Date: Mon, 16 Apr 2012 13:55:02 -0500 Subject: [PATCH] HHH-7240 - Develop identifier handling in new metamodel --- .../engine/spi/SyntheticAttributeHelper.java | 31 ++++ .../hibernate/id/EntityIdentifierNature.java | 75 ++++++++++ .../hibernate/metamodel/internal/Binder.java | 63 +++++--- .../metamodel/internal/MetadataImpl.java | 7 +- .../attribute/SimpleIdentifierSourceImpl.java | 11 +- .../source/annotations/entity/IdType.java | 6 +- .../entity/RootEntitySourceImpl.java | 27 ++-- .../source/hbm/RootEntitySourceImpl.java | 29 +++- .../binding/CompositeAttributeBinding.java | 54 ++++++- .../metamodel/spi/binding/EntityBinding.java | 22 ++- .../spi/binding/EntityIdentifier.java | 106 +++++++++----- .../spi/binding/HierarchyDetails.java | 1 - .../domain/AbstractAttributeContainer.java | 135 ++++++++++-------- .../metamodel/spi/domain/Attribute.java | 9 ++ .../spi/domain/AttributeContainer.java | 35 ++--- .../AggregatedCompositeIdentifierSource.java | 2 +- .../spi/source/IdentifierSource.java | 27 +--- ...onAggregatedCompositeIdentifierSource.java | 2 +- .../spi/source/SimpleIdentifierSource.java | 2 +- .../property/PropertyAccessorFactory.java | 28 ++-- .../org/hibernate/tuple/PropertyFactory.java | 2 +- .../tuple/entity/AbstractEntityTuplizer.java | 6 +- .../tuple/entity/EntityMetamodel.java | 4 +- .../tuple/entity/PojoEntityTuplizer.java | 5 +- .../internal/source/AssertSourcesTest.java | 3 +- .../entity/InheritanceBindingTest.java | 8 +- .../binding/AbstractBasicBindingTests.java | 6 +- .../binding/BasicCollectionBindingTests.java | 4 +- .../spi/binding/SimpleValueBindingTests.java | 2 +- 29 files changed, 498 insertions(+), 214 deletions(-) create mode 100644 hibernate-core/src/main/java/org/hibernate/engine/spi/SyntheticAttributeHelper.java create mode 100644 hibernate-core/src/main/java/org/hibernate/id/EntityIdentifierNature.java diff --git a/hibernate-core/src/main/java/org/hibernate/engine/spi/SyntheticAttributeHelper.java b/hibernate-core/src/main/java/org/hibernate/engine/spi/SyntheticAttributeHelper.java new file mode 100644 index 0000000000..f58e0df575 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/engine/spi/SyntheticAttributeHelper.java @@ -0,0 +1,31 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, 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.spi; + +/** + * @author Steve Ebersole + */ +public class SyntheticAttributeHelper { + public static final String SYNTHETIC_COMPOSITE_ID_ATTRIBUTE_NAME = "_identifierMapper"; +} diff --git a/hibernate-core/src/main/java/org/hibernate/id/EntityIdentifierNature.java b/hibernate-core/src/main/java/org/hibernate/id/EntityIdentifierNature.java new file mode 100644 index 0000000000..f57288ddcd --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/id/EntityIdentifierNature.java @@ -0,0 +1,75 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, 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.id; + +/** + * Describes the nature of the entity-defined identifier. + * + * @author Steve Ebersole +*/ +public enum EntityIdentifierNature { + /** + * A simple identifier. Resolved as a basic type and mapped to a singular, basic attribute. Equivalent of: + */ + SIMPLE, + + /** + * What Hibernate used to term an "embedded composite identifier", which is not to be confused with the JPA + * term embedded. Resolved as a tuple of basic type values and mapped over multiple singular attributes. + * Specifically a composite identifier where there is no single attribute representing the composite value. + * Equivalent of: + * + * NOTE : May or may not have a related "lookup identifier class" as indicated by a {@code @IdClass} annotation. + * + * @see javax.persistence.IdClass + */ + COMPOSITE, + + /** + * Composite identifier mapped to a single entity attribute by means of an actual component class used to + * aggregate the tuple values. + * Equivalent of: + * + * @see javax.persistence.EmbeddedId + */ + AGGREGATED_COMPOSITE +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/Binder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/Binder.java index 22c384dfe7..f480203838 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/Binder.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/Binder.java @@ -31,6 +31,8 @@ import java.util.List; import java.util.Map; import java.util.Properties; +import org.jboss.logging.Logger; + import org.hibernate.AssertionFailure; import org.hibernate.EntityMode; import org.hibernate.TruthValue; @@ -39,6 +41,7 @@ import org.hibernate.cfg.NamingStrategy; import org.hibernate.cfg.NotYetImplementedException; import org.hibernate.cfg.ObjectNameNormalizer; import org.hibernate.engine.FetchTiming; +import org.hibernate.id.EntityIdentifierNature; import org.hibernate.id.IdentifierGenerator; import org.hibernate.id.PersistentIdentifierGenerator; import org.hibernate.id.factory.IdentifierGeneratorFactory; @@ -106,7 +109,6 @@ import org.hibernate.metamodel.spi.source.EntitySource; import org.hibernate.metamodel.spi.source.ExplicitHibernateTypeSource; import org.hibernate.metamodel.spi.source.ForeignKeyContributingSource; import org.hibernate.metamodel.spi.source.IdentifierSource; -import org.hibernate.metamodel.spi.source.IdentifierSource.Nature; import org.hibernate.metamodel.spi.source.InLineViewSource; import org.hibernate.metamodel.spi.source.IndexedPluralAttributeSource; import org.hibernate.metamodel.spi.source.LocalBindingContext; @@ -143,7 +145,8 @@ import org.hibernate.tuple.entity.EntityTuplizer; import org.hibernate.type.ComponentType; import org.hibernate.type.EntityType; import org.hibernate.type.Type; -import org.jboss.logging.Logger; + +import static org.hibernate.engine.spi.SyntheticAttributeHelper.SYNTHETIC_COMPOSITE_ID_ATTRIBUTE_NAME; /** * The common binder shared between annotations and {@code hbm.xml} processing. @@ -438,7 +441,8 @@ public class Binder { if ( !attribute.isTypeResolved() ) { attribute.resolveType( referencedEntityBinding.getEntity() ); } - final boolean isRefToPk = referencedEntityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding() == referencedAttributeBinding; + final boolean isRefToPk = referencedEntityBinding.getHierarchyDetails().getEntityIdentifier() + .isIdentifierAttributeBinding( referencedAttributeBinding ); final String uniqueKeyAttributeName = isRefToPk ? null : referencedAttributeBinding.getAttribute().getName(); Type resolvedType = metadata.getTypeResolver().getTypeFactory().manyToOne( attributeBinding.getReferencedEntityName(), @@ -999,7 +1003,7 @@ public class Binder { } private void bindIdentifier( final EntityBinding rootEntityBinding, final IdentifierSource identifierSource ) { - final Nature nature = identifierSource.getNature(); + final EntityIdentifierNature nature = identifierSource.getNature(); switch ( nature ) { case SIMPLE: { bindSimpleIdentifier( rootEntityBinding, ( SimpleIdentifierSource ) identifierSource ); @@ -1035,7 +1039,7 @@ public class Binder { // determine the unsaved value mapping final String unsavedValue = interpretIdentifierUnsavedValue( identifierSource, generator ); - rootEntityBinding.getHierarchyDetails().getEntityIdentifier().bindAsSingleAttributeIdentifier( + rootEntityBinding.getHierarchyDetails().getEntityIdentifier().prepareAsSimpleIdentifier( idAttributeBinding, generator, unsavedValue @@ -1060,7 +1064,7 @@ public class Binder { // determine the unsaved value mapping final String unsavedValue = interpretIdentifierUnsavedValue( identifierSource, generator ); - rootEntityBinding.getHierarchyDetails().getEntityIdentifier().bindAsSingleAttributeIdentifier( + rootEntityBinding.getHierarchyDetails().getEntityIdentifier().prepareAsAggregatedCompositeIdentifier( idAttributeBinding, generator, unsavedValue @@ -1070,7 +1074,7 @@ public class Binder { private void bindNonAggregatedCompositeIdentifier( EntityBinding rootEntityBinding, NonAggregatedCompositeIdentifierSource identifierSource) { - // locate the attribute bindings + // locate the attribute bindings for the real attributes List idAttributeBindings = new ArrayList(); for ( SingularAttributeSource attributeSource : identifierSource.getAttributeSourcesMakingUpIdentifier() ) { idAttributeBindings.add( @@ -1078,8 +1082,21 @@ public class Binder { ); } - rootEntityBinding.getHierarchyDetails().getEntityIdentifier().bindAsMultipleAttributeIdentifier( + // Create the synthetic attribute + SingularAttribute syntheticAttribute = rootEntityBinding.getEntity().createSyntheticCompositeAttribute( + SYNTHETIC_COMPOSITE_ID_ATTRIBUTE_NAME, + rootEntityBinding.getEntity() + ); + + // Create the synthetic attribute binding. + final CompositeAttributeBinding syntheticAttributeBinding = rootEntityBinding.makeVirtualComponentAttributeBinding( + syntheticAttribute, idAttributeBindings, + createMetaAttributeContext( rootEntityBinding, identifierSource.getMetaAttributeSources() ) + ); + + rootEntityBinding.getHierarchyDetails().getEntityIdentifier().prepareAsNonAggregatedCompositeIdentifier( + syntheticAttributeBinding, identifierSource.getLookupIdClass() ); } @@ -1150,13 +1167,8 @@ public class Binder { AttributeBindingContainer sourceAttributeBindingContainer, EntityBinding referencedEntityBinding, ForeignKey foreignKey) { - // todo : currently only works for simple and embedded identifiers... if ( resolutionDelegate == null ) { - // this needs to change when I integrate HHH-7240 in - if ( referencedEntityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding() == null ) { - throw new NotYetImplementedException( "reference to non-aggregated composite identifier not yet supported" ); - } - return referencedEntityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding(); + return referencedEntityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(); } final String explicitName = resolutionDelegate.getReferencedAttributeName(); @@ -1480,9 +1492,19 @@ public class Binder { final AttributeBindingContainer attributeBindingContainer, final AttributeSource attributeSource ) { return createMetaAttributeContext( - attributeSource.metaAttributes(), + attributeBindingContainer, + attributeSource.metaAttributes() + ); + } + + private MetaAttributeContext createMetaAttributeContext( + final AttributeBindingContainer attributeBindingContainer, + final Iterable metaAttributeSources ) { + return createMetaAttributeContext( + metaAttributeSources, false, - attributeBindingContainer.getMetaAttributeContext() ); + attributeBindingContainer.getMetaAttributeContext() + ); } private MetaAttributeContext createMetaAttributeContext( @@ -1553,7 +1575,7 @@ public class Binder { final AttributeBindingContainer attributeBindingContainer, final SingularAttributeSource attributeSource ) { return attributeSource.isVirtualAttribute() - ? attributeBindingContainer.getAttributeContainer().createVirtualSingularAttribute( attributeSource.getName() ) + ? attributeBindingContainer.getAttributeContainer().createSyntheticSingularAttribute( attributeSource.getName() ) : attributeBindingContainer.getAttributeContainer().createSingularAttribute( attributeSource.getName() ); } @@ -1666,13 +1688,8 @@ public class Binder { final ForeignKeyContributingSource.JoinColumnResolutionDelegate resolutionDelegate = attributeSource.getKeySource().getForeignKeyTargetColumnResolutionDelegate(); - // todo : currently only works for simple and embedded identifiers... if ( resolutionDelegate == null ) { - // this needs to change when I integrate HHH-7240 in - if ( entityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding() == null ) { - throw new NotYetImplementedException( "reference to non-aggregated composite identifier not yet supported" ); - } - return entityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding(); + return entityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(); } final String explicitName = resolutionDelegate.getReferencedAttributeName(); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataImpl.java index 28326e0bc9..95641d0523 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataImpl.java @@ -539,10 +539,7 @@ public class MetadataImpl implements MetadataImplementor, Serializable { if ( entityBinding == null ) { throw new MappingException( "Entity binding not known: " + entityName ); } - return entityBinding - .getHierarchyDetails() - .getEntityIdentifier() - .getValueBinding() + return entityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding() .getHibernateTypeDescriptor() .getResolvedTypeMapping(); } @@ -553,7 +550,7 @@ public class MetadataImpl implements MetadataImplementor, Serializable { if ( entityBinding == null ) { throw new MappingException( "Entity binding not known: " + entityName ); } - AttributeBinding idBinding = entityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding(); + AttributeBinding idBinding = entityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(); return idBinding == null ? null : idBinding.getAttribute().getName(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/SimpleIdentifierSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/SimpleIdentifierSourceImpl.java index 2841a854f7..a242606a67 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/SimpleIdentifierSourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/SimpleIdentifierSourceImpl.java @@ -26,7 +26,9 @@ package org.hibernate.metamodel.internal.source.annotations.attribute; import java.util.Map; import org.hibernate.AssertionFailure; +import org.hibernate.id.EntityIdentifierNature; import org.hibernate.metamodel.spi.binding.IdGenerator; +import org.hibernate.metamodel.spi.source.MetaAttributeSource; import org.hibernate.metamodel.spi.source.SimpleIdentifierSource; import org.hibernate.metamodel.spi.source.SingularAttributeSource; @@ -51,8 +53,8 @@ public class SimpleIdentifierSourceImpl implements SimpleIdentifierSource { } @Override - public Nature getNature() { - return Nature.SIMPLE; + public EntityIdentifierNature getNature() { + return EntityIdentifierNature.SIMPLE; } @Override @@ -69,6 +71,11 @@ public class SimpleIdentifierSourceImpl implements SimpleIdentifierSource { public String getUnsavedValue() { return null; } + + @Override + public Iterable getMetaAttributeSources() { + return null; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/IdType.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/IdType.java index bb0116c18f..9d54cbb16c 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/IdType.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/IdType.java @@ -31,19 +31,19 @@ package org.hibernate.metamodel.internal.source.annotations.entity; public enum IdType { /** * single @Id annotation. Corresponds to - * {@link org.hibernate.metamodel.spi.source.IdentifierSource.Nature#SIMPLE} + * {@link org.hibernate.id.EntityIdentifierNature#SIMPLE} */ SIMPLE, /** * multiple @Id annotations. Corresponds to - * {@link org.hibernate.metamodel.spi.source.IdentifierSource.Nature#COMPOSITE} + * {@link org.hibernate.id.EntityIdentifierNature#COMPOSITE} */ COMPOSED, /** * Indicates encountered {@code @EmbeddedId} annotation. Corresponds to - * {@link org.hibernate.metamodel.spi.source.IdentifierSource.Nature#AGGREGATED_COMPOSITE} + * {@link org.hibernate.id.EntityIdentifierNature#AGGREGATED_COMPOSITE} */ // EMBEDDED, diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/RootEntitySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/RootEntitySourceImpl.java index aa17da5a45..17af7a1973 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/RootEntitySourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/RootEntitySourceImpl.java @@ -32,8 +32,8 @@ import org.jboss.jandex.AnnotationInstance; import org.hibernate.AssertionFailure; import org.hibernate.EntityMode; -import org.hibernate.cfg.NotYetImplementedException; import org.hibernate.engine.OptimisticLockStyle; +import org.hibernate.id.EntityIdentifierNature; import org.hibernate.metamodel.internal.source.annotations.attribute.AttributeOverride; import org.hibernate.metamodel.internal.source.annotations.attribute.BasicAttribute; import org.hibernate.metamodel.internal.source.annotations.attribute.DiscriminatorSourceImpl; @@ -48,6 +48,7 @@ import org.hibernate.metamodel.spi.source.AggregatedCompositeIdentifierSource; import org.hibernate.metamodel.spi.source.ComponentAttributeSource; import org.hibernate.metamodel.spi.source.DiscriminatorSource; import org.hibernate.metamodel.spi.source.IdentifierSource; +import org.hibernate.metamodel.spi.source.MetaAttributeSource; import org.hibernate.metamodel.spi.source.NonAggregatedCompositeIdentifierSource; import org.hibernate.metamodel.spi.source.RootEntitySource; import org.hibernate.metamodel.spi.source.SingularAttributeSource; @@ -161,7 +162,9 @@ public class RootEntitySourceImpl extends EntitySourceImpl implements RootEntity ); } - final EmbeddableClass embeddableClass = rootEntitySource.getEntityClass().getEmbeddedClasses().get( idAttribute.getName() ); + final EmbeddableClass embeddableClass = rootEntitySource.getEntityClass().getEmbeddedClasses().get( + idAttribute.getName() + ); if ( embeddableClass == null ) { throw rootEntitySource.getLocalBindingContext().makeMappingException( "Could not locate embedded identifier class metadata" @@ -191,14 +194,19 @@ public class RootEntitySourceImpl extends EntitySourceImpl implements RootEntity } @Override - public Nature getNature() { - return Nature.AGGREGATED_COMPOSITE; + public EntityIdentifierNature getNature() { + return EntityIdentifierNature.AGGREGATED_COMPOSITE; } @Override public String getUnsavedValue() { return null; } + + @Override + public Iterable getMetaAttributeSources() { + return null; //To change body of implemented methods use File | Settings | File Templates. + } } private class NonAggregatedCompositeIdentifierSourceImpl implements NonAggregatedCompositeIdentifierSource { @@ -245,18 +253,21 @@ public class RootEntitySourceImpl extends EntitySourceImpl implements RootEntity } @Override - public Nature getNature() { - return Nature.COMPOSITE; + public EntityIdentifierNature getNature() { + return EntityIdentifierNature.COMPOSITE; } @Override public String getUnsavedValue() { return null; } + + @Override + public Iterable getMetaAttributeSources() { + return null; //To change body of implemented methods use File | Settings | File Templates. + } } - - } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/RootEntitySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/RootEntitySourceImpl.java index c9afa16ea7..a1da55f141 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/RootEntitySourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/RootEntitySourceImpl.java @@ -31,6 +31,7 @@ import org.hibernate.EntityMode; import org.hibernate.HibernateException; import org.hibernate.TruthValue; import org.hibernate.engine.OptimisticLockStyle; +import org.hibernate.id.EntityIdentifierNature; import org.hibernate.internal.jaxb.mapping.hbm.JaxbAnyElement; import org.hibernate.internal.jaxb.mapping.hbm.JaxbComponentElement; import org.hibernate.internal.jaxb.mapping.hbm.JaxbHibernateMapping; @@ -48,6 +49,7 @@ import org.hibernate.metamodel.spi.source.ComponentAttributeSource; import org.hibernate.metamodel.spi.source.DiscriminatorSource; import org.hibernate.metamodel.spi.source.IdentifierSource; import org.hibernate.metamodel.spi.source.MappingException; +import org.hibernate.metamodel.spi.source.MetaAttributeSource; import org.hibernate.metamodel.spi.source.NonAggregatedCompositeIdentifierSource; import org.hibernate.metamodel.spi.source.RelationalValueSource; import org.hibernate.metamodel.spi.source.RootEntitySource; @@ -282,14 +284,19 @@ public class RootEntitySourceImpl extends AbstractEntitySourceImpl implements Ro } @Override - public Nature getNature() { - return Nature.SIMPLE; + public EntityIdentifierNature getNature() { + return EntityIdentifierNature.SIMPLE; } @Override public String getUnsavedValue() { return entityElement().getId().getUnsavedValue(); } + + @Override + public Iterable getMetaAttributeSources() { + return Helper.buildMetaAttributeSources( entityElement().getId().getMeta() ); + } } private class AggregatedCompositeIdentifierSourceImpl implements AggregatedCompositeIdentifierSource { @@ -327,14 +334,19 @@ public class RootEntitySourceImpl extends AbstractEntitySourceImpl implements Ro } @Override - public Nature getNature() { - return Nature.AGGREGATED_COMPOSITE; + public EntityIdentifierNature getNature() { + return EntityIdentifierNature.AGGREGATED_COMPOSITE; } @Override public String getUnsavedValue() { return entityElement().getCompositeId().getUnsavedValue(); } + + @Override + public Iterable getMetaAttributeSources() { + return Helper.buildMetaAttributeSources( entityElement().getId().getMeta() ); + } } private class CompositeIdentifierComponentAttributeSourceImpl extends AbstractComponentAttributeSourceImpl { @@ -486,13 +498,18 @@ public class RootEntitySourceImpl extends AbstractEntitySourceImpl implements Ro } @Override - public Nature getNature() { - return Nature.COMPOSITE; + public EntityIdentifierNature getNature() { + return EntityIdentifierNature.COMPOSITE; } @Override public String getUnsavedValue() { return entityElement().getCompositeId().getUnsavedValue(); } + + @Override + public Iterable getMetaAttributeSources() { + return Helper.buildMetaAttributeSources( entityElement().getId().getMeta() ); + } } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/CompositeAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/CompositeAttributeBinding.java index 62cfbb046a..53b735a040 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/CompositeAttributeBinding.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/CompositeAttributeBinding.java @@ -24,6 +24,7 @@ package org.hibernate.metamodel.spi.binding; import java.util.ArrayList; +import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; @@ -48,7 +49,7 @@ public class CompositeAttributeBinding implements SingularNonAssociationAttributeBinding, AttributeBindingContainer { private final String path; private final SingularAttribute parentReference; - private Map attributeBindingMap = new HashMap(); + private Map attributeBindingMap; public CompositeAttributeBinding( AttributeBindingContainer container, @@ -58,6 +59,45 @@ public class CompositeAttributeBinding boolean lazy, MetaAttributeContext metaAttributeContext, SingularAttribute parentReference) { + this( + container, + attribute, + propertyAccessorName, + includedInOptimisticLocking, + lazy, + metaAttributeContext, + parentReference, + null + ); + } + + public CompositeAttributeBinding( + AttributeBindingContainer container, + SingularAttribute attribute, + String propertyAccessorName, + MetaAttributeContext metaAttributeContext, + List subAttributeBindings) { + this( + container, + attribute, + propertyAccessorName, + false, + false, + metaAttributeContext, + null, + subAttributeBindings + ); + } + + private CompositeAttributeBinding( + AttributeBindingContainer container, + SingularAttribute attribute, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + MetaAttributeContext metaAttributeContext, + SingularAttribute parentReference, + List subAttributeBindings) { super( container, attribute, @@ -66,8 +106,20 @@ public class CompositeAttributeBinding lazy, metaAttributeContext ); + this.parentReference = parentReference; this.path = container.getPathBase() + '.' + attribute.getName(); + + if ( subAttributeBindings == null ) { + attributeBindingMap = new HashMap(); + } + else { + HashMap map = new HashMap(); + for ( SingularAttributeBinding attributeBinding : subAttributeBindings ) { + attributeBindingMap.put( attributeBinding.getAttribute().getName(), attributeBinding ); + } + attributeBindingMap = Collections.unmodifiableMap( map ); + } } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityBinding.java index 2bed305fa7..3392c8f01b 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityBinding.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityBinding.java @@ -46,6 +46,7 @@ import org.hibernate.metamodel.spi.relational.TableSpecification; import org.hibernate.metamodel.spi.source.JpaCallbackSource; import org.hibernate.metamodel.spi.source.MetaAttributeContext; import org.hibernate.persister.entity.EntityPersister; +import org.hibernate.property.PropertyAccessorFactory; import org.hibernate.tuple.entity.EntityTuplizer; /** @@ -524,6 +525,26 @@ public class EntityBinding implements AttributeBindingContainer { return binding; } + public CompositeAttributeBinding makeVirtualComponentAttributeBinding( + SingularAttribute syntheticAttribute, + List subAttributeBindings, + MetaAttributeContext metaAttributeContext) { + if ( ! syntheticAttribute.isSynthetic() ) { + throw new AssertionFailure( + "Illegal attempt to create synthetic attribute binding from non-synthetic attribute reference" + ); + } + final CompositeAttributeBinding binding = new CompositeAttributeBinding( + this, + syntheticAttribute, + PropertyAccessorFactory.EMBEDDED_ACCESSOR_NAME, + metaAttributeContext, + subAttributeBindings + ); + registerAttributeBinding( syntheticAttribute.getName(), binding ); + return binding; + } + @Override public ManyToOneAttributeBinding makeManyToOneAttributeBinding( SingularAttribute attribute, @@ -714,5 +735,4 @@ public class EntityBinding implements AttributeBindingContainer { public Iterable getJpaCallbackClasses() { return jpaCallbackClasses; } - } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityIdentifier.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityIdentifier.java index ac5aa8f00c..1341064b54 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityIdentifier.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityIdentifier.java @@ -23,15 +23,18 @@ */ package org.hibernate.metamodel.spi.binding; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; import java.util.Properties; +import org.hibernate.AssertionFailure; +import org.hibernate.id.EntityIdentifierNature; import org.hibernate.id.IdentifierGenerator; import org.hibernate.id.factory.IdentifierGeneratorFactory; import org.hibernate.metamodel.spi.relational.Column; +import static org.hibernate.id.EntityIdentifierNature.AGGREGATED_COMPOSITE; +import static org.hibernate.id.EntityIdentifierNature.COMPOSITE; +import static org.hibernate.id.EntityIdentifierNature.SIMPLE; + /** * Hold information about the entity identifier. At a high-level, can be one of 2-types:
    *
  • single-attribute identifier - this includes both simple identifiers and aggregated composite identifiers
  • @@ -43,8 +46,9 @@ import org.hibernate.metamodel.spi.relational.Column; */ public class EntityIdentifier { private final EntityBinding entityBinding; + private EntityIdentifierNature nature; - private List identifierAttributeBindings = new ArrayList(); + private SingularNonAssociationAttributeBinding identifierAttributeBinding; private IdGenerator idGenerator; private String unsavedValue; @@ -63,12 +67,29 @@ public class EntityIdentifier { this.entityBinding = entityBinding; } - public void bindAsSingleAttributeIdentifier( + public void prepareAsSimpleIdentifier( + SingularNonAssociationAttributeBinding attributeBinding, + IdGenerator idGenerator, + String unsavedValue) { + prepareAsSingleAttributeIdentifier( SIMPLE, attributeBinding, idGenerator, unsavedValue ); + } + + public void prepareAsAggregatedCompositeIdentifier( + SingularNonAssociationAttributeBinding attributeBinding, + IdGenerator idGenerator, + String unsavedValue) { + prepareAsSingleAttributeIdentifier( AGGREGATED_COMPOSITE, attributeBinding, idGenerator, unsavedValue ); + } + + protected void prepareAsSingleAttributeIdentifier( + EntityIdentifierNature nature, SingularNonAssociationAttributeBinding attributeBinding, IdGenerator idGenerator, String unsavedValue) { ensureNotBound(); - identifierAttributeBindings.add( attributeBinding ); + + this.nature = nature; + this.identifierAttributeBinding = attributeBinding; this.idGenerator = idGenerator; this.unsavedValue = unsavedValue; this.columnCount = attributeBinding.getRelationalValueBindings().size(); @@ -79,52 +100,57 @@ public class EntityIdentifier { } } - private void ensureNotBound() { - if ( ! identifierAttributeBindings.isEmpty() ) { - throw new IllegalStateException( "Entity identifier was already bound" ); - } - } - - public void bindAsMultipleAttributeIdentifier( - List nonAggregatedCompositeAttributeBindings, + public void prepareAsNonAggregatedCompositeIdentifier( + CompositeAttributeBinding syntheticCompositeAttributeBinding, Class idClassClass) { ensureNotBound(); - for ( SingularAttributeBinding attributeBinding : nonAggregatedCompositeAttributeBindings ) { - identifierAttributeBindings.add( attributeBinding ); - columnCount += attributeBinding.getRelationalValueBindings().size(); + + this.nature = COMPOSITE; + this.identifierAttributeBinding = syntheticCompositeAttributeBinding; + this.idClassClass = idClassClass; + + for ( AttributeBinding attributeBinding : syntheticCompositeAttributeBinding.attributeBindings() ) { + if ( ! attributeBinding.getAttribute().isSingular() ) { + throw new AssertionFailure( "Expecting all singular attribute bindings as part of composite identifier" ); + } + final SingularAttributeBinding singularAttributeBinding = (SingularAttributeBinding) attributeBinding; + columnCount += singularAttributeBinding.getRelationalValueBindings().size(); // Configure primary key in relational model - for ( final RelationalValueBinding valueBinding : attributeBinding.getRelationalValueBindings() ) { + for ( final RelationalValueBinding valueBinding : singularAttributeBinding.getRelationalValueBindings() ) { entityBinding.getPrimaryTable().getPrimaryKey().addColumn( (Column) valueBinding.getValue() ); } } - this.idClassClass = idClassClass; + } + + public EntityIdentifierNature getNature() { + return nature; } public boolean isSingleAttribute() { ensureBound(); - return identifierAttributeBindings.size() == 1; + return getNature() != COMPOSITE; } - public List getIdentifierAttributeBindings() { - return Collections.unmodifiableList( identifierAttributeBindings ); + public SingularNonAssociationAttributeBinding getAttributeBinding() { + ensureBound(); + return identifierAttributeBinding; } public boolean isIdentifierAttributeBinding(AttributeBinding attributeBinding) { - for ( SingularAttributeBinding identifierAttributeBinding : identifierAttributeBindings ) { - if ( identifierAttributeBinding.equals( attributeBinding ) ) { - return true; + ensureBound(); + if ( getNature() == COMPOSITE ) { + for ( AttributeBinding identifierAttributeBinding + : ( (CompositeAttributeBinding) this.identifierAttributeBinding ).attributeBindings() ) { + if ( identifierAttributeBinding.equals( attributeBinding ) ) { + return true; + } } + return false; } - return false; - } - - protected SingularNonAssociationAttributeBinding getSingleIdentifierAttributeBinding() { - if ( ! isSingleAttribute() ) { - throw new IllegalStateException( "Entity identifier is made up of multiple attributes" ); + else { + return identifierAttributeBinding.equals( attributeBinding ); } - - return (SingularNonAssociationAttributeBinding) identifierAttributeBindings.get( 0 ); } public String getUnsavedValue() { @@ -150,7 +176,7 @@ public class EntityIdentifier { ensureBound(); if ( identifierGenerator == null ) { if ( isSingleAttribute() && idGenerator != null ) { - identifierGenerator = getSingleIdentifierAttributeBinding().createIdentifierGenerator( + identifierGenerator = identifierAttributeBinding.createIdentifierGenerator( idGenerator, factory, properties @@ -166,11 +192,21 @@ public class EntityIdentifier { } protected void ensureBound() { - if ( identifierAttributeBindings.isEmpty() ) { + if ( ! isBound() ) { throw new IllegalStateException( "Entity identifier was not yet bound" ); } } + protected void ensureNotBound() { + if ( isBound() ) { + throw new IllegalStateException( "Entity identifier was already bound" ); + } + } + + protected boolean isBound() { + return nature != null; + } + public int getColumnCount() { ensureBound(); return columnCount; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/HierarchyDetails.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/HierarchyDetails.java index 2ea970788c..143f722d45 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/HierarchyDetails.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/HierarchyDetails.java @@ -35,7 +35,6 @@ public class HierarchyDetails { private final EntityMode entityMode; private final EntityIdentifier entityIdentifier; - private EntityDiscriminator entityDiscriminator; private OptimisticLockStyle optimisticLockStyle; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/AbstractAttributeContainer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/AbstractAttributeContainer.java index 3d2f3e3bbc..745693e9eb 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/AbstractAttributeContainer.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/AbstractAttributeContainer.java @@ -28,7 +28,6 @@ import java.util.HashMap; import java.util.LinkedHashSet; import java.util.Set; -import org.hibernate.cfg.NotYetImplementedException; import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.Value; @@ -44,6 +43,7 @@ public abstract class AbstractAttributeContainer implements AttributeContainer, private final String className; private final Value> classReference; private final Hierarchical superType; + private LinkedHashSet attributeSet = new LinkedHashSet(); private HashMap attributeMap = new HashMap(); @@ -99,84 +99,36 @@ public abstract class AbstractAttributeContainer implements AttributeContainer, return (SingularAttribute) locateAttribute( name ); } - @Override - public SingularAttribute createSingularAttribute(String name) { - SingularAttribute attribute = new SingularAttributeImpl( name, this ); - addAttribute( attribute ); - return attribute; - } - - @Override - public SingularAttribute createVirtualSingularAttribute(String name) { - throw new NotYetImplementedException(); - } - @Override public SingularAttribute locateCompositeAttribute(String name) { return (SingularAttributeImpl) locateAttribute( name ); } - @Override - public SingularAttribute createCompositeAttribute(String name, Composite composite) { - SingularAttributeImpl attribute = new SingularAttributeImpl( name, this ); - attribute.resolveType( composite ); - addAttribute( attribute ); - return attribute; - } - @Override public PluralAttribute locatePluralAttribute(String name) { return (PluralAttribute) locateAttribute( name ); } - protected PluralAttribute createPluralAttribute(String name, PluralAttributeNature nature) { - PluralAttribute attribute = nature.isIndexed() - ? new IndexedPluralAttributeImpl( name, nature, this ) - : new PluralAttributeImpl( name, nature, this ); - addAttribute( attribute ); - return attribute; - } - @Override public PluralAttribute locateBag(String name) { return locatePluralAttribute( name ); } - @Override - public PluralAttribute createBag(String name) { - return createPluralAttribute( name, PluralAttributeNature.BAG ); - } - @Override public PluralAttribute locateSet(String name) { return locatePluralAttribute( name ); } - @Override - public PluralAttribute createSet(String name) { - return createPluralAttribute( name, PluralAttributeNature.SET ); - } - @Override public IndexedPluralAttribute locateList(String name) { return (IndexedPluralAttribute) locatePluralAttribute( name ); } - @Override - public IndexedPluralAttribute createList(String name) { - return (IndexedPluralAttribute) createPluralAttribute( name, PluralAttributeNature.LIST ); - } - @Override public IndexedPluralAttribute locateMap(String name) { return (IndexedPluralAttribute) locatePluralAttribute( name ); } - @Override - public IndexedPluralAttribute createMap(String name) { - return (IndexedPluralAttribute) createPluralAttribute( name, PluralAttributeNature.MAP ); - } - @Override public String toString() { final StringBuilder sb = new StringBuilder(); @@ -187,8 +139,66 @@ public abstract class AbstractAttributeContainer implements AttributeContainer, return sb.toString(); } + + @Override + public SingularAttribute createSyntheticSingularAttribute(String name) { + SingularAttribute attribute = new SingularAttributeImpl( this, name, true ); + addAttribute( attribute ); + return attribute; + } + + @Override + public SingularAttribute createSyntheticCompositeAttribute(String name, Hierarchical type) { + SingularAttributeImpl attribute = new SingularAttributeImpl( this, name, true ); + attribute.resolveType( type ); + addAttribute( attribute ); + return attribute; + } + + @Override + public SingularAttribute createSingularAttribute(String name) { + SingularAttribute attribute = new SingularAttributeImpl( this, name, false ); + addAttribute( attribute ); + return attribute; + } + + @Override + public SingularAttribute createCompositeAttribute(String name, Composite composite) { + SingularAttributeImpl attribute = new SingularAttributeImpl( this, name, false ); + attribute.resolveType( composite ); + addAttribute( attribute ); + return attribute; + } + + @Override + public PluralAttribute createBag(String name) { + return createPluralAttribute( name, PluralAttributeNature.BAG ); + } + + protected PluralAttribute createPluralAttribute(String name, PluralAttributeNature nature) { + PluralAttribute attribute = nature.isIndexed() + ? new IndexedPluralAttributeImpl( this, name, nature ) + : new PluralAttributeImpl( this, name, nature ); + addAttribute( attribute ); + return attribute; + } + + @Override + public PluralAttribute createSet(String name) { + return createPluralAttribute( name, PluralAttributeNature.SET ); + } + + @Override + public IndexedPluralAttribute createList(String name) { + return (IndexedPluralAttribute) createPluralAttribute( name, PluralAttributeNature.LIST ); + } + + @Override + public IndexedPluralAttribute createMap(String name) { + return (IndexedPluralAttribute) createPluralAttribute( name, PluralAttributeNature.MAP ); + } + protected void addAttribute(Attribute attribute) { - // todo : how to best "secure" this? if ( attributeMap.put( attribute.getName(), attribute ) != null ) { throw new IllegalArgumentException( "Attribute with name [" + attribute.getName() + "] already registered" ); } @@ -200,11 +210,13 @@ public abstract class AbstractAttributeContainer implements AttributeContainer, public static class SingularAttributeImpl implements SingularAttribute { private final AttributeContainer attributeContainer; private final String name; + private final boolean synthetic; private Type type; - public SingularAttributeImpl(String name, AttributeContainer attributeContainer) { - this.name = name; + public SingularAttributeImpl(AttributeContainer attributeContainer, String name, boolean synthetic) { this.attributeContainer = attributeContainer; + this.name = name; + this.synthetic = synthetic; } public boolean isTypeResolved() { @@ -237,6 +249,11 @@ public abstract class AbstractAttributeContainer implements AttributeContainer, public boolean isSingular() { return true; } + + @Override + public boolean isSynthetic() { + return synthetic; + } } public static class PluralAttributeImpl implements PluralAttribute { @@ -246,10 +263,10 @@ public abstract class AbstractAttributeContainer implements AttributeContainer, private Type elementType; - public PluralAttributeImpl(String name, PluralAttributeNature nature, AttributeContainer attributeContainer) { + public PluralAttributeImpl(AbstractAttributeContainer attributeContainer, String name, PluralAttributeNature nature) { + this.attributeContainer = attributeContainer; this.name = name; this.nature = nature; - this.attributeContainer = attributeContainer; } @Override @@ -262,6 +279,12 @@ public abstract class AbstractAttributeContainer implements AttributeContainer, return false; } + @Override + public boolean isSynthetic() { + // don't think there are ever any synthetic plural attributes created... + return false; + } + @Override public PluralAttributeNature getNature() { return nature; @@ -291,8 +314,8 @@ public abstract class AbstractAttributeContainer implements AttributeContainer, public static class IndexedPluralAttributeImpl extends PluralAttributeImpl implements IndexedPluralAttribute { private Type indexType; - public IndexedPluralAttributeImpl(String name, PluralAttributeNature nature, AttributeContainer attributeContainer) { - super( name, nature, attributeContainer ); + public IndexedPluralAttributeImpl(AbstractAttributeContainer attributeContainer, String name, PluralAttributeNature nature) { + super( attributeContainer, name, nature ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/Attribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/Attribute.java index d5b1b2003a..8f6f9bf354 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/Attribute.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/Attribute.java @@ -52,4 +52,13 @@ public interface Attribute { * @return True if attribute is singular; false if plural. */ public boolean isSingular(); + + /** + * Synthetic attributes do not really exist in the users domain classes. Hibernate sometimes generates these + * synthetic attributes for various reasons. Some parts of the code base use the phrase "virtual" as well. + * + * @return {@code true} indicates this attribute is synthetic; {@code false} indicates it is non-synthetic + * (an actual attribute). + */ + public boolean isSynthetic(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/AttributeContainer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/AttributeContainer.java index aad5f2d427..763b3f0f86 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/AttributeContainer.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/domain/AttributeContainer.java @@ -42,6 +42,13 @@ public interface AttributeContainer extends Type { */ public String getRoleBaseName(); + /** + * Retrieve the attributes contained in this container. + * + * @return The contained attributes + */ + public Set attributes(); + /** * Retrieve an attribute by name. * @@ -50,33 +57,21 @@ public interface AttributeContainer extends Type { * @return The attribute matching the given name, or null. */ public Attribute locateAttribute(String name); - - /** - * Retrieve the attributes contained in this container. - * - * @return The contained attributes - */ - public Set attributes(); - public SingularAttribute locateSingularAttribute(String name); - public SingularAttribute createSingularAttribute(String name); - public SingularAttribute createVirtualSingularAttribute(String name); - public SingularAttribute locateCompositeAttribute(String name); - public SingularAttribute createCompositeAttribute(String name, Composite composite); - public PluralAttribute locatePluralAttribute(String name); - public PluralAttribute locateBag(String name); - public PluralAttribute createBag(String name); - public PluralAttribute locateSet(String name); - public PluralAttribute createSet(String name); - public IndexedPluralAttribute locateList(String name); - public IndexedPluralAttribute createList(String name); - public IndexedPluralAttribute locateMap(String name); + + public SingularAttribute createSingularAttribute(String name); + public SingularAttribute createCompositeAttribute(String name, Composite composite); + public PluralAttribute createBag(String name); + public PluralAttribute createSet(String name); + public IndexedPluralAttribute createList(String name); public IndexedPluralAttribute createMap(String name); + public SingularAttribute createSyntheticSingularAttribute(String name); + public SingularAttribute createSyntheticCompositeAttribute(String name, Hierarchical container); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/AggregatedCompositeIdentifierSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/AggregatedCompositeIdentifierSource.java index ab0cfbbdf2..28ecf8149f 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/AggregatedCompositeIdentifierSource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/AggregatedCompositeIdentifierSource.java @@ -25,7 +25,7 @@ package org.hibernate.metamodel.spi.source; /** * Additional contract describing the source of an identifier mapping whose {@link #getNature() nature} is - * {@link IdentifierSource.Nature#AGGREGATED_COMPOSITE aggregated-composite}. This equates to an identifier which is + * {@link org.hibernate.id.EntityIdentifierNature#AGGREGATED_COMPOSITE aggregated-composite}. This equates to an identifier which is * made up of multiple values which are defined as part of a component/embedded. * * @author Strong Liu diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/IdentifierSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/IdentifierSource.java index c03864eefd..0cc01c9761 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/IdentifierSource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/IdentifierSource.java @@ -23,6 +23,7 @@ */ package org.hibernate.metamodel.spi.source; +import org.hibernate.id.EntityIdentifierNature; import org.hibernate.metamodel.spi.binding.IdGenerator; /** @@ -43,34 +44,12 @@ public interface IdentifierSource { */ IdGenerator getIdentifierGeneratorDescriptor(); - public static enum Nature { - /** - * A single, simple identifier. Equivalent of an {@code } mapping or a single {@code @Id} - * annotation. Indicates the {@link IdentifierSource} is castable to {@link SimpleIdentifierSource}. - */ - SIMPLE, - - /** - * What we used to term an "embedded composite identifier", which is not to be confused with the JPA - * term embedded. Specifically a composite id where there is no component class (though there may be an - * {@code @IdClass}). Indicates that the {@link IdentifierSource} is castable to - * {@link NonAggregatedCompositeIdentifierSource} - */ - COMPOSITE, - - /** - * Composite identifier with an actual component class used to aggregate the individual attributes. Indicates - * that the {@link IdentifierSource} is castable to {@link AggregatedCompositeIdentifierSource} - */ - AGGREGATED_COMPOSITE - } - /** * Obtain the nature of this identifier source. * * @return The identifier source's nature. */ - public Nature getNature(); + public EntityIdentifierNature getNature(); /** * Returns the "unsaved" entity identifier value. @@ -80,4 +59,6 @@ public interface IdentifierSource { * @return the "unsaved" entity identifier value */ public String getUnsavedValue(); + + public Iterable getMetaAttributeSources(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/NonAggregatedCompositeIdentifierSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/NonAggregatedCompositeIdentifierSource.java index e1e839defb..1dec67b8fd 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/NonAggregatedCompositeIdentifierSource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/NonAggregatedCompositeIdentifierSource.java @@ -27,7 +27,7 @@ import java.util.List; /** * Additional contract describing the source of an identifier mapping whose {@link #getNature() nature} is - * {@link org.hibernate.metamodel.spi.source.IdentifierSource.Nature#SIMPLE simple}. + * {@link org.hibernate.id.EntityIdentifierNature#SIMPLE simple}. * * @author Steve Ebersole */ diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/SimpleIdentifierSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/SimpleIdentifierSource.java index bb79a9d8cf..00944cdf43 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/SimpleIdentifierSource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/SimpleIdentifierSource.java @@ -25,7 +25,7 @@ package org.hibernate.metamodel.spi.source; /** * Additional contract describing the source of an identifier mapping whose {@link #getNature() nature} is - * {@link org.hibernate.metamodel.spi.source.IdentifierSource.Nature#SIMPLE simple}. + * {@link org.hibernate.id.EntityIdentifierNature#SIMPLE simple}. * * @author Steve Ebersole */ diff --git a/hibernate-core/src/main/java/org/hibernate/property/PropertyAccessorFactory.java b/hibernate-core/src/main/java/org/hibernate/property/PropertyAccessorFactory.java index dae34e9da1..f1cd352463 100644 --- a/hibernate-core/src/main/java/org/hibernate/property/PropertyAccessorFactory.java +++ b/hibernate-core/src/main/java/org/hibernate/property/PropertyAccessorFactory.java @@ -39,6 +39,10 @@ import org.hibernate.metamodel.spi.binding.AttributeBinding; * @author Steve Ebersole */ public final class PropertyAccessorFactory { + public static final String BASIC_ACCESSOR_NAME = "property"; + public static final String FIELD_ACCESSOR_NAME = "field"; + public static final String EMBEDDED_ACCESSOR_NAME = "embedded"; + public static final String NOOP_ACCESSOR_NAME = "noop"; private static final PropertyAccessor BASIC_PROPERTY_ACCESSOR = new BasicPropertyAccessor(); private static final PropertyAccessor DIRECT_PROPERTY_ACCESSOR = new DirectPropertyAccessor(); @@ -110,16 +114,16 @@ public final class PropertyAccessorFactory { * @return An appropriate accessor. */ private static PropertyAccessor getPojoPropertyAccessor(String pojoAccessorStrategy) { - if ( StringHelper.isEmpty( pojoAccessorStrategy ) || "property".equals( pojoAccessorStrategy ) ) { + if ( StringHelper.isEmpty( pojoAccessorStrategy ) || BASIC_ACCESSOR_NAME.equals( pojoAccessorStrategy ) ) { return BASIC_PROPERTY_ACCESSOR; } - else if ( "field".equals( pojoAccessorStrategy ) ) { + else if ( FIELD_ACCESSOR_NAME.equals( pojoAccessorStrategy ) ) { return DIRECT_PROPERTY_ACCESSOR; } - else if ( "embedded".equals( pojoAccessorStrategy ) ) { + else if ( EMBEDDED_ACCESSOR_NAME.equals( pojoAccessorStrategy ) ) { return EMBEDDED_PROPERTY_ACCESSOR; } - else if ( "noop".equals(pojoAccessorStrategy) ) { + else if ( NOOP_ACCESSOR_NAME.equals( pojoAccessorStrategy ) ) { return NOOP_ACCESSOR; } else { @@ -157,11 +161,19 @@ public final class PropertyAccessorFactory { // todo : this eventually needs to be removed public static PropertyAccessor getPropertyAccessor(String type) throws MappingException { - if ( type==null || "property".equals(type) ) return BASIC_PROPERTY_ACCESSOR; - if ( "field".equals(type) ) return DIRECT_PROPERTY_ACCESSOR; + if ( type==null || BASIC_ACCESSOR_NAME.equals(type) ) { + return BASIC_PROPERTY_ACCESSOR; + } + if ( FIELD_ACCESSOR_NAME.equals(type) ) { + return DIRECT_PROPERTY_ACCESSOR; + } if ( "map".equals(type) ) return MAP_ACCESSOR; - if ( "embedded".equals(type) ) return EMBEDDED_PROPERTY_ACCESSOR; - if ( "noop".equals(type)) return NOOP_ACCESSOR; + if ( EMBEDDED_ACCESSOR_NAME.equals(type) ) { + return EMBEDDED_PROPERTY_ACCESSOR; + } + if ( NOOP_ACCESSOR_NAME.equals(type) ) { + return NOOP_ACCESSOR; + } return resolveCustomAccessor(type); } diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/PropertyFactory.java b/hibernate-core/src/main/java/org/hibernate/tuple/PropertyFactory.java index fe0cc8b86a..f760c9e1f4 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/PropertyFactory.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/PropertyFactory.java @@ -111,7 +111,7 @@ public class PropertyFactory { */ public static IdentifierProperty buildIdentifierProperty(EntityBinding mappedEntity, IdentifierGenerator generator) { - final SingularAttributeBinding property = mappedEntity.getHierarchyDetails().getEntityIdentifier().getValueBinding(); + final SingularAttributeBinding property = mappedEntity.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(); // TODO: the following will cause an NPE with "virtual" IDs; how should they be set? // (steve) virtual attributes will still be attributes, they will simply be marked as virtual. diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/entity/AbstractEntityTuplizer.java b/hibernate-core/src/main/java/org/hibernate/tuple/entity/AbstractEntityTuplizer.java index 7414151313..df3f1f6e7f 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/entity/AbstractEntityTuplizer.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/entity/AbstractEntityTuplizer.java @@ -242,8 +242,8 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer { this.entityMetamodel = entityMetamodel; if ( !entityMetamodel.getIdentifierProperty().isVirtual() ) { - idGetter = buildPropertyGetter( mappingInfo.getHierarchyDetails().getEntityIdentifier().getValueBinding() ); - idSetter = buildPropertySetter( mappingInfo.getHierarchyDetails().getEntityIdentifier().getValueBinding() ); + idGetter = buildPropertyGetter( mappingInfo.getHierarchyDetails().getEntityIdentifier().getAttributeBinding() ); + idSetter = buildPropertySetter( mappingInfo.getHierarchyDetails().getEntityIdentifier().getAttributeBinding() ); } else { idGetter = null; @@ -258,7 +258,7 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer { boolean foundCustomAccessor = false; int i = 0; for ( AttributeBinding property : mappingInfo.getAttributeBindingClosure() ) { - if ( property == mappingInfo.getHierarchyDetails().getEntityIdentifier().getValueBinding() ) { + if ( property == mappingInfo.getHierarchyDetails().getEntityIdentifier().getAttributeBinding() ) { continue; // ID binding processed above } diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityMetamodel.java b/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityMetamodel.java index db1ea9df7b..0790f84e35 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityMetamodel.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityMetamodel.java @@ -390,7 +390,9 @@ public class EntityMetamodel implements Serializable { boolean hasLazy = false; // TODO: Fix after HHH-6337 is fixed; for now assume entityBinding is the root binding - SingularNonAssociationAttributeBinding rootEntityIdentifier = entityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding(); + SingularNonAssociationAttributeBinding rootEntityIdentifier = entityBinding.getHierarchyDetails() + .getEntityIdentifier() + .getAttributeBinding(); // entityBinding.getAttributeClosureSpan() includes the identifier binding; // "properties" here excludes the ID, so subtract 1 if the identifier binding is non-null propertySpan = rootEntityIdentifier == null ? diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/entity/PojoEntityTuplizer.java b/hibernate-core/src/main/java/org/hibernate/tuple/entity/PojoEntityTuplizer.java index 37e74b115c..15ab9d4a4d 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/entity/PojoEntityTuplizer.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/entity/PojoEntityTuplizer.java @@ -324,10 +324,9 @@ public class PojoEntityTuplizer extends AbstractEntityTuplizer { proxyGetIdentifierMethod, proxySetIdentifierMethod, entityBinding.getHierarchyDetails().getEntityIdentifier().isEmbedded() - ? ( CompositeType ) entityBinding - .getHierarchyDetails() + ? ( CompositeType ) entityBinding.getHierarchyDetails() .getEntityIdentifier() - .getValueBinding() + .getAttributeBinding() .getHibernateTypeDescriptor() .getResolvedTypeMapping() : null diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/AssertSourcesTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/AssertSourcesTest.java index 46f6e5aeae..1723e3fb3b 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/AssertSourcesTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/AssertSourcesTest.java @@ -26,6 +26,7 @@ package org.hibernate.metamodel.internal.source; import java.util.Iterator; import org.hibernate.EntityMode; +import org.hibernate.id.EntityIdentifierNature; import org.hibernate.mapping.PropertyGeneration; import org.hibernate.metamodel.MetadataSources; import org.hibernate.metamodel.internal.MetadataBuilderImpl; @@ -116,7 +117,7 @@ public class AssertSourcesTest extends BaseUnitTestCase { IdentifierSource identifierSource = entitySource.getIdentifierSource(); assertNotNull( identifierSource ); - assertEquals( IdentifierSource.Nature.SIMPLE, identifierSource.getNature() ); + assertEquals( EntityIdentifierNature.SIMPLE, identifierSource.getNature() ); SimpleIdentifierSource simpleIdentifierSource = (SimpleIdentifierSource) identifierSource; SingularAttributeSource identifierAttributeSource = simpleIdentifierSource.getIdentifierAttributeSource(); assertEquals( "id", identifierAttributeSource.getName() ); diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/InheritanceBindingTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/InheritanceBindingTest.java index fe9d0b4d62..18eb2fecfb 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/InheritanceBindingTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/InheritanceBindingTest.java @@ -130,21 +130,21 @@ public class InheritanceBindingTest extends BaseAnnotationBindingTestCase { } assertEquals( 1, directAttributeBindings.size() ); assertSame( - noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding(), + noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(), directAttributeBindings.iterator().next() ); assertEquals( 1, noInheritanceEntityBinding.getAttributeBindingClosureSpan() ); Iterator iterator = noInheritanceEntityBinding.attributeBindings().iterator(); assertTrue( iterator.hasNext() ); - assertSame( noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding(), iterator.next() ); + assertSame( noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(), iterator.next() ); assertFalse( iterator.hasNext() ); iterator = noInheritanceEntityBinding.getAttributeBindingClosure().iterator(); assertTrue( iterator.hasNext() ); - assertSame( noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding(), iterator.next() ); + assertSame( noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(), iterator.next() ); assertFalse( iterator.hasNext() ); iterator = noInheritanceEntityBinding.getSubEntityAttributeBindingClosure().iterator(); assertTrue( iterator.hasNext() ); - assertSame( noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding(), iterator.next() ); + assertSame( noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(), iterator.next() ); assertFalse( iterator.hasNext() ); } diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/AbstractBasicBindingTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/AbstractBasicBindingTests.java index 8809d8a375..01b43cdbfc 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/AbstractBasicBindingTests.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/AbstractBasicBindingTests.java @@ -127,7 +127,7 @@ public abstract class AbstractBasicBindingTests extends BaseUnitTestCase { entityWithManyToOneBinding, attributeBinding, SingularAttributeBinding.class.cast( - simpleEntityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding() + simpleEntityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding() ), "`simpleEntity`" ); @@ -262,11 +262,11 @@ public abstract class AbstractBasicBindingTests extends BaseUnitTestCase { protected void assertIdAndSimpleProperty(EntityBinding entityBinding) { assertNotNull( entityBinding ); assertNotNull( entityBinding.getHierarchyDetails().getEntityIdentifier() ); - assertNotNull( entityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding() ); + assertNotNull( entityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding() ); AttributeBinding idAttributeBinding = entityBinding.locateAttributeBinding( "id" ); assertNotNull( idAttributeBinding ); - assertSame( idAttributeBinding, entityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding() ); + assertSame( idAttributeBinding, entityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding() ); assertSame( LongType.INSTANCE, idAttributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping() ); assertTrue( idAttributeBinding.getAttribute().isSingular() ); diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/BasicCollectionBindingTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/BasicCollectionBindingTests.java index e6eebeb3ab..488f649e61 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/BasicCollectionBindingTests.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/BasicCollectionBindingTests.java @@ -127,7 +127,7 @@ public class BasicCollectionBindingTests extends BaseUnitTestCase { // FK name is null because no default FK name is generated until HHH-7092 is fixed assertNull( fkBag.getName() ); checkEquals( - entityIdentifier.getValueBinding().getHibernateTypeDescriptor(), + entityIdentifier.getAttributeBinding().getHibernateTypeDescriptor(), bagKeyBinding.getHibernateTypeDescriptor() ); assertEquals( 0, bagCollectionTable.getPrimaryKey().getColumnSpan() ); @@ -176,7 +176,7 @@ public class BasicCollectionBindingTests extends BaseUnitTestCase { // FK is null because no default FK name is generated until HHH-7092 is fixed assertNull( fkSet.getName() ); checkEquals( - entityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding().getHibernateTypeDescriptor(), + entityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding().getHibernateTypeDescriptor(), setKeyBinding.getHibernateTypeDescriptor() ); assertFalse( setKeyBinding.isInverse() ); diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/SimpleValueBindingTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/SimpleValueBindingTests.java index 469d1eb50b..2f810be772 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/SimpleValueBindingTests.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/SimpleValueBindingTests.java @@ -92,7 +92,7 @@ public class SimpleValueBindingTests extends BaseUnitTestCase { attributeBinding.getHibernateTypeDescriptor().setExplicitTypeName( "long" ); assertSame( idAttribute, attributeBinding.getAttribute() ); - entityBinding.getHierarchyDetails().getEntityIdentifier().bindAsSingleAttributeIdentifier( + entityBinding.getHierarchyDetails().getEntityIdentifier().prepareAsSimpleIdentifier( attributeBinding, new IdGenerator( "assigned", "assigned", Collections.emptyMap() ), "null"