HHH-7240 - Develop identifier handling in new metamodel

This commit is contained in:
Steve Ebersole 2012-04-16 13:55:02 -05:00
parent 5946391477
commit d3a7e989f3
29 changed files with 498 additions and 214 deletions

View File

@ -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";
}

View File

@ -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:<ul>
* <li>an {@code <id/>} mapping</li>
* <li>a single {@code @Id} annotation</li>
* </ul>
*/
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:<ul>
* <li>
* a {@code <composite-id/>} mapping without a specified {@code name} XML-attribute (which would name
* the single identifier attribute
* </li>
* <li>
* multiple {@code @Id} annotations
* </li>
* </ul>
*
* 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:<ul>
* <li>
* a {@code <composite-id/>} mapping naming a single identifier attribute via the {@code name} XML-attribute
* </li>
* <li>
* an {@code @EmbeddedId} annotation
* </li>
* </ul>
*
* @see javax.persistence.EmbeddedId
*/
AGGREGATED_COMPOSITE
}

View File

@ -31,6 +31,8 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
import org.jboss.logging.Logger;
import org.hibernate.AssertionFailure; import org.hibernate.AssertionFailure;
import org.hibernate.EntityMode; import org.hibernate.EntityMode;
import org.hibernate.TruthValue; import org.hibernate.TruthValue;
@ -39,6 +41,7 @@ import org.hibernate.cfg.NamingStrategy;
import org.hibernate.cfg.NotYetImplementedException; import org.hibernate.cfg.NotYetImplementedException;
import org.hibernate.cfg.ObjectNameNormalizer; import org.hibernate.cfg.ObjectNameNormalizer;
import org.hibernate.engine.FetchTiming; import org.hibernate.engine.FetchTiming;
import org.hibernate.id.EntityIdentifierNature;
import org.hibernate.id.IdentifierGenerator; import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.PersistentIdentifierGenerator; import org.hibernate.id.PersistentIdentifierGenerator;
import org.hibernate.id.factory.IdentifierGeneratorFactory; 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.ExplicitHibernateTypeSource;
import org.hibernate.metamodel.spi.source.ForeignKeyContributingSource; import org.hibernate.metamodel.spi.source.ForeignKeyContributingSource;
import org.hibernate.metamodel.spi.source.IdentifierSource; 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.InLineViewSource;
import org.hibernate.metamodel.spi.source.IndexedPluralAttributeSource; import org.hibernate.metamodel.spi.source.IndexedPluralAttributeSource;
import org.hibernate.metamodel.spi.source.LocalBindingContext; 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.ComponentType;
import org.hibernate.type.EntityType; import org.hibernate.type.EntityType;
import org.hibernate.type.Type; 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. * The common binder shared between annotations and {@code hbm.xml} processing.
@ -438,7 +441,8 @@ public class Binder {
if ( !attribute.isTypeResolved() ) { if ( !attribute.isTypeResolved() ) {
attribute.resolveType( referencedEntityBinding.getEntity() ); 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(); final String uniqueKeyAttributeName = isRefToPk ? null : referencedAttributeBinding.getAttribute().getName();
Type resolvedType = metadata.getTypeResolver().getTypeFactory().manyToOne( Type resolvedType = metadata.getTypeResolver().getTypeFactory().manyToOne(
attributeBinding.getReferencedEntityName(), attributeBinding.getReferencedEntityName(),
@ -999,7 +1003,7 @@ public class Binder {
} }
private void bindIdentifier( final EntityBinding rootEntityBinding, final IdentifierSource identifierSource ) { private void bindIdentifier( final EntityBinding rootEntityBinding, final IdentifierSource identifierSource ) {
final Nature nature = identifierSource.getNature(); final EntityIdentifierNature nature = identifierSource.getNature();
switch ( nature ) { switch ( nature ) {
case SIMPLE: { case SIMPLE: {
bindSimpleIdentifier( rootEntityBinding, ( SimpleIdentifierSource ) identifierSource ); bindSimpleIdentifier( rootEntityBinding, ( SimpleIdentifierSource ) identifierSource );
@ -1035,7 +1039,7 @@ public class Binder {
// determine the unsaved value mapping // determine the unsaved value mapping
final String unsavedValue = interpretIdentifierUnsavedValue( identifierSource, generator ); final String unsavedValue = interpretIdentifierUnsavedValue( identifierSource, generator );
rootEntityBinding.getHierarchyDetails().getEntityIdentifier().bindAsSingleAttributeIdentifier( rootEntityBinding.getHierarchyDetails().getEntityIdentifier().prepareAsSimpleIdentifier(
idAttributeBinding, idAttributeBinding,
generator, generator,
unsavedValue unsavedValue
@ -1060,7 +1064,7 @@ public class Binder {
// determine the unsaved value mapping // determine the unsaved value mapping
final String unsavedValue = interpretIdentifierUnsavedValue( identifierSource, generator ); final String unsavedValue = interpretIdentifierUnsavedValue( identifierSource, generator );
rootEntityBinding.getHierarchyDetails().getEntityIdentifier().bindAsSingleAttributeIdentifier( rootEntityBinding.getHierarchyDetails().getEntityIdentifier().prepareAsAggregatedCompositeIdentifier(
idAttributeBinding, idAttributeBinding,
generator, generator,
unsavedValue unsavedValue
@ -1070,7 +1074,7 @@ public class Binder {
private void bindNonAggregatedCompositeIdentifier( private void bindNonAggregatedCompositeIdentifier(
EntityBinding rootEntityBinding, EntityBinding rootEntityBinding,
NonAggregatedCompositeIdentifierSource identifierSource) { NonAggregatedCompositeIdentifierSource identifierSource) {
// locate the attribute bindings // locate the attribute bindings for the real attributes
List<SingularAttributeBinding> idAttributeBindings = new ArrayList<SingularAttributeBinding>(); List<SingularAttributeBinding> idAttributeBindings = new ArrayList<SingularAttributeBinding>();
for ( SingularAttributeSource attributeSource : identifierSource.getAttributeSourcesMakingUpIdentifier() ) { for ( SingularAttributeSource attributeSource : identifierSource.getAttributeSourcesMakingUpIdentifier() ) {
idAttributeBindings.add( 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, idAttributeBindings,
createMetaAttributeContext( rootEntityBinding, identifierSource.getMetaAttributeSources() )
);
rootEntityBinding.getHierarchyDetails().getEntityIdentifier().prepareAsNonAggregatedCompositeIdentifier(
syntheticAttributeBinding,
identifierSource.getLookupIdClass() identifierSource.getLookupIdClass()
); );
} }
@ -1150,13 +1167,8 @@ public class Binder {
AttributeBindingContainer sourceAttributeBindingContainer, AttributeBindingContainer sourceAttributeBindingContainer,
EntityBinding referencedEntityBinding, EntityBinding referencedEntityBinding,
ForeignKey foreignKey) { ForeignKey foreignKey) {
// todo : currently only works for simple and embedded identifiers...
if ( resolutionDelegate == null ) { if ( resolutionDelegate == null ) {
// this needs to change when I integrate HHH-7240 in return referencedEntityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding();
if ( referencedEntityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding() == null ) {
throw new NotYetImplementedException( "reference to non-aggregated composite identifier not yet supported" );
}
return referencedEntityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding();
} }
final String explicitName = resolutionDelegate.getReferencedAttributeName(); final String explicitName = resolutionDelegate.getReferencedAttributeName();
@ -1480,9 +1492,19 @@ public class Binder {
final AttributeBindingContainer attributeBindingContainer, final AttributeBindingContainer attributeBindingContainer,
final AttributeSource attributeSource ) { final AttributeSource attributeSource ) {
return createMetaAttributeContext( return createMetaAttributeContext(
attributeSource.metaAttributes(), attributeBindingContainer,
attributeSource.metaAttributes()
);
}
private MetaAttributeContext createMetaAttributeContext(
final AttributeBindingContainer attributeBindingContainer,
final Iterable<MetaAttributeSource> metaAttributeSources ) {
return createMetaAttributeContext(
metaAttributeSources,
false, false,
attributeBindingContainer.getMetaAttributeContext() ); attributeBindingContainer.getMetaAttributeContext()
);
} }
private MetaAttributeContext createMetaAttributeContext( private MetaAttributeContext createMetaAttributeContext(
@ -1553,7 +1575,7 @@ public class Binder {
final AttributeBindingContainer attributeBindingContainer, final AttributeBindingContainer attributeBindingContainer,
final SingularAttributeSource attributeSource ) { final SingularAttributeSource attributeSource ) {
return attributeSource.isVirtualAttribute() return attributeSource.isVirtualAttribute()
? attributeBindingContainer.getAttributeContainer().createVirtualSingularAttribute( attributeSource.getName() ) ? attributeBindingContainer.getAttributeContainer().createSyntheticSingularAttribute( attributeSource.getName() )
: attributeBindingContainer.getAttributeContainer().createSingularAttribute( attributeSource.getName() ); : attributeBindingContainer.getAttributeContainer().createSingularAttribute( attributeSource.getName() );
} }
@ -1666,13 +1688,8 @@ public class Binder {
final ForeignKeyContributingSource.JoinColumnResolutionDelegate resolutionDelegate = final ForeignKeyContributingSource.JoinColumnResolutionDelegate resolutionDelegate =
attributeSource.getKeySource().getForeignKeyTargetColumnResolutionDelegate(); attributeSource.getKeySource().getForeignKeyTargetColumnResolutionDelegate();
// todo : currently only works for simple and embedded identifiers...
if ( resolutionDelegate == null ) { if ( resolutionDelegate == null ) {
// this needs to change when I integrate HHH-7240 in return entityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding();
if ( entityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding() == null ) {
throw new NotYetImplementedException( "reference to non-aggregated composite identifier not yet supported" );
}
return entityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding();
} }
final String explicitName = resolutionDelegate.getReferencedAttributeName(); final String explicitName = resolutionDelegate.getReferencedAttributeName();

View File

@ -539,10 +539,7 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
if ( entityBinding == null ) { if ( entityBinding == null ) {
throw new MappingException( "Entity binding not known: " + entityName ); throw new MappingException( "Entity binding not known: " + entityName );
} }
return entityBinding return entityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding()
.getHierarchyDetails()
.getEntityIdentifier()
.getValueBinding()
.getHibernateTypeDescriptor() .getHibernateTypeDescriptor()
.getResolvedTypeMapping(); .getResolvedTypeMapping();
} }
@ -553,7 +550,7 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
if ( entityBinding == null ) { if ( entityBinding == null ) {
throw new MappingException( "Entity binding not known: " + entityName ); 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(); return idBinding == null ? null : idBinding.getAttribute().getName();
} }

View File

@ -26,7 +26,9 @@ package org.hibernate.metamodel.internal.source.annotations.attribute;
import java.util.Map; import java.util.Map;
import org.hibernate.AssertionFailure; import org.hibernate.AssertionFailure;
import org.hibernate.id.EntityIdentifierNature;
import org.hibernate.metamodel.spi.binding.IdGenerator; 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.SimpleIdentifierSource;
import org.hibernate.metamodel.spi.source.SingularAttributeSource; import org.hibernate.metamodel.spi.source.SingularAttributeSource;
@ -51,8 +53,8 @@ public class SimpleIdentifierSourceImpl implements SimpleIdentifierSource {
} }
@Override @Override
public Nature getNature() { public EntityIdentifierNature getNature() {
return Nature.SIMPLE; return EntityIdentifierNature.SIMPLE;
} }
@Override @Override
@ -69,6 +71,11 @@ public class SimpleIdentifierSourceImpl implements SimpleIdentifierSource {
public String getUnsavedValue() { public String getUnsavedValue() {
return null; return null;
} }
@Override
public Iterable<MetaAttributeSource> getMetaAttributeSources() {
return null;
}
} }

View File

@ -31,19 +31,19 @@ package org.hibernate.metamodel.internal.source.annotations.entity;
public enum IdType { public enum IdType {
/** /**
* single @Id annotation. Corresponds to * single @Id annotation. Corresponds to
* {@link org.hibernate.metamodel.spi.source.IdentifierSource.Nature#SIMPLE} * {@link org.hibernate.id.EntityIdentifierNature#SIMPLE}
*/ */
SIMPLE, SIMPLE,
/** /**
* multiple @Id annotations. Corresponds to * multiple @Id annotations. Corresponds to
* {@link org.hibernate.metamodel.spi.source.IdentifierSource.Nature#COMPOSITE} * {@link org.hibernate.id.EntityIdentifierNature#COMPOSITE}
*/ */
COMPOSED, COMPOSED,
/** /**
* Indicates encountered {@code @EmbeddedId} annotation. Corresponds to * 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, EMBEDDED,

View File

@ -32,8 +32,8 @@ import org.jboss.jandex.AnnotationInstance;
import org.hibernate.AssertionFailure; import org.hibernate.AssertionFailure;
import org.hibernate.EntityMode; import org.hibernate.EntityMode;
import org.hibernate.cfg.NotYetImplementedException;
import org.hibernate.engine.OptimisticLockStyle; 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.AttributeOverride;
import org.hibernate.metamodel.internal.source.annotations.attribute.BasicAttribute; import org.hibernate.metamodel.internal.source.annotations.attribute.BasicAttribute;
import org.hibernate.metamodel.internal.source.annotations.attribute.DiscriminatorSourceImpl; 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.ComponentAttributeSource;
import org.hibernate.metamodel.spi.source.DiscriminatorSource; import org.hibernate.metamodel.spi.source.DiscriminatorSource;
import org.hibernate.metamodel.spi.source.IdentifierSource; 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.NonAggregatedCompositeIdentifierSource;
import org.hibernate.metamodel.spi.source.RootEntitySource; import org.hibernate.metamodel.spi.source.RootEntitySource;
import org.hibernate.metamodel.spi.source.SingularAttributeSource; 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 ) { if ( embeddableClass == null ) {
throw rootEntitySource.getLocalBindingContext().makeMappingException( throw rootEntitySource.getLocalBindingContext().makeMappingException(
"Could not locate embedded identifier class metadata" "Could not locate embedded identifier class metadata"
@ -191,14 +194,19 @@ public class RootEntitySourceImpl extends EntitySourceImpl implements RootEntity
} }
@Override @Override
public Nature getNature() { public EntityIdentifierNature getNature() {
return Nature.AGGREGATED_COMPOSITE; return EntityIdentifierNature.AGGREGATED_COMPOSITE;
} }
@Override @Override
public String getUnsavedValue() { public String getUnsavedValue() {
return null; return null;
} }
@Override
public Iterable<MetaAttributeSource> getMetaAttributeSources() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
} }
private class NonAggregatedCompositeIdentifierSourceImpl implements NonAggregatedCompositeIdentifierSource { private class NonAggregatedCompositeIdentifierSourceImpl implements NonAggregatedCompositeIdentifierSource {
@ -245,18 +253,21 @@ public class RootEntitySourceImpl extends EntitySourceImpl implements RootEntity
} }
@Override @Override
public Nature getNature() { public EntityIdentifierNature getNature() {
return Nature.COMPOSITE; return EntityIdentifierNature.COMPOSITE;
} }
@Override @Override
public String getUnsavedValue() { public String getUnsavedValue() {
return null; return null;
} }
@Override
public Iterable<MetaAttributeSource> getMetaAttributeSources() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
} }
} }

View File

@ -31,6 +31,7 @@ import org.hibernate.EntityMode;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.TruthValue; import org.hibernate.TruthValue;
import org.hibernate.engine.OptimisticLockStyle; 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.JaxbAnyElement;
import org.hibernate.internal.jaxb.mapping.hbm.JaxbComponentElement; import org.hibernate.internal.jaxb.mapping.hbm.JaxbComponentElement;
import org.hibernate.internal.jaxb.mapping.hbm.JaxbHibernateMapping; 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.DiscriminatorSource;
import org.hibernate.metamodel.spi.source.IdentifierSource; import org.hibernate.metamodel.spi.source.IdentifierSource;
import org.hibernate.metamodel.spi.source.MappingException; 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.NonAggregatedCompositeIdentifierSource;
import org.hibernate.metamodel.spi.source.RelationalValueSource; import org.hibernate.metamodel.spi.source.RelationalValueSource;
import org.hibernate.metamodel.spi.source.RootEntitySource; import org.hibernate.metamodel.spi.source.RootEntitySource;
@ -282,14 +284,19 @@ public class RootEntitySourceImpl extends AbstractEntitySourceImpl implements Ro
} }
@Override @Override
public Nature getNature() { public EntityIdentifierNature getNature() {
return Nature.SIMPLE; return EntityIdentifierNature.SIMPLE;
} }
@Override @Override
public String getUnsavedValue() { public String getUnsavedValue() {
return entityElement().getId().getUnsavedValue(); return entityElement().getId().getUnsavedValue();
} }
@Override
public Iterable<MetaAttributeSource> getMetaAttributeSources() {
return Helper.buildMetaAttributeSources( entityElement().getId().getMeta() );
}
} }
private class AggregatedCompositeIdentifierSourceImpl implements AggregatedCompositeIdentifierSource { private class AggregatedCompositeIdentifierSourceImpl implements AggregatedCompositeIdentifierSource {
@ -327,14 +334,19 @@ public class RootEntitySourceImpl extends AbstractEntitySourceImpl implements Ro
} }
@Override @Override
public Nature getNature() { public EntityIdentifierNature getNature() {
return Nature.AGGREGATED_COMPOSITE; return EntityIdentifierNature.AGGREGATED_COMPOSITE;
} }
@Override @Override
public String getUnsavedValue() { public String getUnsavedValue() {
return entityElement().getCompositeId().getUnsavedValue(); return entityElement().getCompositeId().getUnsavedValue();
} }
@Override
public Iterable<MetaAttributeSource> getMetaAttributeSources() {
return Helper.buildMetaAttributeSources( entityElement().getId().getMeta() );
}
} }
private class CompositeIdentifierComponentAttributeSourceImpl extends AbstractComponentAttributeSourceImpl { private class CompositeIdentifierComponentAttributeSourceImpl extends AbstractComponentAttributeSourceImpl {
@ -486,13 +498,18 @@ public class RootEntitySourceImpl extends AbstractEntitySourceImpl implements Ro
} }
@Override @Override
public Nature getNature() { public EntityIdentifierNature getNature() {
return Nature.COMPOSITE; return EntityIdentifierNature.COMPOSITE;
} }
@Override @Override
public String getUnsavedValue() { public String getUnsavedValue() {
return entityElement().getCompositeId().getUnsavedValue(); return entityElement().getCompositeId().getUnsavedValue();
} }
@Override
public Iterable<MetaAttributeSource> getMetaAttributeSources() {
return Helper.buildMetaAttributeSources( entityElement().getId().getMeta() );
}
} }
} }

View File

@ -24,6 +24,7 @@
package org.hibernate.metamodel.spi.binding; package org.hibernate.metamodel.spi.binding;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@ -48,7 +49,7 @@ public class CompositeAttributeBinding
implements SingularNonAssociationAttributeBinding, AttributeBindingContainer { implements SingularNonAssociationAttributeBinding, AttributeBindingContainer {
private final String path; private final String path;
private final SingularAttribute parentReference; private final SingularAttribute parentReference;
private Map<String, AttributeBinding> attributeBindingMap = new HashMap<String, AttributeBinding>(); private Map<String, AttributeBinding> attributeBindingMap;
public CompositeAttributeBinding( public CompositeAttributeBinding(
AttributeBindingContainer container, AttributeBindingContainer container,
@ -58,6 +59,45 @@ public class CompositeAttributeBinding
boolean lazy, boolean lazy,
MetaAttributeContext metaAttributeContext, MetaAttributeContext metaAttributeContext,
SingularAttribute parentReference) { SingularAttribute parentReference) {
this(
container,
attribute,
propertyAccessorName,
includedInOptimisticLocking,
lazy,
metaAttributeContext,
parentReference,
null
);
}
public CompositeAttributeBinding(
AttributeBindingContainer container,
SingularAttribute attribute,
String propertyAccessorName,
MetaAttributeContext metaAttributeContext,
List<SingularAttributeBinding> 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<SingularAttributeBinding> subAttributeBindings) {
super( super(
container, container,
attribute, attribute,
@ -66,8 +106,20 @@ public class CompositeAttributeBinding
lazy, lazy,
metaAttributeContext metaAttributeContext
); );
this.parentReference = parentReference; this.parentReference = parentReference;
this.path = container.getPathBase() + '.' + attribute.getName(); this.path = container.getPathBase() + '.' + attribute.getName();
if ( subAttributeBindings == null ) {
attributeBindingMap = new HashMap<String, AttributeBinding>();
}
else {
HashMap<String, AttributeBinding> map = new HashMap<String, AttributeBinding>();
for ( SingularAttributeBinding attributeBinding : subAttributeBindings ) {
attributeBindingMap.put( attributeBinding.getAttribute().getName(), attributeBinding );
}
attributeBindingMap = Collections.unmodifiableMap( map );
}
} }
@Override @Override

View File

@ -46,6 +46,7 @@ import org.hibernate.metamodel.spi.relational.TableSpecification;
import org.hibernate.metamodel.spi.source.JpaCallbackSource; import org.hibernate.metamodel.spi.source.JpaCallbackSource;
import org.hibernate.metamodel.spi.source.MetaAttributeContext; import org.hibernate.metamodel.spi.source.MetaAttributeContext;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.property.PropertyAccessorFactory;
import org.hibernate.tuple.entity.EntityTuplizer; import org.hibernate.tuple.entity.EntityTuplizer;
/** /**
@ -524,6 +525,26 @@ public class EntityBinding implements AttributeBindingContainer {
return binding; return binding;
} }
public CompositeAttributeBinding makeVirtualComponentAttributeBinding(
SingularAttribute syntheticAttribute,
List<SingularAttributeBinding> 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 @Override
public ManyToOneAttributeBinding makeManyToOneAttributeBinding( public ManyToOneAttributeBinding makeManyToOneAttributeBinding(
SingularAttribute attribute, SingularAttribute attribute,
@ -714,5 +735,4 @@ public class EntityBinding implements AttributeBindingContainer {
public Iterable<JpaCallbackSource> getJpaCallbackClasses() { public Iterable<JpaCallbackSource> getJpaCallbackClasses() {
return jpaCallbackClasses; return jpaCallbackClasses;
} }
} }

View File

@ -23,15 +23,18 @@
*/ */
package org.hibernate.metamodel.spi.binding; package org.hibernate.metamodel.spi.binding;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Properties; import java.util.Properties;
import org.hibernate.AssertionFailure;
import org.hibernate.id.EntityIdentifierNature;
import org.hibernate.id.IdentifierGenerator; import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.factory.IdentifierGeneratorFactory; import org.hibernate.id.factory.IdentifierGeneratorFactory;
import org.hibernate.metamodel.spi.relational.Column; 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:<ul> * Hold information about the entity identifier. At a high-level, can be one of 2-types:<ul>
* <li>single-attribute identifier - this includes both simple identifiers and aggregated composite identifiers</li> * <li>single-attribute identifier - this includes both simple identifiers and aggregated composite identifiers</li>
@ -43,8 +46,9 @@ import org.hibernate.metamodel.spi.relational.Column;
*/ */
public class EntityIdentifier { public class EntityIdentifier {
private final EntityBinding entityBinding; private final EntityBinding entityBinding;
private EntityIdentifierNature nature;
private List<SingularAttributeBinding> identifierAttributeBindings = new ArrayList<SingularAttributeBinding>(); private SingularNonAssociationAttributeBinding identifierAttributeBinding;
private IdGenerator idGenerator; private IdGenerator idGenerator;
private String unsavedValue; private String unsavedValue;
@ -63,12 +67,29 @@ public class EntityIdentifier {
this.entityBinding = entityBinding; 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, SingularNonAssociationAttributeBinding attributeBinding,
IdGenerator idGenerator, IdGenerator idGenerator,
String unsavedValue) { String unsavedValue) {
ensureNotBound(); ensureNotBound();
identifierAttributeBindings.add( attributeBinding );
this.nature = nature;
this.identifierAttributeBinding = attributeBinding;
this.idGenerator = idGenerator; this.idGenerator = idGenerator;
this.unsavedValue = unsavedValue; this.unsavedValue = unsavedValue;
this.columnCount = attributeBinding.getRelationalValueBindings().size(); this.columnCount = attributeBinding.getRelationalValueBindings().size();
@ -79,52 +100,57 @@ public class EntityIdentifier {
} }
} }
private void ensureNotBound() { public void prepareAsNonAggregatedCompositeIdentifier(
if ( ! identifierAttributeBindings.isEmpty() ) { CompositeAttributeBinding syntheticCompositeAttributeBinding,
throw new IllegalStateException( "Entity identifier was already bound" );
}
}
public void bindAsMultipleAttributeIdentifier(
List<SingularAttributeBinding> nonAggregatedCompositeAttributeBindings,
Class idClassClass) { Class idClassClass) {
ensureNotBound(); ensureNotBound();
for ( SingularAttributeBinding attributeBinding : nonAggregatedCompositeAttributeBindings ) {
identifierAttributeBindings.add( attributeBinding ); this.nature = COMPOSITE;
columnCount += attributeBinding.getRelationalValueBindings().size(); 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 // 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() ); entityBinding.getPrimaryTable().getPrimaryKey().addColumn( (Column) valueBinding.getValue() );
} }
} }
this.idClassClass = idClassClass; }
public EntityIdentifierNature getNature() {
return nature;
} }
public boolean isSingleAttribute() { public boolean isSingleAttribute() {
ensureBound(); ensureBound();
return identifierAttributeBindings.size() == 1; return getNature() != COMPOSITE;
} }
public List<SingularAttributeBinding> getIdentifierAttributeBindings() { public SingularNonAssociationAttributeBinding getAttributeBinding() {
return Collections.unmodifiableList( identifierAttributeBindings ); ensureBound();
return identifierAttributeBinding;
} }
public boolean isIdentifierAttributeBinding(AttributeBinding attributeBinding) { public boolean isIdentifierAttributeBinding(AttributeBinding attributeBinding) {
for ( SingularAttributeBinding identifierAttributeBinding : identifierAttributeBindings ) { ensureBound();
if ( identifierAttributeBinding.equals( attributeBinding ) ) { if ( getNature() == COMPOSITE ) {
return true; for ( AttributeBinding identifierAttributeBinding
: ( (CompositeAttributeBinding) this.identifierAttributeBinding ).attributeBindings() ) {
if ( identifierAttributeBinding.equals( attributeBinding ) ) {
return true;
}
} }
return false;
} }
return false; else {
} return identifierAttributeBinding.equals( attributeBinding );
protected SingularNonAssociationAttributeBinding getSingleIdentifierAttributeBinding() {
if ( ! isSingleAttribute() ) {
throw new IllegalStateException( "Entity identifier is made up of multiple attributes" );
} }
return (SingularNonAssociationAttributeBinding) identifierAttributeBindings.get( 0 );
} }
public String getUnsavedValue() { public String getUnsavedValue() {
@ -150,7 +176,7 @@ public class EntityIdentifier {
ensureBound(); ensureBound();
if ( identifierGenerator == null ) { if ( identifierGenerator == null ) {
if ( isSingleAttribute() && idGenerator != null ) { if ( isSingleAttribute() && idGenerator != null ) {
identifierGenerator = getSingleIdentifierAttributeBinding().createIdentifierGenerator( identifierGenerator = identifierAttributeBinding.createIdentifierGenerator(
idGenerator, idGenerator,
factory, factory,
properties properties
@ -166,11 +192,21 @@ public class EntityIdentifier {
} }
protected void ensureBound() { protected void ensureBound() {
if ( identifierAttributeBindings.isEmpty() ) { if ( ! isBound() ) {
throw new IllegalStateException( "Entity identifier was not yet bound" ); 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() { public int getColumnCount() {
ensureBound(); ensureBound();
return columnCount; return columnCount;

View File

@ -35,7 +35,6 @@ public class HierarchyDetails {
private final EntityMode entityMode; private final EntityMode entityMode;
private final EntityIdentifier entityIdentifier; private final EntityIdentifier entityIdentifier;
private EntityDiscriminator entityDiscriminator; private EntityDiscriminator entityDiscriminator;
private OptimisticLockStyle optimisticLockStyle; private OptimisticLockStyle optimisticLockStyle;

View File

@ -28,7 +28,6 @@ import java.util.HashMap;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.Set; import java.util.Set;
import org.hibernate.cfg.NotYetImplementedException;
import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.Value; import org.hibernate.internal.util.Value;
@ -44,6 +43,7 @@ public abstract class AbstractAttributeContainer implements AttributeContainer,
private final String className; private final String className;
private final Value<Class<?>> classReference; private final Value<Class<?>> classReference;
private final Hierarchical superType; private final Hierarchical superType;
private LinkedHashSet<Attribute> attributeSet = new LinkedHashSet<Attribute>(); private LinkedHashSet<Attribute> attributeSet = new LinkedHashSet<Attribute>();
private HashMap<String, Attribute> attributeMap = new HashMap<String, Attribute>(); private HashMap<String, Attribute> attributeMap = new HashMap<String, Attribute>();
@ -99,84 +99,36 @@ public abstract class AbstractAttributeContainer implements AttributeContainer,
return (SingularAttribute) locateAttribute( name ); 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 @Override
public SingularAttribute locateCompositeAttribute(String name) { public SingularAttribute locateCompositeAttribute(String name) {
return (SingularAttributeImpl) locateAttribute( 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 @Override
public PluralAttribute locatePluralAttribute(String name) { public PluralAttribute locatePluralAttribute(String name) {
return (PluralAttribute) locateAttribute( 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 @Override
public PluralAttribute locateBag(String name) { public PluralAttribute locateBag(String name) {
return locatePluralAttribute( name ); return locatePluralAttribute( name );
} }
@Override
public PluralAttribute createBag(String name) {
return createPluralAttribute( name, PluralAttributeNature.BAG );
}
@Override @Override
public PluralAttribute locateSet(String name) { public PluralAttribute locateSet(String name) {
return locatePluralAttribute( name ); return locatePluralAttribute( name );
} }
@Override
public PluralAttribute createSet(String name) {
return createPluralAttribute( name, PluralAttributeNature.SET );
}
@Override @Override
public IndexedPluralAttribute locateList(String name) { public IndexedPluralAttribute locateList(String name) {
return (IndexedPluralAttribute) locatePluralAttribute( name ); return (IndexedPluralAttribute) locatePluralAttribute( name );
} }
@Override
public IndexedPluralAttribute createList(String name) {
return (IndexedPluralAttribute) createPluralAttribute( name, PluralAttributeNature.LIST );
}
@Override @Override
public IndexedPluralAttribute locateMap(String name) { public IndexedPluralAttribute locateMap(String name) {
return (IndexedPluralAttribute) locatePluralAttribute( name ); return (IndexedPluralAttribute) locatePluralAttribute( name );
} }
@Override
public IndexedPluralAttribute createMap(String name) {
return (IndexedPluralAttribute) createPluralAttribute( name, PluralAttributeNature.MAP );
}
@Override @Override
public String toString() { public String toString() {
final StringBuilder sb = new StringBuilder(); final StringBuilder sb = new StringBuilder();
@ -187,8 +139,66 @@ public abstract class AbstractAttributeContainer implements AttributeContainer,
return sb.toString(); 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) { protected void addAttribute(Attribute attribute) {
// todo : how to best "secure" this?
if ( attributeMap.put( attribute.getName(), attribute ) != null ) { if ( attributeMap.put( attribute.getName(), attribute ) != null ) {
throw new IllegalArgumentException( "Attribute with name [" + attribute.getName() + "] already registered" ); 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 { public static class SingularAttributeImpl implements SingularAttribute {
private final AttributeContainer attributeContainer; private final AttributeContainer attributeContainer;
private final String name; private final String name;
private final boolean synthetic;
private Type type; private Type type;
public SingularAttributeImpl(String name, AttributeContainer attributeContainer) { public SingularAttributeImpl(AttributeContainer attributeContainer, String name, boolean synthetic) {
this.name = name;
this.attributeContainer = attributeContainer; this.attributeContainer = attributeContainer;
this.name = name;
this.synthetic = synthetic;
} }
public boolean isTypeResolved() { public boolean isTypeResolved() {
@ -237,6 +249,11 @@ public abstract class AbstractAttributeContainer implements AttributeContainer,
public boolean isSingular() { public boolean isSingular() {
return true; return true;
} }
@Override
public boolean isSynthetic() {
return synthetic;
}
} }
public static class PluralAttributeImpl implements PluralAttribute { public static class PluralAttributeImpl implements PluralAttribute {
@ -246,10 +263,10 @@ public abstract class AbstractAttributeContainer implements AttributeContainer,
private Type elementType; 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.name = name;
this.nature = nature; this.nature = nature;
this.attributeContainer = attributeContainer;
} }
@Override @Override
@ -262,6 +279,12 @@ public abstract class AbstractAttributeContainer implements AttributeContainer,
return false; return false;
} }
@Override
public boolean isSynthetic() {
// don't think there are ever any synthetic plural attributes created...
return false;
}
@Override @Override
public PluralAttributeNature getNature() { public PluralAttributeNature getNature() {
return nature; return nature;
@ -291,8 +314,8 @@ public abstract class AbstractAttributeContainer implements AttributeContainer,
public static class IndexedPluralAttributeImpl extends PluralAttributeImpl implements IndexedPluralAttribute { public static class IndexedPluralAttributeImpl extends PluralAttributeImpl implements IndexedPluralAttribute {
private Type indexType; private Type indexType;
public IndexedPluralAttributeImpl(String name, PluralAttributeNature nature, AttributeContainer attributeContainer) { public IndexedPluralAttributeImpl(AbstractAttributeContainer attributeContainer, String name, PluralAttributeNature nature) {
super( name, nature, attributeContainer ); super( attributeContainer, name, nature );
} }
@Override @Override

View File

@ -52,4 +52,13 @@ public interface Attribute {
* @return True if attribute is singular; false if plural. * @return True if attribute is singular; false if plural.
*/ */
public boolean isSingular(); 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();
} }

View File

@ -42,6 +42,13 @@ public interface AttributeContainer extends Type {
*/ */
public String getRoleBaseName(); public String getRoleBaseName();
/**
* Retrieve the attributes contained in this container.
*
* @return The contained attributes
*/
public Set<Attribute> attributes();
/** /**
* Retrieve an attribute by name. * Retrieve an attribute by name.
* *
@ -50,33 +57,21 @@ public interface AttributeContainer extends Type {
* @return The attribute matching the given name, or null. * @return The attribute matching the given name, or null.
*/ */
public Attribute locateAttribute(String name); public Attribute locateAttribute(String name);
/**
* Retrieve the attributes contained in this container.
*
* @return The contained attributes
*/
public Set<Attribute> attributes();
public SingularAttribute locateSingularAttribute(String name); public SingularAttribute locateSingularAttribute(String name);
public SingularAttribute createSingularAttribute(String name);
public SingularAttribute createVirtualSingularAttribute(String name);
public SingularAttribute locateCompositeAttribute(String name); public SingularAttribute locateCompositeAttribute(String name);
public SingularAttribute createCompositeAttribute(String name, Composite composite);
public PluralAttribute locatePluralAttribute(String name); public PluralAttribute locatePluralAttribute(String name);
public PluralAttribute locateBag(String name); public PluralAttribute locateBag(String name);
public PluralAttribute createBag(String name);
public PluralAttribute locateSet(String name); public PluralAttribute locateSet(String name);
public PluralAttribute createSet(String name);
public IndexedPluralAttribute locateList(String name); public IndexedPluralAttribute locateList(String name);
public IndexedPluralAttribute createList(String name);
public IndexedPluralAttribute locateMap(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 IndexedPluralAttribute createMap(String name);
public SingularAttribute createSyntheticSingularAttribute(String name);
public SingularAttribute createSyntheticCompositeAttribute(String name, Hierarchical container);
} }

View File

@ -25,7 +25,7 @@ package org.hibernate.metamodel.spi.source;
/** /**
* Additional contract describing the source of an identifier mapping whose {@link #getNature() nature} is * 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. * made up of multiple values which are defined as part of a component/embedded.
* *
* @author Strong Liu * @author Strong Liu

View File

@ -23,6 +23,7 @@
*/ */
package org.hibernate.metamodel.spi.source; package org.hibernate.metamodel.spi.source;
import org.hibernate.id.EntityIdentifierNature;
import org.hibernate.metamodel.spi.binding.IdGenerator; import org.hibernate.metamodel.spi.binding.IdGenerator;
/** /**
@ -43,34 +44,12 @@ public interface IdentifierSource {
*/ */
IdGenerator getIdentifierGeneratorDescriptor(); IdGenerator getIdentifierGeneratorDescriptor();
public static enum Nature {
/**
* A single, simple identifier. Equivalent of an {@code <id/>} 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. * Obtain the nature of this identifier source.
* *
* @return The identifier source's nature. * @return The identifier source's nature.
*/ */
public Nature getNature(); public EntityIdentifierNature getNature();
/** /**
* Returns the "unsaved" entity identifier value. * Returns the "unsaved" entity identifier value.
@ -80,4 +59,6 @@ public interface IdentifierSource {
* @return the "unsaved" entity identifier value * @return the "unsaved" entity identifier value
*/ */
public String getUnsavedValue(); public String getUnsavedValue();
public Iterable<MetaAttributeSource> getMetaAttributeSources();
} }

View File

@ -27,7 +27,7 @@ import java.util.List;
/** /**
* Additional contract describing the source of an identifier mapping whose {@link #getNature() nature} is * 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 * @author Steve Ebersole
*/ */

View File

@ -25,7 +25,7 @@ package org.hibernate.metamodel.spi.source;
/** /**
* Additional contract describing the source of an identifier mapping whose {@link #getNature() nature} is * 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 * @author Steve Ebersole
*/ */

View File

@ -39,6 +39,10 @@ import org.hibernate.metamodel.spi.binding.AttributeBinding;
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public final class PropertyAccessorFactory { 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 BASIC_PROPERTY_ACCESSOR = new BasicPropertyAccessor();
private static final PropertyAccessor DIRECT_PROPERTY_ACCESSOR = new DirectPropertyAccessor(); private static final PropertyAccessor DIRECT_PROPERTY_ACCESSOR = new DirectPropertyAccessor();
@ -110,16 +114,16 @@ public final class PropertyAccessorFactory {
* @return An appropriate accessor. * @return An appropriate accessor.
*/ */
private static PropertyAccessor getPojoPropertyAccessor(String pojoAccessorStrategy) { 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; return BASIC_PROPERTY_ACCESSOR;
} }
else if ( "field".equals( pojoAccessorStrategy ) ) { else if ( FIELD_ACCESSOR_NAME.equals( pojoAccessorStrategy ) ) {
return DIRECT_PROPERTY_ACCESSOR; return DIRECT_PROPERTY_ACCESSOR;
} }
else if ( "embedded".equals( pojoAccessorStrategy ) ) { else if ( EMBEDDED_ACCESSOR_NAME.equals( pojoAccessorStrategy ) ) {
return EMBEDDED_PROPERTY_ACCESSOR; return EMBEDDED_PROPERTY_ACCESSOR;
} }
else if ( "noop".equals(pojoAccessorStrategy) ) { else if ( NOOP_ACCESSOR_NAME.equals( pojoAccessorStrategy ) ) {
return NOOP_ACCESSOR; return NOOP_ACCESSOR;
} }
else { else {
@ -157,11 +161,19 @@ public final class PropertyAccessorFactory {
// todo : this eventually needs to be removed // todo : this eventually needs to be removed
public static PropertyAccessor getPropertyAccessor(String type) throws MappingException { public static PropertyAccessor getPropertyAccessor(String type) throws MappingException {
if ( type==null || "property".equals(type) ) return BASIC_PROPERTY_ACCESSOR; if ( type==null || BASIC_ACCESSOR_NAME.equals(type) ) {
if ( "field".equals(type) ) return DIRECT_PROPERTY_ACCESSOR; return BASIC_PROPERTY_ACCESSOR;
}
if ( FIELD_ACCESSOR_NAME.equals(type) ) {
return DIRECT_PROPERTY_ACCESSOR;
}
if ( "map".equals(type) ) return MAP_ACCESSOR; if ( "map".equals(type) ) return MAP_ACCESSOR;
if ( "embedded".equals(type) ) return EMBEDDED_PROPERTY_ACCESSOR; if ( EMBEDDED_ACCESSOR_NAME.equals(type) ) {
if ( "noop".equals(type)) return NOOP_ACCESSOR; return EMBEDDED_PROPERTY_ACCESSOR;
}
if ( NOOP_ACCESSOR_NAME.equals(type) ) {
return NOOP_ACCESSOR;
}
return resolveCustomAccessor(type); return resolveCustomAccessor(type);
} }

View File

@ -111,7 +111,7 @@ public class PropertyFactory {
*/ */
public static IdentifierProperty buildIdentifierProperty(EntityBinding mappedEntity, IdentifierGenerator generator) { 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? // 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. // (steve) virtual attributes will still be attributes, they will simply be marked as virtual.

View File

@ -242,8 +242,8 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
this.entityMetamodel = entityMetamodel; this.entityMetamodel = entityMetamodel;
if ( !entityMetamodel.getIdentifierProperty().isVirtual() ) { if ( !entityMetamodel.getIdentifierProperty().isVirtual() ) {
idGetter = buildPropertyGetter( mappingInfo.getHierarchyDetails().getEntityIdentifier().getValueBinding() ); idGetter = buildPropertyGetter( mappingInfo.getHierarchyDetails().getEntityIdentifier().getAttributeBinding() );
idSetter = buildPropertySetter( mappingInfo.getHierarchyDetails().getEntityIdentifier().getValueBinding() ); idSetter = buildPropertySetter( mappingInfo.getHierarchyDetails().getEntityIdentifier().getAttributeBinding() );
} }
else { else {
idGetter = null; idGetter = null;
@ -258,7 +258,7 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
boolean foundCustomAccessor = false; boolean foundCustomAccessor = false;
int i = 0; int i = 0;
for ( AttributeBinding property : mappingInfo.getAttributeBindingClosure() ) { for ( AttributeBinding property : mappingInfo.getAttributeBindingClosure() ) {
if ( property == mappingInfo.getHierarchyDetails().getEntityIdentifier().getValueBinding() ) { if ( property == mappingInfo.getHierarchyDetails().getEntityIdentifier().getAttributeBinding() ) {
continue; // ID binding processed above continue; // ID binding processed above
} }

View File

@ -390,7 +390,9 @@ public class EntityMetamodel implements Serializable {
boolean hasLazy = false; boolean hasLazy = false;
// TODO: Fix after HHH-6337 is fixed; for now assume entityBinding is the root binding // 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; // entityBinding.getAttributeClosureSpan() includes the identifier binding;
// "properties" here excludes the ID, so subtract 1 if the identifier binding is non-null // "properties" here excludes the ID, so subtract 1 if the identifier binding is non-null
propertySpan = rootEntityIdentifier == null ? propertySpan = rootEntityIdentifier == null ?

View File

@ -324,10 +324,9 @@ public class PojoEntityTuplizer extends AbstractEntityTuplizer {
proxyGetIdentifierMethod, proxyGetIdentifierMethod,
proxySetIdentifierMethod, proxySetIdentifierMethod,
entityBinding.getHierarchyDetails().getEntityIdentifier().isEmbedded() entityBinding.getHierarchyDetails().getEntityIdentifier().isEmbedded()
? ( CompositeType ) entityBinding ? ( CompositeType ) entityBinding.getHierarchyDetails()
.getHierarchyDetails()
.getEntityIdentifier() .getEntityIdentifier()
.getValueBinding() .getAttributeBinding()
.getHibernateTypeDescriptor() .getHibernateTypeDescriptor()
.getResolvedTypeMapping() .getResolvedTypeMapping()
: null : null

View File

@ -26,6 +26,7 @@ package org.hibernate.metamodel.internal.source;
import java.util.Iterator; import java.util.Iterator;
import org.hibernate.EntityMode; import org.hibernate.EntityMode;
import org.hibernate.id.EntityIdentifierNature;
import org.hibernate.mapping.PropertyGeneration; import org.hibernate.mapping.PropertyGeneration;
import org.hibernate.metamodel.MetadataSources; import org.hibernate.metamodel.MetadataSources;
import org.hibernate.metamodel.internal.MetadataBuilderImpl; import org.hibernate.metamodel.internal.MetadataBuilderImpl;
@ -116,7 +117,7 @@ public class AssertSourcesTest extends BaseUnitTestCase {
IdentifierSource identifierSource = entitySource.getIdentifierSource(); IdentifierSource identifierSource = entitySource.getIdentifierSource();
assertNotNull( identifierSource ); assertNotNull( identifierSource );
assertEquals( IdentifierSource.Nature.SIMPLE, identifierSource.getNature() ); assertEquals( EntityIdentifierNature.SIMPLE, identifierSource.getNature() );
SimpleIdentifierSource simpleIdentifierSource = (SimpleIdentifierSource) identifierSource; SimpleIdentifierSource simpleIdentifierSource = (SimpleIdentifierSource) identifierSource;
SingularAttributeSource identifierAttributeSource = simpleIdentifierSource.getIdentifierAttributeSource(); SingularAttributeSource identifierAttributeSource = simpleIdentifierSource.getIdentifierAttributeSource();
assertEquals( "id", identifierAttributeSource.getName() ); assertEquals( "id", identifierAttributeSource.getName() );

View File

@ -130,21 +130,21 @@ public class InheritanceBindingTest extends BaseAnnotationBindingTestCase {
} }
assertEquals( 1, directAttributeBindings.size() ); assertEquals( 1, directAttributeBindings.size() );
assertSame( assertSame(
noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding(), noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(),
directAttributeBindings.iterator().next() directAttributeBindings.iterator().next()
); );
assertEquals( 1, noInheritanceEntityBinding.getAttributeBindingClosureSpan() ); assertEquals( 1, noInheritanceEntityBinding.getAttributeBindingClosureSpan() );
Iterator<AttributeBinding> iterator = noInheritanceEntityBinding.attributeBindings().iterator(); Iterator<AttributeBinding> iterator = noInheritanceEntityBinding.attributeBindings().iterator();
assertTrue( iterator.hasNext() ); assertTrue( iterator.hasNext() );
assertSame( noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding(), iterator.next() ); assertSame( noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(), iterator.next() );
assertFalse( iterator.hasNext() ); assertFalse( iterator.hasNext() );
iterator = noInheritanceEntityBinding.getAttributeBindingClosure().iterator(); iterator = noInheritanceEntityBinding.getAttributeBindingClosure().iterator();
assertTrue( iterator.hasNext() ); assertTrue( iterator.hasNext() );
assertSame( noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding(), iterator.next() ); assertSame( noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(), iterator.next() );
assertFalse( iterator.hasNext() ); assertFalse( iterator.hasNext() );
iterator = noInheritanceEntityBinding.getSubEntityAttributeBindingClosure().iterator(); iterator = noInheritanceEntityBinding.getSubEntityAttributeBindingClosure().iterator();
assertTrue( iterator.hasNext() ); assertTrue( iterator.hasNext() );
assertSame( noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding(), iterator.next() ); assertSame( noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(), iterator.next() );
assertFalse( iterator.hasNext() ); assertFalse( iterator.hasNext() );
} }

View File

@ -127,7 +127,7 @@ public abstract class AbstractBasicBindingTests extends BaseUnitTestCase {
entityWithManyToOneBinding, entityWithManyToOneBinding,
attributeBinding, attributeBinding,
SingularAttributeBinding.class.cast( SingularAttributeBinding.class.cast(
simpleEntityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding() simpleEntityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding()
), ),
"`simpleEntity`" "`simpleEntity`"
); );
@ -262,11 +262,11 @@ public abstract class AbstractBasicBindingTests extends BaseUnitTestCase {
protected void assertIdAndSimpleProperty(EntityBinding entityBinding) { protected void assertIdAndSimpleProperty(EntityBinding entityBinding) {
assertNotNull( entityBinding ); assertNotNull( entityBinding );
assertNotNull( entityBinding.getHierarchyDetails().getEntityIdentifier() ); assertNotNull( entityBinding.getHierarchyDetails().getEntityIdentifier() );
assertNotNull( entityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding() ); assertNotNull( entityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding() );
AttributeBinding idAttributeBinding = entityBinding.locateAttributeBinding( "id" ); AttributeBinding idAttributeBinding = entityBinding.locateAttributeBinding( "id" );
assertNotNull( idAttributeBinding ); assertNotNull( idAttributeBinding );
assertSame( idAttributeBinding, entityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding() ); assertSame( idAttributeBinding, entityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding() );
assertSame( LongType.INSTANCE, idAttributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping() ); assertSame( LongType.INSTANCE, idAttributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping() );
assertTrue( idAttributeBinding.getAttribute().isSingular() ); assertTrue( idAttributeBinding.getAttribute().isSingular() );

View File

@ -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 // FK name is null because no default FK name is generated until HHH-7092 is fixed
assertNull( fkBag.getName() ); assertNull( fkBag.getName() );
checkEquals( checkEquals(
entityIdentifier.getValueBinding().getHibernateTypeDescriptor(), entityIdentifier.getAttributeBinding().getHibernateTypeDescriptor(),
bagKeyBinding.getHibernateTypeDescriptor() bagKeyBinding.getHibernateTypeDescriptor()
); );
assertEquals( 0, bagCollectionTable.getPrimaryKey().getColumnSpan() ); 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 // FK is null because no default FK name is generated until HHH-7092 is fixed
assertNull( fkSet.getName() ); assertNull( fkSet.getName() );
checkEquals( checkEquals(
entityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding().getHibernateTypeDescriptor(), entityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding().getHibernateTypeDescriptor(),
setKeyBinding.getHibernateTypeDescriptor() setKeyBinding.getHibernateTypeDescriptor()
); );
assertFalse( setKeyBinding.isInverse() ); assertFalse( setKeyBinding.isInverse() );

View File

@ -92,7 +92,7 @@ public class SimpleValueBindingTests extends BaseUnitTestCase {
attributeBinding.getHibernateTypeDescriptor().setExplicitTypeName( "long" ); attributeBinding.getHibernateTypeDescriptor().setExplicitTypeName( "long" );
assertSame( idAttribute, attributeBinding.getAttribute() ); assertSame( idAttribute, attributeBinding.getAttribute() );
entityBinding.getHierarchyDetails().getEntityIdentifier().bindAsSingleAttributeIdentifier( entityBinding.getHierarchyDetails().getEntityIdentifier().prepareAsSimpleIdentifier(
attributeBinding, attributeBinding,
new IdGenerator( "assigned", "assigned", Collections.<String,String>emptyMap() ), new IdGenerator( "assigned", "assigned", Collections.<String,String>emptyMap() ),
"null" "null"