HHH-7240 - Develop identifier handling in new metamodel
This commit is contained in:
parent
5946391477
commit
d3a7e989f3
|
@ -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";
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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<SingularAttributeBinding> idAttributeBindings = new ArrayList<SingularAttributeBinding>();
|
||||
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<MetaAttributeSource> 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();
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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<MetaAttributeSource> getMetaAttributeSources() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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<MetaAttributeSource> 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<MetaAttributeSource> getMetaAttributeSources() {
|
||||
return null; //To change body of implemented methods use File | Settings | File Templates.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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<MetaAttributeSource> 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<MetaAttributeSource> 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<MetaAttributeSource> getMetaAttributeSources() {
|
||||
return Helper.buildMetaAttributeSources( entityElement().getId().getMeta() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<String, AttributeBinding> attributeBindingMap = new HashMap<String, AttributeBinding>();
|
||||
private Map<String, AttributeBinding> 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<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(
|
||||
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<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
|
||||
|
|
|
@ -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<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
|
||||
public ManyToOneAttributeBinding makeManyToOneAttributeBinding(
|
||||
SingularAttribute attribute,
|
||||
|
@ -714,5 +735,4 @@ public class EntityBinding implements AttributeBindingContainer {
|
|||
public Iterable<JpaCallbackSource> getJpaCallbackClasses() {
|
||||
return jpaCallbackClasses;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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:<ul>
|
||||
* <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 {
|
||||
private final EntityBinding entityBinding;
|
||||
private EntityIdentifierNature nature;
|
||||
|
||||
private List<SingularAttributeBinding> identifierAttributeBindings = new ArrayList<SingularAttributeBinding>();
|
||||
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<SingularAttributeBinding> 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<SingularAttributeBinding> 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;
|
||||
|
|
|
@ -35,7 +35,6 @@ public class HierarchyDetails {
|
|||
private final EntityMode entityMode;
|
||||
|
||||
private final EntityIdentifier entityIdentifier;
|
||||
|
||||
private EntityDiscriminator entityDiscriminator;
|
||||
|
||||
private OptimisticLockStyle optimisticLockStyle;
|
||||
|
|
|
@ -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<Class<?>> classReference;
|
||||
private final Hierarchical superType;
|
||||
|
||||
private LinkedHashSet<Attribute> attributeSet = new LinkedHashSet<Attribute>();
|
||||
private HashMap<String, Attribute> attributeMap = new HashMap<String, Attribute>();
|
||||
|
||||
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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<Attribute> 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<Attribute> 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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 <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.
|
||||
*
|
||||
* @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<MetaAttributeSource> getMetaAttributeSources();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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 ?
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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() );
|
||||
|
|
|
@ -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<AttributeBinding> 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() );
|
||||
}
|
||||
|
||||
|
|
|
@ -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() );
|
||||
|
|
|
@ -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() );
|
||||
|
|
|
@ -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.<String,String>emptyMap() ),
|
||||
"null"
|
||||
|
|
Loading…
Reference in New Issue