HHH-9055 - Binding support for IdClass and MapsId needs a complete review

This commit is contained in:
Steve Ebersole 2014-04-24 15:27:53 -05:00
parent 104eea1beb
commit bd7605da01
114 changed files with 4910 additions and 2039 deletions

View File

@ -48,6 +48,7 @@ import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.event.service.spi.EventListenerRegistry;
import org.hibernate.event.spi.EventType;
import org.hibernate.id.EntityIdentifierNature;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.StringHelper;
@ -58,6 +59,7 @@ import org.hibernate.metamodel.spi.binding.AttributeBinding;
import org.hibernate.metamodel.spi.binding.BasicAttributeBinding;
import org.hibernate.metamodel.spi.binding.EmbeddedAttributeBinding;
import org.hibernate.metamodel.spi.binding.EntityBinding;
import org.hibernate.metamodel.spi.binding.EntityIdentifier;
import org.hibernate.metamodel.spi.binding.InheritanceType;
import org.hibernate.metamodel.spi.binding.RelationalValueBinding;
import org.hibernate.metamodel.spi.domain.Attribute;
@ -404,9 +406,18 @@ class TypeSafeActivator {
* {@code propertyPath} is {@code null} or empty, the id attribute binding is returned.
*/
private static AttributeBinding findPropertyByName(EntityBinding entityBinding, String propertyPath) {
final AttributeBinding idAttributeBinding = entityBinding.getHierarchyDetails()
.getEntityIdentifier()
.getAttributeBinding();
final AttributeBinding idAttributeBinding;
final EntityIdentifier idInfo = entityBinding.getHierarchyDetails().getEntityIdentifier();
if ( idInfo.getNature() == EntityIdentifierNature.NON_AGGREGATED_COMPOSITE ) {
idAttributeBinding = null;
}
else {
final EntityIdentifier.AttributeBasedIdentifierBinding identifierBinding =
(EntityIdentifier.AttributeBasedIdentifierBinding) idInfo.getEntityIdentifierBinding();
idAttributeBinding = identifierBinding.getAttributeBinding();
}
final String idAttributeName = idAttributeBinding == null ? null : idAttributeBinding.getAttribute().getName();
if ( propertyPath == null || propertyPath.length() == 0 || propertyPath.equals( idAttributeName ) ) {

View File

@ -54,6 +54,7 @@ import org.hibernate.engine.spi.FilterDefinition;
import org.hibernate.engine.spi.NamedQueryDefinition;
import org.hibernate.engine.spi.NamedSQLQueryDefinition;
import org.hibernate.engine.spi.SyntheticAttributeHelper;
import org.hibernate.id.EntityIdentifierNature;
import org.hibernate.id.factory.IdentifierGeneratorFactory;
import org.hibernate.id.factory.spi.MutableIdentifierGeneratorFactory;
import org.hibernate.internal.util.collections.CollectionHelper;
@ -90,6 +91,7 @@ import org.hibernate.metamodel.spi.TypeContributor;
import org.hibernate.metamodel.spi.binding.AttributeBinding;
import org.hibernate.metamodel.spi.binding.BackRefAttributeBinding;
import org.hibernate.metamodel.spi.binding.EntityBinding;
import org.hibernate.metamodel.spi.binding.EntityIdentifier;
import org.hibernate.metamodel.spi.binding.FetchProfile;
import org.hibernate.metamodel.spi.binding.IdentifierGeneratorDefinition;
import org.hibernate.metamodel.spi.binding.IndexedPluralAttributeBinding;
@ -100,7 +102,11 @@ import org.hibernate.metamodel.spi.binding.PluralAttributeKeyBinding;
import org.hibernate.metamodel.spi.binding.RelationalValueBinding;
import org.hibernate.metamodel.spi.binding.SecondaryTable;
import org.hibernate.metamodel.spi.binding.TypeDefinition;
import org.hibernate.metamodel.spi.domain.Aggregate;
import org.hibernate.metamodel.spi.domain.BasicType;
import org.hibernate.metamodel.spi.domain.Entity;
import org.hibernate.metamodel.spi.domain.Hierarchical;
import org.hibernate.metamodel.spi.domain.MappedSuperclass;
import org.hibernate.metamodel.spi.domain.SingularAttribute;
import org.hibernate.metamodel.spi.domain.Type;
import org.hibernate.metamodel.spi.relational.Database;
@ -605,21 +611,97 @@ public class MetadataBuildingProcess {
return javaTypeDescriptorRepository.getType( javaTypeDescriptorRepository.buildName( qualifyClassName( name ) ) );
}
private final Map<JavaTypeDescriptor, Type> domainModelTypes = new HashMap<JavaTypeDescriptor, Type>();
@Override
public BasicType buildBasicDomainType(JavaTypeDescriptor typeDescriptor) {
final BasicType type = new BasicType( typeDescriptor.getName().toString(), typeDescriptor );
final Type old = domainModelTypes.put( typeDescriptor, type );
if ( old != null ) {
log.debugf( "Building basic domain type overrode existing entry: %s", old );
}
return type;
}
@Override
public MappedSuperclass buildMappedSuperclassDomainType(JavaTypeDescriptor typeDescriptor) {
return buildMappedSuperclassDomainType( typeDescriptor, null );
}
@Override
public MappedSuperclass buildMappedSuperclassDomainType(
JavaTypeDescriptor typeDescriptor,
Hierarchical superType) {
final MappedSuperclass type = new MappedSuperclass( typeDescriptor, superType );
final Type old = domainModelTypes.put( typeDescriptor, type );
if ( old != null ) {
log.debugf( "Building MappedSuperclass domain type overrode existing entry: %s", old );
}
return type;
}
@Override
public Aggregate buildComponentDomainType(JavaTypeDescriptor typeDescriptor) {
return buildComponentDomainType( typeDescriptor, null );
}
@Override
public Aggregate buildComponentDomainType(
JavaTypeDescriptor typeDescriptor
, Hierarchical superType) {
final Aggregate type = new Aggregate( typeDescriptor, superType );
final Type old = domainModelTypes.put( typeDescriptor, type );
if ( old != null ) {
log.debugf( "Building Aggregate domain type overrode existing entry: %s", old );
}
return type;
}
@Override
public Entity buildEntityDomainType(JavaTypeDescriptor typeDescriptor) {
return buildEntityDomainType( typeDescriptor, null );
}
@Override
public Entity buildEntityDomainType(
JavaTypeDescriptor typeDescriptor,
Hierarchical superType) {
final Entity type = new Entity( typeDescriptor, superType );
final Type old = domainModelTypes.put( typeDescriptor, type );
if ( old != null ) {
log.debugf( "Building Entity domain type overrode existing entry: %s", old );
}
return type;
}
@Override
public Type locateDomainType(JavaTypeDescriptor typeDescriptor) {
return domainModelTypes.get( typeDescriptor );
}
@Override
public Type locateOrBuildDomainType(JavaTypeDescriptor typeDescriptor, boolean isAggregate) {
Type type = domainModelTypes.get( typeDescriptor );
if ( type == null ) {
type = isAggregate
? buildComponentDomainType( typeDescriptor )
: buildBasicDomainType( typeDescriptor );
}
return type;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// BindingContext deprecated impls
@Override
public Type makeDomainType(String className) {
return new BasicType( className, typeDescriptor( className ) );
return buildBasicDomainType( typeDescriptor( className ) );
}
@Override
public Type makeDomainType(DotName typeName) {
return new BasicType(
typeName.toString(),
typeDescriptor( typeName.toString() )
);
return buildBasicDomainType( typeDescriptor( typeName.toString() ) );
}
}
@ -1143,9 +1225,10 @@ public class MetadataBuildingProcess {
if ( entityBinding == null ) {
throw new MappingException( "Entity binding not known: " + entityName );
}
return entityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding()
.getHibernateTypeDescriptor()
.getResolvedTypeMapping();
return entityBinding.getHierarchyDetails()
.getEntityIdentifier()
.getEntityIdentifierBinding()
.getHibernateType();
}
@Override
@ -1154,8 +1237,15 @@ public class MetadataBuildingProcess {
if ( entityBinding == null ) {
throw new MappingException( "Entity binding not known: " + entityName );
}
AttributeBinding idBinding = entityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding();
return idBinding == null ? null : idBinding.getAttribute().getName();
final EntityIdentifier idInfo = entityBinding.getHierarchyDetails().getEntityIdentifier();
if ( idInfo.getNature() == EntityIdentifierNature.NON_AGGREGATED_COMPOSITE ) {
return null;
}
final EntityIdentifier.AttributeBasedIdentifierBinding identifierBinding =
(EntityIdentifier.AttributeBasedIdentifierBinding) idInfo.getEntityIdentifierBinding();
return identifierBinding.getAttributeBinding().getAttribute().getName();
}
@Override

View File

@ -38,12 +38,14 @@ import org.hibernate.engine.ResultSetMappingDefinition;
import org.hibernate.engine.spi.FilterDefinition;
import org.hibernate.engine.spi.NamedQueryDefinition;
import org.hibernate.engine.spi.NamedSQLQueryDefinition;
import org.hibernate.id.EntityIdentifierNature;
import org.hibernate.id.factory.IdentifierGeneratorFactory;
import org.hibernate.metamodel.NamedStoredProcedureQueryDefinition;
import org.hibernate.metamodel.SessionFactoryBuilder;
import org.hibernate.metamodel.spi.MetadataImplementor;
import org.hibernate.metamodel.spi.binding.AttributeBinding;
import org.hibernate.metamodel.spi.binding.EntityBinding;
import org.hibernate.metamodel.spi.binding.EntityIdentifier;
import org.hibernate.metamodel.spi.binding.FetchProfile;
import org.hibernate.metamodel.spi.binding.IdentifierGeneratorDefinition;
import org.hibernate.metamodel.spi.binding.PluralAttributeBinding;
@ -300,9 +302,10 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
if ( entityBinding == null ) {
throw new MappingException( "Entity binding not known: " + entityName );
}
return entityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding()
.getHibernateTypeDescriptor()
.getResolvedTypeMapping();
return entityBinding.getHierarchyDetails()
.getEntityIdentifier()
.getEntityIdentifierBinding()
.getHibernateType();
}
@Override
@ -311,8 +314,15 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
if ( entityBinding == null ) {
throw new MappingException( "Entity binding not known: " + entityName );
}
AttributeBinding idBinding = entityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding();
return idBinding == null ? null : idBinding.getAttribute().getName();
final EntityIdentifier idInfo = entityBinding.getHierarchyDetails().getEntityIdentifier();
if ( idInfo.getNature() == EntityIdentifierNature.NON_AGGREGATED_COMPOSITE ) {
return null;
}
final EntityIdentifier.AttributeBasedIdentifierBinding identifierBinding =
(EntityIdentifier.AttributeBasedIdentifierBinding) idInfo.getEntityIdentifierBinding();
return identifierBinding.getAttributeBinding().getAttribute().getName();
}
@Override

View File

@ -0,0 +1,34 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2014, 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.metamodel.internal.binder;
import org.hibernate.metamodel.spi.binding.AttributeBinding;
/**
* @author Steve Ebersole
*/
public interface AttributeBindingListener {
public void attributeBound(AttributeBinding attribute);
public void attributeResolved(AttributeBinding attribute);
}

View File

@ -0,0 +1,30 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2014, 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.metamodel.internal.binder;
/**
* @author Steve Ebersole
*/
public interface AttributeBindingProducer {
}

View File

@ -0,0 +1,163 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2014, 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.metamodel.internal.binder;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.hibernate.metamodel.spi.binding.EmbeddableBinding;
import org.hibernate.metamodel.spi.binding.HibernateTypeDescriptor;
import org.hibernate.metamodel.spi.binding.HierarchyDetails;
import org.jboss.logging.Logger;
/**
* Acts as the central message hub for 2 types of events in the Binder ecosystem:<ul>
* <li>when an identifier is fully resolved</li>
* <li>when an attribute is fully resolved</li>
* </ul>
*
* @author Steve Ebersole
*/
public class BinderEventBus implements HibernateTypeDescriptor.ResolutionListener {
private static final Logger log = Logger.getLogger( BinderEventBus.class );
private List<IdentifierBindingListener> identifierBindingListeners;
private List<AttributeBindingListener> attributeBindingListeners;
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// IdentifierBindingListener
public void addIdentifierBindingListener(IdentifierBindingListener listener) {
log.debugf( "Adding IdentifierBindingListener : %s ", listener );
if ( identifierBindingListeners == null ) {
identifierBindingListeners = new ArrayList<IdentifierBindingListener>();
}
identifierBindingListeners.add( listener );
}
public void removeIdentifierBindingListener(IdentifierBindingListener listener) {
log.debugf( "Removing IdentifierBindingListener : %s ", listener );
if ( identifierBindingListeners == null ) {
throw new IllegalStateException( "No listeners defined" );
}
identifierBindingListeners.remove( listener );
}
private int identifierResolutionDepth = 0;
private List<IdentifierBindingListener> completedIdentifierBindingListeners;
public void fireIdentifierResolved(HierarchyDetails hierarchyDetails) {
final String entityName = hierarchyDetails.getRootEntityBinding().getEntityName();
log.debugf( "Starting 'identifier resolved' notifications : %s ", entityName );
if ( identifierBindingListeners == null ) {
return;
}
identifierResolutionDepth++;
try {
for ( IdentifierBindingListener identifierBindingListener : identifierBindingListeners ) {
log.tracef(
" - sending 'identifier resolved' notification [%s] to IdentifierBindingListener : %s",
entityName,
identifierBindingListener
);
final boolean done = identifierBindingListener.identifierResolved( hierarchyDetails );
if ( done ) {
if ( completedIdentifierBindingListeners == null ) {
completedIdentifierBindingListeners = new ArrayList<IdentifierBindingListener>();
}
completedIdentifierBindingListeners.add( identifierBindingListener );
}
}
}
finally {
identifierResolutionDepth--;
}
if ( identifierResolutionDepth == 0 ) {
if ( completedIdentifierBindingListeners != null
&& !completedIdentifierBindingListeners.isEmpty() ) {
identifierBindingListeners.removeAll( completedIdentifierBindingListeners );
}
}
}
public void finishUpIdentifiers() {
// todo : how to best allow all listeners to report any un-resolved state and still throw an excetpion here?
// for now, we throw an error if there are any remaining listeners
if ( identifierBindingListeners != null && !identifierBindingListeners.isEmpty() ) {
throw new IllegalStateException( "Could not resolve all identifiers" );
}
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// AttributeBindingListener
public void addAttributeBindingListener(AttributeBindingListener listener) {
log.debugf( "Adding AttributeBindingListener : %s ", listener );
if ( attributeBindingListeners == null ) {
attributeBindingListeners = new ArrayList<AttributeBindingListener>();
}
attributeBindingListeners.add( listener );
}
public void removeAttributeBindingListener(AttributeBindingListener listener) {
log.debugf( "Removing AttributeBindingListener : %s ", listener );
if ( attributeBindingListeners == null ) {
throw new IllegalStateException( "No listeners defined" );
}
attributeBindingListeners.remove( listener );
}
public void finishUpAttributes() {
// todo : how to best allow all listeners to report any un-resolved state and still throw an excetpion here?
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// HibernateTypeDescriptor.ResolutionListener
@Override
public void typeResolved(HibernateTypeDescriptor typeDescriptor) {
}
public void fireEmbeddableResolved(EmbeddableBinding binding) {
}
}

View File

@ -94,6 +94,16 @@ public class BinderLocalBindingContextSelectorImpl implements BinderLocalBinding
return parent().getLocalBindingContextSelector();
}
@Override
public BinderEventBus getEventBus() {
return parent().getEventBus();
}
@Override
public SourceIndex getSourceIndex() {
return parent().getSourceIndex();
}
@Override
public HibernateTypeHelper typeHelper() {
return parent().typeHelper();

View File

@ -39,45 +39,52 @@ import org.hibernate.metamodel.spi.binding.InheritanceType;
* EntitySource structure skipping MapperSuperclassSource types.
*
* @author Steve Ebersole
* @author Gail Badner
*/
public class BinderProcessHelper {
private final BinderRootContext context;
public static final BinderStepHierarchyStrategy NOOP_HIERARCHY_STRATEGY = new BinderStepHierarchyStrategy() {
@Override
public void visit(EntityHierarchySource source, BinderLocalBindingContext context) {
}
};
public static final BinderStepEntityStrategy NOOP_ENTITY_STRATEGY = new BinderStepEntityStrategy() {
@Override
public boolean applyToRootEntity() {
return false;
}
@Override
public void visit(EntitySource source, BinderLocalBindingContext context) {
}
};
public BinderProcessHelper(BinderRootContext context) {
this.context = context;
}
/**
* Public method to apply the "hierarchy strategy" to each hierarchy source
* object.
*
* @param hierarchySources The hierarchy sources
* @param hierarchyStrategy The strategy to call back into
*/
public void apply(
Collection<EntityHierarchySource> hierarchySources,
BinderStepHierarchyStrategy hierarchyStrategy) {
for ( EntityHierarchySource hierarchySource : hierarchySources ) {
apply( hierarchySource, hierarchyStrategy );
}
}
public void apply(EntityHierarchySource hierarchySource, BinderStepHierarchyStrategy hierarchyStrategy) {
apply( hierarchySource, hierarchyStrategy, NOOP_ENTITY_STRATEGY );
}
}
/**
* Public method to apply the "entity strategy" to each hierarchy source
* object.
*
* @param hierarchySources The hierarchy sources
* @param entityStrategy The strategy to call back into
*/
public void apply(
Collection<EntityHierarchySource> hierarchySources,
BinderStepEntityStrategy entityStrategy) {
for ( EntityHierarchySource hierarchySource: hierarchySources ) {
apply( hierarchySource, NOOP_HIERARCHY_STRATEGY, entityStrategy );
}
}
/**
* Public method to apply the "combined strategy" to each hierarchy source
* object.
*
* @param hierarchySources The hierarchy sources
* @param strategy The strategy to call back into
*/
public void apply(
Collection<EntityHierarchySource> hierarchySources,
BinderStepCombinedStrategy strategy) {
@ -86,22 +93,26 @@ public class BinderProcessHelper {
}
}
/**
* Public method to apply the "combined strategy" to a single hierarchy source
* object.
*
* @param hierarchySource The hierarchy source
* @param strategy The strategy to call back into
*/
public void apply(EntityHierarchySource hierarchySource, BinderStepCombinedStrategy strategy) {
apply( hierarchySource, strategy, strategy );
}
public void apply(
Collection<EntityHierarchySource> hierarchySources,
BinderStepEntityStrategy entityStrategy) {
for ( EntityHierarchySource hierarchySource: hierarchySources ) {
apply( hierarchySource, entityStrategy );
}
}
public void apply(EntityHierarchySource hierarchySource, BinderStepEntityStrategy strategy) {
apply( hierarchySource, NOOP_HIERARCHY_STRATEGY, strategy );
}
/**
* Public method to apply the "combined strategy" to each hierarchy source
* object.
*
* @param hierarchySources The hierarchy sources
* @param hierarchyStrategy The hierarchy strategy to call back into
* @param entityStrategy The entity strategy to call back into
*/
public void apply(
Collection<EntityHierarchySource> hierarchySources,
BinderStepHierarchyStrategy hierarchyStrategy,
@ -129,6 +140,10 @@ public class BinderProcessHelper {
if ( hierarchySource.getHierarchyInheritanceType() != InheritanceType.NO_INHERITANCE ) {
visitSubclasses( rootEntitySource, entityStrategy, localContext );
}
entityStrategy.afterAllEntitiesInHierarchy();
selector.unsetCurrent();
}
private void visitSubclasses(
@ -142,4 +157,32 @@ public class BinderProcessHelper {
visitSubclasses( subType, entityStrategy, localContext );
}
}
/**
* A no-op version of the BinderStepHierarchyStrategy contract
*/
public static final BinderStepHierarchyStrategy NOOP_HIERARCHY_STRATEGY = new BinderStepHierarchyStrategy() {
@Override
public void visit(EntityHierarchySource source, BinderLocalBindingContext context) {
}
};
/**
* A no-op version of the BinderStepEntityStrategy contract
*/
public static final BinderStepEntityStrategy NOOP_ENTITY_STRATEGY = new BinderStepEntityStrategy() {
@Override
public boolean applyToRootEntity() {
return false;
}
@Override
public void visit(EntitySource source, BinderLocalBindingContext context) {
}
@Override
public void afterAllEntitiesInHierarchy() {
}
};
}

View File

@ -55,10 +55,14 @@ public interface BinderRootContext extends BindingContext {
public BinderLocalBindingContextSelector getLocalBindingContextSelector();
public BinderEventBus getEventBus();
public SourceIndex getSourceIndex();
HibernateTypeHelper typeHelper();
RelationalIdentifierHelper relationalIdentifierHelper();
TableHelper tableHelper();
ForeignKeyHelper foreignKeyHelper();
RelationalValueBindingHelper relationalValueBindingHelper();
NaturalIdUniqueKeyHelper naturalIdUniqueKeyHelper();
}

View File

@ -37,6 +37,8 @@ import org.hibernate.metamodel.spi.binding.HierarchyDetails;
* @author Steve Ebersole
*/
public class BinderRootContextImpl extends BaseDelegatingBindingContext implements BinderRootContext {
private final SourceIndex sourceIndex;
private final BinderEventBus eventBus;
private Map<EntityHierarchySource,HierarchyDetails> hierarchySourceToBindingMap
= new HashMap<EntityHierarchySource, HierarchyDetails>();
private Map<EntitySource,EntityBinding> entitySourceToBindingMap
@ -51,8 +53,10 @@ public class BinderRootContextImpl extends BaseDelegatingBindingContext implemen
private final BinderLocalBindingContextSelector localBindingContextSelector;
public BinderRootContextImpl(BindingContext parent) {
public BinderRootContextImpl(BindingContext parent, SourceIndex sourceIndex, BinderEventBus eventBus) {
super( parent );
this.sourceIndex = sourceIndex;
this.eventBus = eventBus;
this.typeHelper = new HibernateTypeHelper( this );
this.relationalIdentifierHelper = new RelationalIdentifierHelper( this );
@ -63,6 +67,15 @@ public class BinderRootContextImpl extends BaseDelegatingBindingContext implemen
this.localBindingContextSelector = new BinderLocalBindingContextSelectorImpl( this );
}
public BinderEventBus getEventBus() {
return eventBus;
}
@Override
public SourceIndex getSourceIndex() {
return sourceIndex;
}
public void addMapping(EntityHierarchySource source, HierarchyDetails binding) {
hierarchySourceToBindingMap.put( source, binding );
}

View File

@ -39,4 +39,6 @@ public interface BinderStepEntityStrategy {
public boolean applyToRootEntity();
public void visit(EntitySource source, BinderLocalBindingContext context);
public void afterAllEntitiesInHierarchy();
}

View File

@ -28,6 +28,7 @@ import java.util.List;
import org.hibernate.AssertionFailure;
import org.hibernate.cfg.NotYetImplementedException;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.metamodel.internal.binder.ConstraintNamingStrategyHelper.ForeignKeyNamingStrategyHelper;
import org.hibernate.metamodel.source.spi.ForeignKeyContributingSource;
import org.hibernate.metamodel.spi.binding.AttributeBinding;
@ -99,15 +100,19 @@ public class ForeignKeyHelper {
public SingularAttributeBinding determineReferencedAttributeBinding(
final ForeignKeyContributingSource foreignKeyContributingSource,
final EntityBinding referencedEntityBinding) {
// todo : this is definitely the place that leads to problems with @Id @ManyToOne
final ForeignKeyContributingSource.JoinColumnResolutionDelegate resolutionDelegate =
foreignKeyContributingSource.getForeignKeyTargetColumnResolutionDelegate();
final ForeignKeyContributingSource.JoinColumnResolutionContext resolutionContext = resolutionDelegate == null ? null : new JoinColumnResolutionContextImpl(
referencedEntityBinding
);
if ( resolutionDelegate == null ) {
return referencedEntityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding();
return referencedEntityBinding.getHierarchyDetails().getEntityIdentifier()
.getEntityIdentifierBinding()
.getAttributeBinding();
}
final ForeignKeyContributingSource.JoinColumnResolutionContext resolutionContext =
new JoinColumnResolutionContextImpl( referencedEntityBinding );
final String explicitName = resolutionDelegate.getReferencedAttributeName();
final AttributeBinding referencedAttributeBinding;
if ( explicitName != null ) {
@ -256,33 +261,34 @@ public class ForeignKeyHelper {
String logicalTableName,
String logicalSchemaName,
String logicalCatalogName) {
if ( bindingContext().quoteIdentifiersInContext() && !org.hibernate
.internal
.util
.StringHelper
.isQuoted( logicalColumnName ) ) {
logicalColumnName = org.hibernate.internal.util.StringHelper.quote( logicalColumnName );
if ( bindingContext().quoteIdentifiersInContext()
&& !StringHelper.isQuoted( logicalColumnName ) ) {
logicalColumnName = StringHelper.quote( logicalColumnName );
}
return resolveTable( logicalTableName, logicalSchemaName, logicalCatalogName ).locateOrCreateColumn(
logicalColumnName
);
return resolveTable( logicalTableName, logicalSchemaName, logicalCatalogName )
.locateOrCreateColumn( logicalColumnName );
}
@Override
public TableSpecification resolveTable(String logicalTableName, String logicalSchemaName, String logicalCatalogName) {
Identifier tableIdentifier = helperContext.relationalIdentifierHelper().createIdentifier( logicalTableName );
if ( tableIdentifier == null ) {
// todo : why not just return referencedEntityBinding.getPrimaryTable() here?
// is it really valid to expect the table name to be missing, but the
// schema/catalog to be specified as an indication to look for a table
// with the same name as the primary table, but in the specified
// schema/catalog?
tableIdentifier = referencedEntityBinding.getPrimaryTable().getLogicalName();
}
Identifier catalogName = org.hibernate.internal.util.StringHelper.isNotEmpty( logicalCatalogName ) ?
Identifier.toIdentifier( logicalCatalogName )
final Identifier catalogName = StringHelper.isNotEmpty( logicalCatalogName )
? Identifier.toIdentifier( logicalCatalogName )
: referencedEntityBinding.getPrimaryTable().getSchema().getName().getCatalog();
Identifier schemaName = org.hibernate.internal.util.StringHelper.isNotEmpty( logicalCatalogName ) ?
Identifier.toIdentifier( logicalSchemaName )
final Identifier schemaName = StringHelper.isNotEmpty( logicalCatalogName )
? Identifier.toIdentifier( logicalSchemaName )
: referencedEntityBinding.getPrimaryTable().getSchema().getName().getSchema();
Schema schema = bindingContext().getMetadataCollector().getDatabase().getSchema( catalogName, schemaName );
final Schema schema = bindingContext().getMetadataCollector().getDatabase()
.getSchema( catalogName, schemaName );
return schema.locateTable( tableIdentifier );
}
@ -316,7 +322,10 @@ public class ForeignKeyHelper {
private SingularAttributeBinding resolveReferencedAttributeBinding(String attributeName) {
if ( attributeName == null ) {
return referencedEntityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding();
return referencedEntityBinding.getHierarchyDetails()
.getEntityIdentifier()
.getEntityIdentifierBinding()
.getAttributeBinding();
}
final AttributeBinding referencedAttributeBinding =
referencedEntityBinding.locateAttributeBindingByPath( attributeName, true );

View File

@ -36,6 +36,7 @@ import org.hibernate.AssertionFailure;
import org.hibernate.EntityMode;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.cfg.NotYetImplementedException;
import org.hibernate.id.EntityIdentifierNature;
import org.hibernate.internal.util.beans.BeanInfoHelper;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.metamodel.reflite.spi.ClassDescriptor;
@ -54,6 +55,7 @@ import org.hibernate.metamodel.source.spi.SingularAttributeSource;
import org.hibernate.metamodel.spi.InFlightMetadataCollector;
import org.hibernate.metamodel.spi.PluralAttributeElementNature;
import org.hibernate.metamodel.spi.PluralAttributeNature;
import org.hibernate.metamodel.spi.SingularAttributeNature;
import org.hibernate.metamodel.spi.binding.AttributeBinding;
import org.hibernate.metamodel.spi.binding.BasicAttributeBinding;
import org.hibernate.metamodel.spi.binding.EmbeddedAttributeBinding;
@ -84,6 +86,8 @@ import org.hibernate.type.TypeFactory;
import org.jboss.jandex.DotName;
import org.jboss.logging.Logger;
import static org.hibernate.metamodel.spi.binding.EntityIdentifier.IdClassMetadata;
/**
* Delegate for handling:<ol>
* <li>
@ -112,7 +116,7 @@ import org.jboss.logging.Logger;
* @author Gail Badner
* @author Brett Meyer
*/
class HibernateTypeHelper {
public class HibernateTypeHelper {
private static final Logger log = Logger.getLogger( HibernateTypeHelper.class );
/**
@ -414,6 +418,33 @@ class HibernateTypeHelper {
elementBinding.getRelationalValueBindings()
);
}
public void bindNonAggregatedCompositeIdentifierType(
ServiceRegistry serviceRegistry,
EntityIdentifier.NonAggregatedCompositeIdentifierBinding idBinding) {
final CompositeType idType;
final CompositeType virtualIdType = (CompositeType) idBinding.getHibernateType( serviceRegistry, typeFactory() );
final IdClassMetadata idClassMetadata = idBinding.getIdClassMetadata();
if ( idClassMetadata != null ) {
idType = (CompositeType) idClassMetadata.getHibernateType( serviceRegistry, typeFactory() );
}
else {
idType = virtualIdType;
}
idBinding.getAttributeBinding().getHibernateTypeDescriptor().setResolvedTypeMapping( idType );
bindHibernateTypeDescriptor(
idBinding.getAttributeBinding().getHibernateTypeDescriptor(),
idType.getReturnedClass().getName(),
null,
null,
idType
);
}
void bindNonAggregatedCompositeIdentifierType(
final ServiceRegistry serviceRegistry,
final EmbeddedAttributeBinding syntheticAttributeBinding,
@ -433,6 +464,7 @@ class HibernateTypeHelper {
resolvedType
);
}
void bindManyToManyAttributeType(
final PluralAttributeElementBindingManyToMany elementBinding,
final PluralAttributeElementSourceManyToMany elementSource,
@ -483,14 +515,17 @@ class HibernateTypeHelper {
final JavaTypeDescriptor defaultTypeDescriptor;
if ( attributeTypeDescriptor != null ) {
attributeBinding.getAttribute().resolveType(
makeDomainType( attributeTypeDescriptor.getName().toString() )
bindingContext().locateOrBuildDomainType(
attributeTypeDescriptor,
attributeSource.getSingularAttributeNature() == SingularAttributeNature.COMPOSITE
)
);
defaultTypeDescriptor = attributeTypeDescriptor;
}
else {
defaultTypeDescriptor = null;
}
//do our best to full fill hibernateTypeDescriptor
//do our best to fully fill hibernateTypeDescriptor
bindHibernateTypeDescriptor(
hibernateTypeDescriptor,
attributeSource.getTypeInformation(),
@ -969,10 +1004,14 @@ class HibernateTypeHelper {
*/
private static String getReferencedPropertyNameIfNotId(
final PluralAttributeBinding pluralAttributeBinding) {
EntityIdentifier entityIdentifier =
pluralAttributeBinding.getContainer().seekEntityBinding().getHierarchyDetails().getEntityIdentifier();
final String idAttributeName =
entityIdentifier.getAttributeBinding().getAttribute().getName();
EntityIdentifier entityIdentifier = pluralAttributeBinding.getContainer()
.seekEntityBinding()
.getHierarchyDetails()
.getEntityIdentifier();
final String idAttributeName = entityIdentifier.getEntityIdentifierBinding()
.getAttributeBinding()
.getAttribute()
.getName();
return pluralAttributeBinding.getReferencedPropertyName().equals( idAttributeName ) ?
null :
pluralAttributeBinding.getReferencedPropertyName();

View File

@ -0,0 +1,40 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2014, 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.metamodel.internal.binder;
import org.hibernate.metamodel.spi.binding.HierarchyDetails;
/**
* @author Steve Ebersole
*/
public interface IdentifierBindingListener {
/**
*
* @param hierarchyDetails
*
* @return {@code true} indicates that the listener should be removed; {@code false}
* indicates it should stay.
*/
public boolean identifierResolved(HierarchyDetails hierarchyDetails);
}

View File

@ -23,15 +23,22 @@
*/
package org.hibernate.metamodel.internal.binder;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import org.hibernate.AssertionFailure;
import org.hibernate.id.EntityIdentifierNature;
import org.hibernate.internal.CoreLogging;
import org.hibernate.metamodel.source.spi.AggregatedCompositeIdentifierSource;
import org.hibernate.metamodel.source.spi.AttributeSource;
@ -42,6 +49,7 @@ import org.hibernate.metamodel.source.spi.EntitySource;
import org.hibernate.metamodel.source.spi.IdentifiableTypeSource;
import org.hibernate.metamodel.source.spi.IdentifierSource;
import org.hibernate.metamodel.source.spi.IndexedPluralAttributeSource;
import org.hibernate.metamodel.source.spi.MapsIdSource;
import org.hibernate.metamodel.source.spi.NonAggregatedCompositeIdentifierSource;
import org.hibernate.metamodel.source.spi.PluralAttributeIndexSourceResolver;
import org.hibernate.metamodel.source.spi.PluralAttributeSource;
@ -49,6 +57,7 @@ import org.hibernate.metamodel.source.spi.SimpleIdentifierSource;
import org.hibernate.metamodel.source.spi.SingularAttributeSource;
import org.hibernate.metamodel.source.spi.ToOneAttributeSource;
import org.hibernate.metamodel.spi.AttributeRole;
import org.hibernate.metamodel.spi.BindingContext;
import org.hibernate.metamodel.spi.SingularAttributeNature;
import org.hibernate.metamodel.spi.binding.AttributeBinding;
import org.hibernate.metamodel.spi.binding.EntityBinding;
@ -57,24 +66,325 @@ import org.hibernate.metamodel.spi.relational.Column;
import org.jboss.logging.Logger;
/**
* Used to build indexes (x-refs) of various parts of an entity hierarchy and
* its attributes.
*
* Builds indexes (cross references) of the various parts of the source model
* for Binder access.
* <p/>
* The main contracts of SourceIndex are:<ul>
* <li>
* Indexing the entities in each hierarchy : {@link #indexHierarchy}
* </li>
* <li>
* Accessing all hierarchies:<ul>
* <li>{@link #getAllHierarchySources()}</li>
* <li>{@link #getIdDependencyOrderedHierarchySources()}</li>
* </ul>
* </li>
* <li>
* Accessing the attributes in various ways:<ul>
* <li>{@link #attributeSource(AttributeRole)}</li>
* <li>{@link #attributeSource(EntityBinding, AttributeBinding)}</li>
* <li>{@link #attributeSource(String, String)}</li>
* <li>{@link #getSingularAttributeSources}</li>
* <li>{@link #getPluralAttributeSources}</li>
* </ul>
* </li>
* <li>
* This notion of "resolving associations" at the source level. See
* {@link #resolveAssociationSources}. I really want to look at this
* and the point it is trying to solve.
* </li>
* </ul>
* @author Gail Badner
* @author Steve Ebersole
*/
public class SourceIndex {
private static final Logger log = CoreLogging.logger( SourceIndex.class );
private final Map<String, EntitySourceIndex> entitySourceIndexByEntityName = new HashMap<String, EntitySourceIndex>();
private final Map<AttributeRole, AttributeSource> attributeSourcesByKey = new HashMap<AttributeRole, AttributeSource>();
private final BindingContext context;
private final Map<AttributeRole, AttributeRole> mappedByAttributeKeysByOwnerAttributeKeys =
new HashMap<AttributeRole, AttributeRole>();
private final Map<String, EntityHierarchySource> entityHierarchiesByRootEntityName;
private final Map<String, EntitySourceIndex> entitySourceIndexByEntityName;
private final Map<AttributeRole, AttributeSource> attributeSourcesByKey;
private final Map<AttributeRole, AttributeRole> mappedByAttributeKeysByOwnerAttributeKeys;
public SourceIndex(BindingContext context) {
this.context = context;
this.entityHierarchiesByRootEntityName = new LinkedHashMap<String, EntityHierarchySource>();
this.entitySourceIndexByEntityName = new HashMap<String, EntitySourceIndex>();
this.attributeSourcesByKey = new HashMap<AttributeRole, AttributeSource>();
this.mappedByAttributeKeysByOwnerAttributeKeys = new HashMap<AttributeRole, AttributeRole>();
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Accessing hierarchies
/**
* Access to source information about an entity hierarchy by its root entity
* name
*
* @param rootEntityName The root entity name
*
* @return The hierarchy source information.
*/
public EntityHierarchySource getHierarchySourceByRootEntityName(String rootEntityName) {
return entityHierarchiesByRootEntityName.get( rootEntityName );
}
/**
* Obtains source information about all entity hierarchies.
* <p/>
* Note that a Collection is returned because no order is undefined;
* see {@link #getIdDependencyOrderedHierarchySources()}
*
* @return Source information about all entity hierarchies.
*/
public Collection<EntityHierarchySource> getAllHierarchySources() {
return entityHierarchiesByRootEntityName.values();
}
/**
* Used to hold the essential ordering information for a hierarchy
*/
public static class HierarchyByIdDependencyGraphNode {
private final String hierarchyKey;
private final EntityIdentifierNature nature;
private boolean containsUnknownTarget = false;
private final Set<String> targets;
public HierarchyByIdDependencyGraphNode(String hierarchyKey, EntityIdentifierNature nature) {
this.hierarchyKey = hierarchyKey;
this.nature = nature;
this.targets = new HashSet<String>();
}
public void toggleUnknownTarget() {
// todo : how to best utilize containsUnknownTarget in sorting?
containsUnknownTarget = true;
}
}
/**
* Comparator of HierarchyByIdDependencyGraphNode instances used to help
* in ordering the hierarchies.
*/
public static class HierarchyByIdDependencyGraphNodeComparator
implements Comparator<HierarchyByIdDependencyGraphNode> {
@Override
public int compare(
HierarchyByIdDependencyGraphNode o1,
HierarchyByIdDependencyGraphNode o2) {
if ( o1.hierarchyKey.equals( o2.hierarchyKey ) ) {
return 0;
}
final boolean o1HasDeps = !o1.targets.isEmpty();
final boolean o2HasDeps = !o2.targets.isEmpty();
if ( !o1HasDeps ) {
// o1 has no id dependencies,
if ( o2HasDeps ) {
// but o2 does: o1 comes BEFORE o2
return -1;
}
else {
// neither has id dependencies
return o1.nature == EntityIdentifierNature.SIMPLE
? -1
: 1;
}
}
// to get here, we know the o1 hierarchy has one or more id dependencies
if ( !o2HasDeps ) {
// but, o2 did not : 01 comes AFTER o2
return 1;
}
if ( o2.targets.contains( o1.hierarchyKey ) ) {
// o2 "depends on" o1 : o1 needs to come BEFORE 02
return -1;
}
else {
// otherwise : put o1 AFTER o2
return 1;
}
}
}
/**
* Obtains source information about all entity hierarchies. Attempts a best
* effort to order the hierarchy according to identifier dependencies.
*
* @return Source information about all entity hierarchies, ordered.
*
* @return The ordered hierarchy source information.
*/
public List<EntityHierarchySource> getIdDependencyOrderedHierarchySources() {
// it is important that this be called only after all hierarchies have been
// applied and indexed!! Duh :)
//
// Also, this is likely an expensive operation and it is best it be
// called just once (like while processing identifiers).
final TreeSet<HierarchyByIdDependencyGraphNode> nodeSet =
new TreeSet<HierarchyByIdDependencyGraphNode>( new HierarchyByIdDependencyGraphNodeComparator() );
for ( Map.Entry<String, EntityHierarchySource> hierarchySourceEntry :
entityHierarchiesByRootEntityName.entrySet() ) {
final HierarchyByIdDependencyGraphNode node = new HierarchyByIdDependencyGraphNode(
hierarchySourceEntry.getKey(),
hierarchySourceEntry.getValue().getIdentifierSource().getNature()
);
collectRootEntityNamesOnWhichIdDepends( hierarchySourceEntry.getValue(), node );
nodeSet.add( node );
}
final List<EntityHierarchySource> rtn = new ArrayList<EntityHierarchySource>();
for ( HierarchyByIdDependencyGraphNode node : nodeSet ) {
rtn.add( entityHierarchiesByRootEntityName.get( node.hierarchyKey ) );
}
return rtn;
}
private void collectRootEntityNamesOnWhichIdDepends(
EntityHierarchySource entityHierarchySource,
HierarchyByIdDependencyGraphNode node) {
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// First, identifier attributes (key-many-to-one)
//
// id attribute(s) can only be basic or to-one types.. assume the source producer
// handle at least that properly
if ( node.nature == EntityIdentifierNature.SIMPLE ) {
final SimpleIdentifierSource identifierSource = (SimpleIdentifierSource) entityHierarchySource.getIdentifierSource();
if ( identifierSource.getIdentifierAttributeSource().getSingularAttributeNature() == SingularAttributeNature.BASIC ) {
return;
}
addDependency( node, (ToOneAttributeSource) identifierSource.getIdentifierAttributeSource() );
}
else if ( node.nature == EntityIdentifierNature.AGGREGATED_COMPOSITE ) {
final AggregatedCompositeIdentifierSource identifierSource =
(AggregatedCompositeIdentifierSource) entityHierarchySource.getIdentifierSource();
for ( AttributeSource attributeSource : identifierSource.getIdentifierAttributeSource()
.getEmbeddableSource()
.attributeSources() ) {
final SingularAttributeSource sAttSource = (SingularAttributeSource) attributeSource;
if ( sAttSource.getSingularAttributeNature() == SingularAttributeNature.BASIC ) {
continue;
}
addDependency( node, (ToOneAttributeSource) sAttSource );
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Then @MapsId + to-one
//
// We make a natural assumption that persistent subclasses cannot (re)define @MapsId...
for ( MapsIdSource mapsIdSource : identifierSource.getMapsIdSources() ) {
final ToOneAttributeSource toOneAttributeSource = mapsIdSource.getAssociationAttributeSource();
addDependency( node, toOneAttributeSource );
}
}
else if ( node.nature == EntityIdentifierNature.NON_AGGREGATED_COMPOSITE ) {
final NonAggregatedCompositeIdentifierSource identifierSource =
(NonAggregatedCompositeIdentifierSource) entityHierarchySource.getIdentifierSource();
for ( SingularAttributeSource attributeSource : identifierSource.getAttributeSourcesMakingUpIdentifier() ) {
if ( attributeSource.getSingularAttributeNature() == SingularAttributeNature.BASIC ) {
continue;
}
addDependency( node, (ToOneAttributeSource) attributeSource );
}
}
}
private void addDependency(
HierarchyByIdDependencyGraphNode node,
ToOneAttributeSource attributeSource) {
final String entityName = attributeSource.getReferencedEntityName();
if ( entityName == null ) {
// best effort.. just return
node.toggleUnknownTarget();
return;
}
final String rootEntityName = entitySourceIndexByEntityName.get( entityName )
.entitySource
.getHierarchy()
.getRoot()
.getEntityName();
node.targets.add( rootEntityName );
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Accessing attributes
public Map<AttributeRole, SingularAttributeSource> getSingularAttributeSources(
String entityName,
boolean isMappedBy,
SingularAttributeNature singularAttributeNature) {
final EntitySourceIndex entitySourceIndex = entitySourceIndexByEntityName.get( entityName );
return entitySourceIndex.getSingularAttributeSources( isMappedBy, singularAttributeNature );
}
public Map<AttributeRole, PluralAttributeSource> getPluralAttributeSources(
String entityName,
boolean isInverse) {
final EntitySourceIndex entitySourceIndex = entitySourceIndexByEntityName.get( entityName );
return entitySourceIndex.getPluralAttributeSources( isInverse );
}
public AttributeSource attributeSource(final AttributeRole attributeRole) {
return attributeSourcesByKey.get( attributeRole );
}
public AttributeSource attributeSource(String entityName, String attributePath) {
final AttributeRole base = new AttributeRole( entityName );
AttributeRole role;
if ( attributePath.contains( "." ) ) {
role = base;
for ( String part : attributePath.split( "\\." ) ) {
role = role.append( part );
}
}
else {
role = base.append( attributePath );
}
return attributeSourcesByKey.get( role );
}
public AttributeSource attributeSource(EntityBinding entityBinding, AttributeBinding attributeBinding) {
return attributeSourcesByKey.get( attributeBinding.getAttributeRole() );
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Resolving associations
public void resolveAssociationSources(EntitySource source, BinderLocalBindingContext context) {
final EntityBinding binding = context.locateBinding( source );
entitySourceIndexByEntityName.get( binding.getEntityName() ).resolveAttributeSources( context );
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Indexing
public void indexHierarchy(EntityHierarchySource hierarchy) {
final String hierarchyKey = hierarchy.getRoot().getEntityName();
entityHierarchiesByRootEntityName.put( hierarchyKey, hierarchy );
final HierarchyInfo hierarchyInfo = new HierarchyInfo( hierarchyKey, hierarchy );
indexIdentifierAttributeSources( hierarchy, hierarchyInfo );
@ -92,6 +402,14 @@ public class SourceIndex {
}
private void indexEntitySource(EntitySource entitySource, HierarchyInfo hierarchyInfo) {
// todo : consider resolving JavaTypeDescriptor or even o.h.metamodel.spi.domain model as as we index the sources.\
//
// This is especially useful for associations and components (mainly in HBM
// uses, as in Annotation uses the JavaTypeDescriptor is already known).
//
// See org.hibernate.metamodel.source.spi.JavaTypeDescriptorResolvable
final String entityName = entitySource.getEntityName();
EntitySourceIndex entitySourceIndex = new EntitySourceIndex( this, hierarchyInfo, entitySource );
entitySourceIndexByEntityName.put( entityName, entitySourceIndex );
@ -139,7 +457,7 @@ public class SourceIndex {
attributeSourcesByKey.put( attributeSource.getAttributeRole(), attributeSource );
if ( attributeSource.isSingular() ) {
attributeIndexingTarget.indexSingularAttributeSource( (SingularAttributeSource) attributeSource, isInIdentifier );
attributeIndexingTarget.indexSingularAttributeSource( (SingularAttributeSource) attributeSource );
}
else {
attributeIndexingTarget.indexPluralAttributeSource( (PluralAttributeSource) attributeSource );
@ -163,72 +481,85 @@ public class SourceIndex {
}
public void resolveAssociationSources(EntitySource source, BinderLocalBindingContext context) {
final EntityBinding binding = context.locateBinding( source );
entitySourceIndexByEntityName.get( binding.getEntityName() ).resolveAttributeSources( context );
}
public Map<AttributeRole, SingularAttributeSource> getSingularAttributeSources(
String entityName,
boolean isMappedBy,
SingularAttributeNature singularAttributeNature) {
final EntitySourceIndex entitySourceIndex = entitySourceIndexByEntityName.get( entityName );
return entitySourceIndex.getSingularAttributeSources( isMappedBy, singularAttributeNature );
}
public Map<AttributeRole, PluralAttributeSource> getPluralAttributeSources(
String entityName,
boolean isInverse) {
final EntitySourceIndex entitySourceIndex = entitySourceIndexByEntityName.get( entityName );
return entitySourceIndex.getPluralAttributeSources( isInverse );
}
public AttributeSource attributeSource(final AttributeRole attributeRole) {
return attributeSourcesByKey.get( attributeRole );
}
public AttributeSource attributeSource(String entityName, String attributePath) {
final AttributeRole base = new AttributeRole( entityName );
AttributeRole role;
if ( attributePath.contains( "." ) ) {
role = base;
for ( String part : attributePath.split( "\\." ) ) {
role = role.append( part );
}
}
else {
role = base.append( attributePath );
}
return attributeSourcesByKey.get( role );
}
public AttributeSource attributeSource(EntityBinding entityBinding, AttributeBinding attributeBinding) {
return attributeSourcesByKey.get( attributeBinding.getAttributeRole() );
}
/**
* Interface to target where attributes should be indexed. Mainly this is
* used to collect id attributes into one pool, and non-id attributes into another.
*/
private static interface AttributeIndexingTarget {
public void indexSingularAttributeSource(SingularAttributeSource attributeSource, boolean isInIdentifier);
public void indexSingularAttributeSource(SingularAttributeSource attributeSource);
public void indexPluralAttributeSource(PluralAttributeSource attributeSource);
}
private static abstract class AbstractAttributeIndexingTarget implements AttributeIndexingTarget {
private final Map<AttributeRole, SingularAttributeSource> unresolvedSingularAttributeSourcesByKey
= new HashMap<AttributeRole, SingularAttributeSource>();
private static class HierarchyInfo implements AttributeIndexingTarget {
private final String hierarchyKey;
private final EntityHierarchySource hierarchySource;
private final Map<SingularAttributeNature, Map<AttributeRole, SingularAttributeSource>> identifierAttributeSourcesByNature
= new EnumMap<SingularAttributeNature, Map<AttributeRole, SingularAttributeSource>>( SingularAttributeNature.class );
private final Map<SingularAttributeNature, Map<AttributeRole, SingularAttributeSource>> nonMappedBySingularAttributeSourcesByNature
private HierarchyInfo(String hierarchyKey, EntityHierarchySource hierarchySource) {
this.hierarchyKey = hierarchyKey;
this.hierarchySource = hierarchySource;
}
public Map<AttributeRole, SingularAttributeSource> getSingularAttributeSources(
SingularAttributeNature singularAttributeNature) {
return identifierAttributeSourcesByNature.get( singularAttributeNature );
}
@Override
public void indexSingularAttributeSource(SingularAttributeSource attributeSource) {
if ( attributeSource.getSingularAttributeNature() == null ) {
( (ToOneAttributeSource) attributeSource ).resolveToOneAttributeSourceNatureAsPartOfIdentifier();
if ( attributeSource.getSingularAttributeNature() == null ) {
throw new IllegalStateException(
"Could not determine to-one association nature for [" +
attributeSource.getAttributeRole().getFullPath() + "]"
);
}
}
if ( ToOneAttributeSource.class.isInstance( attributeSource )
&& ToOneAttributeSource.class.cast( attributeSource ).isMappedBy() ) {
throw new IllegalStateException(
"Association attribute (to-one) that is part of an identifier " +
"cannot be mapped as mappedBy : " +
attributeSource.getAttributeRole().getFullPath()
);
}
Map<AttributeRole, SingularAttributeSource> natureMap =
identifierAttributeSourcesByNature.get( attributeSource.getSingularAttributeNature() );
if ( natureMap == null ) {
natureMap = new HashMap<AttributeRole, SingularAttributeSource>();
identifierAttributeSourcesByNature.put( attributeSource.getSingularAttributeNature(), natureMap );
}
natureMap.put( attributeSource.getAttributeRole(), attributeSource );
}
@Override
public void indexPluralAttributeSource(PluralAttributeSource attributeSource) {
throw new AssertionFailure(
String.format(
"Identifiers should not contain plural attributes: [%s]",
attributeSource.getAttributeRole().getFullPath()
)
);
}
}
private static class EntitySourceIndex implements AttributeIndexingTarget {
private final SourceIndex sourceIndex;
private final HierarchyInfo hierarchyInfo;
private final EntitySource entitySource;
private final Map<AttributeRole, SingularAttributeSource> unresolvedSingularAttributeSourcesByKey
= new HashMap<AttributeRole, SingularAttributeSource>();
private final EnumMap<SingularAttributeNature, Map<AttributeRole, SingularAttributeSource>> nonMappedBySingularAttributeSourcesByNature
= new EnumMap<SingularAttributeNature, Map<AttributeRole, SingularAttributeSource>>( SingularAttributeNature.class );
private final Map<SingularAttributeNature, Map<AttributeRole, SingularAttributeSource>> mappedBySingularAttributeSourcesByNature
private final EnumMap<SingularAttributeNature, Map<AttributeRole, SingularAttributeSource>> mappedBySingularAttributeSourcesByNature
= new EnumMap<SingularAttributeNature, Map<AttributeRole, SingularAttributeSource>>( SingularAttributeNature.class );
// TODO: the following should not need to be LinkedHashMap, but it appears that some unit tests
@ -239,18 +570,24 @@ public class SourceIndex {
private final Map<AttributeRole, PluralAttributeSource> inversePluralAttributeSourcesByKey =
new LinkedHashMap<AttributeRole, PluralAttributeSource>();
private EntitySourceIndex(
final SourceIndex sourceIndex,
final HierarchyInfo hierarchyInfo,
final EntitySource entitySource) {
this.sourceIndex = sourceIndex;
this.hierarchyInfo = hierarchyInfo;
this.entitySource = entitySource;
}
@Override
public void indexSingularAttributeSource(SingularAttributeSource attributeSource, boolean isInIdentifier) {
public void indexSingularAttributeSource(SingularAttributeSource attributeSource) {
if ( attributeSource.getSingularAttributeNature() == null ) {
unresolvedSingularAttributeSourcesByKey.put( attributeSource.getAttributeRole(), attributeSource );
return;
}
final Map<SingularAttributeNature, Map<AttributeRole, SingularAttributeSource>> map;
if ( isInIdentifier ) {
map = identifierAttributeSourcesByNature;
}
else if ( ToOneAttributeSource.class.isInstance( attributeSource ) &&
final EnumMap<SingularAttributeNature, Map<AttributeRole, SingularAttributeSource>> map;
if ( ToOneAttributeSource.class.isInstance( attributeSource ) &&
ToOneAttributeSource.class.cast( attributeSource ).isMappedBy() ) {
map = mappedBySingularAttributeSourcesByNature;
}
@ -261,9 +598,9 @@ public class SourceIndex {
indexSingularAttributeSource( attributeSource, map );
}
private static void indexSingularAttributeSource(
protected static void indexSingularAttributeSource(
SingularAttributeSource attributeSource,
Map<SingularAttributeNature, Map<AttributeRole, SingularAttributeSource>> map) {
EnumMap<SingularAttributeNature, Map<AttributeRole, SingularAttributeSource>> map) {
final Map<AttributeRole, SingularAttributeSource> singularAttributeSources;
if ( map.containsKey( attributeSource.getSingularAttributeNature() ) ) {
singularAttributeSources = map.get( attributeSource.getSingularAttributeNature() );
@ -272,7 +609,13 @@ public class SourceIndex {
singularAttributeSources = new LinkedHashMap<AttributeRole,SingularAttributeSource>();
map.put( attributeSource.getSingularAttributeNature(), singularAttributeSources );
}
if ( singularAttributeSources.put( attributeSource.getAttributeRole(), attributeSource ) != null ) {
indexSingularAttributeSource( attributeSource, singularAttributeSources );
}
protected static void indexSingularAttributeSource(
SingularAttributeSource attributeSource,
Map<AttributeRole, SingularAttributeSource> singularAttributeSourceMap) {
if ( singularAttributeSourceMap.put( attributeSource.getAttributeRole(), attributeSource ) != null ) {
throw new AssertionFailure(
String.format(
Locale.ENGLISH,
@ -377,7 +720,7 @@ public class SourceIndex {
);
}
ToOneAttributeSource toOneAttributeSource = (ToOneAttributeSource) attributeSource;
toOneAttributeSource.resolveToOneAttributeSource( sourceResolutionContext );
toOneAttributeSource.resolveToOneAttributeSourceNature( sourceResolutionContext );
if ( toOneAttributeSource.getSingularAttributeNature() == null ) {
throw new AssertionFailure(
String.format(
@ -396,84 +739,6 @@ public class SourceIndex {
}
}
protected abstract AttributeSourceResolutionContext makeAttributeSourceResolutionContext(BinderLocalBindingContext context);
}
private static class HierarchyInfo extends AbstractAttributeIndexingTarget {
private final String hierarchyKey;
private final EntityHierarchySource hierarchySource;
private HierarchyInfo(String hierarchyKey, EntityHierarchySource hierarchySource) {
this.hierarchyKey = hierarchyKey;
this.hierarchySource = hierarchySource;
}
@Override
public void indexPluralAttributeSource(PluralAttributeSource attributeSource) {
throw new AssertionFailure(
String.format(
"Identifiers should not contain plural attributes: [%s]",
attributeSource.getAttributeRole().getFullPath()
)
);
}
@Override
public Map<AttributeRole, PluralAttributeSource> getPluralAttributeSources(boolean isInverse) {
return Collections.emptyMap();
}
@Override
protected AttributeSourceResolutionContext makeAttributeSourceResolutionContext(final BinderLocalBindingContext context) {
return new AttributeSourceResolutionContext() {
@Override
public IdentifierSource resolveIdentifierSource(String entityName) {
return hierarchySource.getIdentifierSource();
}
@Override
public AttributeSource resolveAttributeSource(String entityName, String attributeName) {
throw new UnsupportedOperationException( "Whaaa!?!" );
}
@Override
public List<Column> resolveIdentifierColumns() {
return context.locateBinding( hierarchySource ).getRootEntityBinding().getPrimaryTable().getPrimaryKey().getColumns();
}
};
}
}
private static class EntitySourceIndex extends AbstractAttributeIndexingTarget {
private final SourceIndex sourceIndex;
private final HierarchyInfo hierarchyInfo;
private final EntitySource entitySource;
private EntitySourceIndex(
final SourceIndex sourceIndex,
final HierarchyInfo hierarchyInfo,
final EntitySource entitySource) {
this.sourceIndex = sourceIndex;
this.hierarchyInfo = hierarchyInfo;
this.entitySource = entitySource;
}
@Override
public Map<AttributeRole, SingularAttributeSource> getSingularAttributeSources(
boolean isMappedBy,
SingularAttributeNature singularAttributeNature) {
Map<AttributeRole, SingularAttributeSource> values = hierarchyInfo.getSingularAttributeSources(
isMappedBy,
singularAttributeNature
);
if ( values == null || values.isEmpty() ) {
values = super.getSingularAttributeSources( isMappedBy, singularAttributeNature );
}
return values;
}
@Override
protected AttributeSourceResolutionContext makeAttributeSourceResolutionContext(
final BinderLocalBindingContext context) {
return new AttributeSourceResolutionContext() {

View File

@ -26,60 +26,23 @@ package org.hibernate.metamodel.source.internal.annotations;
import java.util.Collection;
import java.util.Collections;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames;
import org.hibernate.metamodel.source.spi.IdentifierSource;
import org.hibernate.metamodel.source.spi.ToolingHintSource;
import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.AnnotationValue;
/**
* @author Steve Ebersole
*/
public abstract class AbstractIdentifierSource implements IdentifierSource {
private final RootEntitySourceImpl rootEntitySource;
private final Class lookupIdClass;
protected AbstractIdentifierSource(RootEntitySourceImpl rootEntitySource) {
this.rootEntitySource = rootEntitySource;
this.lookupIdClass = resolveLookupIdClass( rootEntitySource );
}
private Class resolveLookupIdClass(RootEntitySourceImpl rootEntitySource) {
final AnnotationInstance idClassAnnotation = rootEntitySource.getEntityClass()
.getJavaTypeDescriptor()
.findTypeAnnotation( JPADotNames.ID_CLASS );
if ( idClassAnnotation == null ) {
return null;
}
final AnnotationValue idClassValue = idClassAnnotation.value();
if ( idClassValue == null ) {
return null;
}
final String idClassName = StringHelper.nullIfEmpty( idClassValue.asString() );
if ( idClassName == null ) {
return null;
}
return rootEntitySource.getLocalBindingContext().getServiceRegistry()
.getService( ClassLoaderService.class )
.classForName( idClassName );
}
protected RootEntitySourceImpl rootEntitySource() {
return rootEntitySource;
}
@Override
public Class getLookupIdClass() {
return lookupIdClass;
}
@Override
public Collection<? extends ToolingHintSource> getToolingHintSources() {
return Collections.emptySet();

View File

@ -18,9 +18,6 @@ import org.hibernate.metamodel.spi.AttributeRole;
import org.hibernate.metamodel.spi.SingularAttributeNature;
import org.hibernate.type.ForeignKeyDirection;
import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.AnnotationValue;
public abstract class AbstractToOneAttributeSourceImpl extends SingularAttributeSourceImpl implements ToOneAttributeSource{
private final SingularAssociationAttribute associationAttribute;
private final Set<CascadeStyle> unifiedCascadeStyles;
@ -28,14 +25,10 @@ public abstract class AbstractToOneAttributeSourceImpl extends SingularAttribute
private SingularAttributeNature singularAttributeNature;
private final Set<MappedByAssociationSource> ownedAssociationSources = new HashSet<MappedByAssociationSource>();
private final MapsIdSourceImpl mapsIdSource;
public AbstractToOneAttributeSourceImpl(SingularAssociationAttribute associationAttribute) {
super( associationAttribute );
this.associationAttribute = associationAttribute;
this.unifiedCascadeStyles = determineCascadeStyles( associationAttribute );
this.mapsIdSource = MapsIdSourceImpl.interpret( associationAttribute.getMapsIdAnnotation() );
}
private static Set<CascadeStyle> determineCascadeStyles(SingularAssociationAttribute associationAttribute) {
@ -153,39 +146,4 @@ public abstract class AbstractToOneAttributeSourceImpl extends SingularAttribute
public AttributeRole getAttributeRole() {
return associationAttribute.getRole();
}
@Override
public MapsIdSource getMapsIdSource() {
return mapsIdSource;
}
private static class MapsIdSourceImpl implements MapsIdSource {
private final boolean present;
private final String name;
public static MapsIdSourceImpl interpret(AnnotationInstance mapsIdAnnotation) {
if ( mapsIdAnnotation == null ) {
return new MapsIdSourceImpl( false, null );
}
final AnnotationValue value = mapsIdAnnotation.value();
final String name = value == null ? null : value.asString();
return new MapsIdSourceImpl( true, name );
}
private MapsIdSourceImpl(boolean present, String name) {
this.present = present;
this.name = name;
}
@Override
public boolean isDefined() {
return present;
}
@Override
public String getLookupClassAttributeName() {
return name;
}
}
}

View File

@ -25,10 +25,12 @@ package org.hibernate.metamodel.source.internal.annotations;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.hibernate.id.EntityIdentifierNature;
import org.hibernate.metamodel.source.spi.AggregatedCompositeIdentifierSource;
import org.hibernate.metamodel.source.spi.EmbeddedAttributeSource;
import org.hibernate.metamodel.source.spi.MapsIdSource;
import org.hibernate.metamodel.source.spi.ToolingHintSource;
import org.hibernate.metamodel.spi.binding.IdentifierGeneratorDefinition;
@ -42,12 +44,15 @@ class AggregatedCompositeIdentifierSourceImpl
implements AggregatedCompositeIdentifierSource {
private final EmbeddedAttributeSourceImpl componentAttributeSource;
private final List<MapsIdSource> mapsIdSourceList;
public AggregatedCompositeIdentifierSourceImpl(
RootEntitySourceImpl rootEntitySource,
EmbeddedAttributeSourceImpl componentAttributeSource) {
EmbeddedAttributeSourceImpl componentAttributeSource,
List<MapsIdSource> mapsIdSourceList) {
super( rootEntitySource );
this.componentAttributeSource = componentAttributeSource;
this.mapsIdSourceList = mapsIdSourceList;
}
@Override
@ -55,6 +60,11 @@ class AggregatedCompositeIdentifierSourceImpl
return componentAttributeSource;
}
@Override
public List<MapsIdSource> getMapsIdSources() {
return mapsIdSourceList;
}
@Override
public IdentifierGeneratorDefinition getIndividualAttributeIdGenerator(String identifierAttributeName) {
// for now, return null. this is that stupid specj bs
@ -77,11 +87,6 @@ class AggregatedCompositeIdentifierSourceImpl
return null;
}
@Override
public String getIdClassPropertyAccessorName() {
return componentAttributeSource.getPropertyAccessorName();
}
@Override
public Collection<? extends ToolingHintSource> getToolingHintSources() {
// not relevant for annotations

View File

@ -131,7 +131,8 @@ public class EntityHierarchySourceImpl implements EntityHierarchySource {
case AGGREGATED: {
return new AggregatedCompositeIdentifierSourceImpl(
rootSource,
(EmbeddedAttributeSourceImpl) rootSource.getIdentifierAttributes().get( 0 )
(EmbeddedAttributeSourceImpl) rootSource.getIdentifierAttributes().get( 0 ),
rootSource.getMapsIdSources()
);
}
case NON_AGGREGATED: {

View File

@ -224,7 +224,7 @@ public abstract class EntitySourceImpl extends IdentifiableTypeSourceAdapter imp
}
@Override
public LocalBindingContext getLocalBindingContext() {
public EntityBindingContext getLocalBindingContext() {
return getEntityClass().getLocalBindingContext();
}

View File

@ -23,55 +23,68 @@
*/
package org.hibernate.metamodel.source.internal.annotations;
import java.util.Collections;
import java.util.Map;
import org.hibernate.internal.util.ValueHolder;
import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor;
import org.hibernate.metamodel.source.internal.annotations.attribute.PersistentAttribute;
import org.hibernate.metamodel.source.spi.HibernateTypeSource;
import org.hibernate.metamodel.source.spi.JavaTypeDescriptorResolvable;
/**
* @author Hardy Ferentschik
* @author Strong Liu
* @author Steve Ebersole
*/
public class HibernateTypeSourceImpl implements HibernateTypeSource {
private final ValueHolder<String> nameHolder;
private final ValueHolder<Map<String, String>> parameterHolder;
private final JavaTypeDescriptor javaType;
public class HibernateTypeSourceImpl implements HibernateTypeSource, JavaTypeDescriptorResolvable {
private final String name;
private final Map<String, String> parameters;
private JavaTypeDescriptor javaTypeDescriptor;
public HibernateTypeSourceImpl(final PersistentAttribute attribute) {
this.nameHolder = new ValueHolder<String>(
new ValueHolder.DeferredInitializer<String>() {
@Override
public String initialize() {
return attribute.getHibernateTypeResolver().getExplicitHibernateTypeName();
public HibernateTypeSourceImpl(PersistentAttribute attribute) {
this.name = attribute.getHibernateTypeResolver().getExplicitHibernateTypeName();
this.parameters = attribute.getHibernateTypeResolver().getExplicitHibernateTypeParameters();
this.javaTypeDescriptor = attribute.getBackingMember().getType().getErasedType();
}
public HibernateTypeSourceImpl(String name, Map<String, String> parameters, JavaTypeDescriptor javaTypeDescriptor) {
this.name = name;
this.parameters = parameters;
this.javaTypeDescriptor = javaTypeDescriptor;
}
);
this.parameterHolder = new ValueHolder<Map<String, String>>(
new ValueHolder.DeferredInitializer<Map<String, String>>() {
@Override
public Map<String, String> initialize() {
return attribute.getHibernateTypeResolver().getExplicitHibernateTypeParameters();
public HibernateTypeSourceImpl() {
this( (String) null );
}
}
);
this.javaType = attribute.getBackingMember().getType().getErasedType();
public HibernateTypeSourceImpl(String name) {
this.name = name;
this.parameters = Collections.emptyMap();
}
@Override
public String getName() {
return nameHolder.getValue();
return name;
}
@Override
public Map<String, String> getParameters() {
return parameterHolder.getValue();
return parameters;
}
@Override
public JavaTypeDescriptor getJavaType() {
return javaType;
return javaTypeDescriptor;
}
@Override
public void resolveJavaTypeDescriptor(JavaTypeDescriptor descriptor) {
if ( this.javaTypeDescriptor != null ) {
if ( this.javaTypeDescriptor != descriptor ) {
throw new IllegalStateException( "Attempt to resolve an already resolved JavaTypeDescriptor" );
}
}
this.javaTypeDescriptor = descriptor;
}
}

View File

@ -27,17 +27,29 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.id.EntityIdentifierNature;
import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor;
import org.hibernate.metamodel.reflite.spi.MemberDescriptor;
import org.hibernate.metamodel.source.internal.AttributeConversionInfo;
import org.hibernate.metamodel.source.internal.annotations.attribute.AssociationOverride;
import org.hibernate.metamodel.source.internal.annotations.attribute.AttributeOverride;
import org.hibernate.metamodel.source.internal.annotations.attribute.EmbeddedContainer;
import org.hibernate.metamodel.source.internal.annotations.entity.EmbeddableTypeMetadata;
import org.hibernate.metamodel.source.internal.annotations.entity.EntityBindingContext;
import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames;
import org.hibernate.metamodel.source.spi.AttributeSource;
import org.hibernate.metamodel.source.spi.EmbeddableSource;
import org.hibernate.metamodel.source.spi.NonAggregatedCompositeIdentifierSource;
import org.hibernate.metamodel.source.spi.SingularAttributeSource;
import org.hibernate.metamodel.source.spi.ToolingHintSource;
import org.hibernate.metamodel.spi.AttributePath;
import org.hibernate.metamodel.spi.AttributeRole;
import org.hibernate.metamodel.spi.NaturalIdMutability;
import org.hibernate.metamodel.spi.binding.IdentifierGeneratorDefinition;
import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.DotName;
import org.jboss.logging.Logger;
/**
* @author Steve Ebersole
@ -45,26 +57,34 @@ import org.jboss.jandex.DotName;
class NonAggregatedCompositeIdentifierSourceImpl
extends AbstractIdentifierSource
implements NonAggregatedCompositeIdentifierSource {
private static final Logger log = Logger.getLogger( NonAggregatedCompositeIdentifierSourceImpl.class );
private final List<SingularAttributeSource> idAttributes;
private final Class lookupIdClass;
private final List<SingularAttributeSource> idAttributeSources;
private final IdClassSource idClassSource;
public NonAggregatedCompositeIdentifierSourceImpl(RootEntitySourceImpl rootEntitySource) {
super( rootEntitySource );
this.idAttributes = rootEntitySource.getIdentifierAttributes();
this.idAttributeSources = rootEntitySource.getIdentifierAttributes();
final JavaTypeDescriptor idClassDescriptor = resolveIdClassDescriptor();
if ( idClassDescriptor == null ) {
// probably this is an error...
this.lookupIdClass = null;
// todo : map this a MessageLogger message
log.warnf(
"Encountered non-aggregated identifier with no IdClass specified; while this is supported, " +
"its use should be considered deprecated"
);
this.idClassSource = null;
}
else {
final ClassLoaderService cls = rootEntitySource.getLocalBindingContext()
.getServiceRegistry()
.getService( ClassLoaderService.class );
this.lookupIdClass = cls.classForName( idClassDescriptor.getName().toString() );
this.idClassSource = new IdClassSource( rootEntitySource, idClassDescriptor );
}
}
private JavaTypeDescriptor resolveIdClassDescriptor() {
@ -86,13 +106,13 @@ class NonAggregatedCompositeIdentifierSourceImpl
}
@Override
public Class getLookupIdClass() {
return lookupIdClass;
public List<SingularAttributeSource> getAttributeSourcesMakingUpIdentifier() {
return idAttributeSources;
}
@Override
public String getIdClassPropertyAccessorName() {
return idAttributes.get( 0 ).getPropertyAccessorName();
public EmbeddableSource getIdClassSource() {
return idClassSource;
}
@Override
@ -124,8 +144,159 @@ class NonAggregatedCompositeIdentifierSourceImpl
return Collections.emptySet();
}
@Override
public List<SingularAttributeSource> getAttributeSourcesMakingUpIdentifier() {
return idAttributes;
private class IdClassSource implements EmbeddableSource, EmbeddedContainer {
private final JavaTypeDescriptor idClassDescriptor;
private final EmbeddableTypeMetadata idClassTypeMetadata;
private final AttributeRole attributeRoleBase;
private final AttributePath attributePathBase;
private List<AttributeSource> attributeSources;
private IdClassSource(RootEntitySourceImpl rootEntitySource, JavaTypeDescriptor idClassDescriptor) {
this.idClassDescriptor = idClassDescriptor;
this.attributeRoleBase = rootEntitySource.getAttributeRoleBase().append( "<IdClass>" );
this.attributePathBase = rootEntitySource.getAttributePathBase().append( "<IdClass>" );
final AnnotationAttributeSource firstIdAttribute =
(AnnotationAttributeSource) rootEntitySource.getIdentifierAttributes().get( 0 );
this.idClassTypeMetadata = new EmbeddableTypeMetadata(
idClassDescriptor,
this,
attributeRoleBase,
attributePathBase,
firstIdAttribute.getAnnotatedAttribute().getAccessType(),
null,
rootEntitySource.getLocalBindingContext()
);
// todo : locate MapsId annotations and build a specialized AttributeBuilder
this.attributeSources = SourceHelper.buildAttributeSources(
idClassTypeMetadata,
SourceHelper.IdentifierPathAttributeBuilder.INSTANCE
);
if ( log.isDebugEnabled() ) {
String attributeDescriptors = null;
for ( AttributeSource attributeSource : attributeSources ) {
if ( attributeDescriptors == null ) {
attributeDescriptors = attributeSource.getName();
}
else {
attributeDescriptors += ", " + attributeSource.getName();
}
}
log.debugf(
"Built IdClassSource : %s : %s",
idClassTypeMetadata.getJavaTypeDescriptor().getName(),
attributeDescriptors
);
}
// todo : validate the IdClass attributes against the entity's id attributes
// todo : we need similar (MapsId, validation) in the EmbeddedId case too.
}
@Override
public JavaTypeDescriptor getTypeDescriptor() {
return idClassDescriptor;
}
@Override
public String getParentReferenceAttributeName() {
return null;
}
@Override
public String getExplicitTuplizerClassName() {
return idClassTypeMetadata.getCustomTuplizerClassName();
}
@Override
public AttributePath getAttributePathBase() {
return attributePathBase;
}
@Override
public AttributeRole getAttributeRoleBase() {
return attributeRoleBase;
}
@Override
public List<AttributeSource> attributeSources() {
return attributeSources;
}
@Override
public EntityBindingContext getLocalBindingContext() {
return idClassTypeMetadata.getLocalBindingContext();
}
// EmbeddedContainer impl (most of which we don't care about here
@Override
public MemberDescriptor getBackingMember() {
return null;
}
@Override
public AttributeConversionInfo locateConversionInfo(AttributePath attributePath) {
return null;
}
@Override
public AttributeOverride locateAttributeOverride(AttributePath attributePath) {
return null;
}
@Override
public AssociationOverride locateAssociationOverride(
AttributePath attributePath) {
return null;
}
@Override
public NaturalIdMutability getContainerNaturalIdMutability() {
return null;
}
@Override
public boolean getContainerOptionality() {
return false;
}
@Override
public boolean getContainerUpdatability() {
return false;
}
@Override
public boolean getContainerInsertability() {
return false;
}
@Override
public void registerConverter(
AttributePath attributePath, AttributeConversionInfo conversionInfo) {
}
@Override
public void registerAttributeOverride(
AttributePath attributePath, AttributeOverride override) {
}
@Override
public void registerAssociationOverride(
AttributePath attributePath, AssociationOverride override) {
}
}
}

View File

@ -25,15 +25,12 @@ package org.hibernate.metamodel.source.internal.annotations;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.hibernate.cfg.NamingStrategy;
import org.hibernate.metamodel.internal.binder.Binder;
import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor;
import org.hibernate.metamodel.source.internal.annotations.attribute.Column;
import org.hibernate.metamodel.source.internal.annotations.attribute.PluralAttribute;
import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames;
import org.hibernate.metamodel.source.spi.HibernateTypeSource;
import org.hibernate.metamodel.source.spi.PluralAttributeSequentialIndexSource;
import org.hibernate.metamodel.source.spi.RelationalValueSource;
import org.hibernate.metamodel.spi.PluralAttributeIndexNature;
@ -51,21 +48,7 @@ public class PluralAttributeSequentialIndexSourceImpl
private final RelationalValueSource relationalValueSource;
private final Binder.DefaultNamingStrategy defaultNamingStrategy;
private final static HibernateTypeSource INTEGER_TYPE = new HibernateTypeSource() {
@Override
public String getName() {
return "integer";
}
@Override
public Map<String, String> getParameters() {
return Collections.emptyMap();
}
@Override
public JavaTypeDescriptor getJavaType() {
return null;
}
};
private static HibernateTypeSourceImpl INTEGER_TYPE;
public PluralAttributeSequentialIndexSourceImpl(final PluralAttribute attribute) {
super( attribute );
@ -81,6 +64,14 @@ public class PluralAttributeSequentialIndexSourceImpl
return attribute.getName() + "_ORDER";
}
};
if ( INTEGER_TYPE == null ) {
INTEGER_TYPE = new HibernateTypeSourceImpl(
"integer",
null,
attribute.getContext().typeDescriptor( "int" )
);
}
}
@Override
@ -99,7 +90,7 @@ public class PluralAttributeSequentialIndexSourceImpl
}
@Override
public HibernateTypeSource getTypeInformation() {
public HibernateTypeSourceImpl getTypeInformation() {
return INTEGER_TYPE;
}

View File

@ -27,7 +27,6 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.hibernate.AssertionFailure;
@ -499,7 +498,7 @@ public class PluralAttributeSourceImpl
private static class CollectionIdSourceImpl implements CollectionIdSource {
private final ColumnSourceImpl columnSource;
private final HibernateTypeSource typeSource;
private final HibernateTypeSourceImpl typeSource;
private final String generatorName;
public CollectionIdSourceImpl(CollectionIdInformation collectionIdInformation, EntityBindingContext context) {
@ -520,69 +519,32 @@ public class PluralAttributeSourceImpl
return new ColumnSourceImpl( columns.get( 0 ) );
}
private HibernateTypeSource createTypeSource(AttributeTypeResolver typeResolver) {
private HibernateTypeSourceImpl createTypeSource(AttributeTypeResolver typeResolver) {
if ( typeResolver == null ) {
return EmptyHibernateTypeSource.INSTANCE;
return new HibernateTypeSourceImpl();
}
final String resolvedTypeName = typeResolver.getExplicitHibernateTypeName();
if ( StringHelper.isEmpty( resolvedTypeName ) ) {
return EmptyHibernateTypeSource.INSTANCE;
return new HibernateTypeSourceImpl();
}
return new HibernateTypeSource() {
@Override
public String getName() {
return resolvedTypeName;
}
@Override
public Map<String, String> getParameters() {
return Collections.emptyMap();
}
@Override
public JavaTypeDescriptor getJavaType() {
return null;
}
};
return new HibernateTypeSourceImpl( resolvedTypeName );
}
@Override
public ColumnSource getColumnSource() {
return null;
return columnSource;
}
@Override
public HibernateTypeSource getTypeInformation() {
return null;
public HibernateTypeSourceImpl getTypeInformation() {
return typeSource;
}
@Override
public String getGeneratorName() {
return null;
}
}
private static class EmptyHibernateTypeSource implements HibernateTypeSource {
/**
* Singleton access
*/
public static final EmptyHibernateTypeSource INSTANCE = new EmptyHibernateTypeSource();
@Override
public String getName() {
return null;
}
@Override
public Map<String, String> getParameters() {
return null;
}
@Override
public JavaTypeDescriptor getJavaType() {
return null;
return generatorName;
}
}
}

View File

@ -25,8 +25,10 @@ package org.hibernate.metamodel.source.internal.annotations;
import java.util.List;
import org.hibernate.metamodel.source.internal.annotations.attribute.SingularAssociationAttribute;
import org.hibernate.metamodel.source.internal.annotations.entity.EntityBindingContext;
import org.hibernate.metamodel.source.internal.annotations.entity.RootEntityTypeMetadata;
import org.hibernate.metamodel.source.spi.MapsIdSource;
import org.hibernate.metamodel.source.spi.SingularAttributeSource;
import org.hibernate.metamodel.source.spi.TableSpecificationSource;
@ -42,6 +44,7 @@ import org.jboss.jandex.AnnotationInstance;
*/
public class RootEntitySourceImpl extends EntitySourceImpl {
private List<SingularAttributeSource> identifierAttributes;
private List<MapsIdSource> mapsIdSources;
/**
* Constructs the root entity. Called from the construction of the
@ -71,12 +74,21 @@ public class RootEntitySourceImpl extends EntitySourceImpl {
entityTypeMetadata,
SourceHelper.IdentifierPathAttributeBuilder.INSTANCE
);
this.mapsIdSources = SourceHelper.buildMapsIdSources(
entityTypeMetadata,
SourceHelper.IdentifierPathAttributeBuilder.INSTANCE
);
}
public List<SingularAttributeSource> getIdentifierAttributes() {
return identifierAttributes;
}
public List<MapsIdSource> getMapsIdSources() {
return mapsIdSources;
}
@Override
public RootEntityTypeMetadata getEntityClass() {
return (RootEntityTypeMetadata) super.getEntityClass();

View File

@ -62,11 +62,6 @@ public class SimpleIdentifierSourceImpl extends AbstractIdentifierSource impleme
public String getUnsavedValue() {
return null;
}
@Override
public String getIdClassPropertyAccessorName() {
return attributeSource.getPropertyAccessorName();
}
}

View File

@ -31,6 +31,7 @@ import org.hibernate.AssertionFailure;
import org.hibernate.cfg.NotYetImplementedException;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.metamodel.source.internal.annotations.attribute.BasicAttribute;
import org.hibernate.metamodel.source.internal.annotations.attribute.EmbeddedAttribute;
import org.hibernate.metamodel.source.internal.annotations.attribute.OverrideAndConverterCollector;
@ -44,10 +45,13 @@ import org.hibernate.metamodel.source.internal.annotations.entity.MappedSupercla
import org.hibernate.metamodel.source.internal.annotations.entity.RootEntityTypeMetadata;
import org.hibernate.metamodel.source.spi.AttributeSource;
import org.hibernate.metamodel.source.spi.EmbeddedAttributeSource;
import org.hibernate.metamodel.source.spi.MapsIdSource;
import org.hibernate.metamodel.source.spi.PluralAttributeSource;
import org.hibernate.metamodel.source.spi.SingularAttributeSource;
import org.hibernate.metamodel.source.spi.ToOneAttributeSource;
import org.jboss.jandex.AnnotationValue;
/**
* Utilities for building attribute source objects.
*
@ -236,6 +240,37 @@ public class SourceHelper {
}
}
public static List<MapsIdSource> buildMapsIdSources(
RootEntityTypeMetadata entityTypeMetadata,
IdentifierPathAttributeBuilder attributeBuilder) {
final List<MapsIdSource> result = new ArrayList<MapsIdSource>();
for ( final SingularAssociationAttribute attribute : entityTypeMetadata.getMapsIdAttributes() ) {
final ToOneAttributeSource attributeSource = attributeBuilder.buildToOneAttribute(
attribute,
entityTypeMetadata
);
final AnnotationValue mapsIdNameValue = attribute.getMapsIdAnnotation().value();
final String mappedIdAttributeName = mapsIdNameValue == null
? null
: StringHelper.nullIfEmpty( mapsIdNameValue.asString() );
result.add(
new MapsIdSource() {
@Override
public String getMappedIdAttributeName() {
return mappedIdAttributeName;
}
@Override
public ToOneAttributeSource getAssociationAttributeSource() {
return attributeSource;
}
}
);
}
return result;
}
public static interface AttributeBuilder {
public SingularAttributeSource buildBasicAttribute(
BasicAttribute attribute,

View File

@ -59,6 +59,7 @@ import org.jboss.jandex.AnnotationInstance;
/**
* @author Hardy Ferentschik
* @author Gail Badner
* @author Steve Ebersole
*/
public class ToOneAttributeSourceImpl extends AbstractToOneAttributeSourceImpl implements ToOneAttributeSource {
private final List<RelationalValueSource> relationalValueSources;
@ -108,6 +109,10 @@ public class ToOneAttributeSourceImpl extends AbstractToOneAttributeSourceImpl i
}
else if ( associationAttribute.isId() ) {
// if this association is part of the ID then this can't be a one-to-one
// todo : not strictly true...
// it *could* be a one-to-one if this is only value/attribute
// making up the identifier but legacy mapping did not support
// that, so supporting that would be a new feature
return SingularAttributeNature.MANY_TO_ONE;
}
else if ( associationAttribute.getJoinColumnValues() == null ||
@ -125,13 +130,11 @@ public class ToOneAttributeSourceImpl extends AbstractToOneAttributeSourceImpl i
}
@Override
public void resolveToOneAttributeSource(AttributeSourceResolutionContext context) {
public void resolveToOneAttributeSourceNature(AttributeSourceResolutionContext context) {
if ( getSingularAttributeNature() != null ) {
return;
}
// It would be nice to have the following block in determineNatureIfPossible(),
// but it requires context.resolveIdentifierColumns(), it's here instead.
if ( AbstractPersistentAttribute.Nature.ONE_TO_ONE.equals( associationAttribute().getNature() ) ) {
final List<org.hibernate.metamodel.spi.relational.Column> idColumns = context.resolveIdentifierColumns();
if ( associationAttribute().getJoinColumnValues().size() != idColumns.size() ) {
setSingularAttributeNature( SingularAttributeNature.MANY_TO_ONE );
@ -150,17 +153,28 @@ public class ToOneAttributeSourceImpl extends AbstractToOneAttributeSourceImpl i
}
}
setSingularAttributeNature(
areJoinColumnsSameAsIdColumns ?
SingularAttributeNature.ONE_TO_ONE :
SingularAttributeNature.MANY_TO_ONE
areJoinColumnsSameAsIdColumns
? SingularAttributeNature.ONE_TO_ONE
: SingularAttributeNature.MANY_TO_ONE
);
}
}
if ( getSingularAttributeNature() == null ) {
throw new NotYetImplementedException( "unknown type of to-one attribute." );
}
}
@Override
public void resolveToOneAttributeSourceNatureAsPartOfIdentifier() {
if ( getSingularAttributeNature() != null ) {
return;
}
// atm, always treated as a MANY_TO_ONE
// todo see note/todo in #determineNatureIfPossible
setSingularAttributeNature( SingularAttributeNature.MANY_TO_ONE );
}
@Override
public List<Binder.DefaultNamingStrategy> getDefaultNamingStrategies(
final String entityName,
@ -309,10 +323,9 @@ public class ToOneAttributeSourceImpl extends AbstractToOneAttributeSourceImpl i
@Override
public List<? extends Value> getJoinColumns(JoinColumnResolutionContext context) {
final List<Value> values = new ArrayList<Value>();
final List<Column> joinColumns =
associationAttribute().getJoinTableAnnotation() == null ?
associationAttribute().getJoinColumnValues() :
associationAttribute().getInverseJoinColumnValues();
final List<Column> joinColumns = associationAttribute().getJoinTableAnnotation() == null
? associationAttribute().getJoinColumnValues()
: associationAttribute().getInverseJoinColumnValues();
for ( Column joinColumn : joinColumns ) {
if ( joinColumn.getReferencedColumnName() == null ) {
return context.resolveRelationalValuesForAttribute( null );

View File

@ -62,7 +62,7 @@ public class ToOneMappedByAttributeSourceImpl
}
@Override
public void resolveToOneAttributeSource(AttributeSourceResolutionContext context) {
public void resolveToOneAttributeSourceNature(AttributeSourceResolutionContext context) {
if ( getSingularAttributeNature() != null && owner != null) {
return;
}
@ -96,6 +96,11 @@ public class ToOneMappedByAttributeSourceImpl
}
}
@Override
public void resolveToOneAttributeSourceNatureAsPartOfIdentifier() {
// should this be an error?
}
@Override
public boolean isMappedBy() {
return true;

View File

@ -101,6 +101,8 @@ public class EmbeddableTypeMetadata extends ManagedTypeMetadata {
private String decodeTuplizerAnnotation(EmbeddedContainer container) {
// prefer tuplizer defined at the embedded level
{
// might be null though in the case of an IdClass
if ( container.getBackingMember() != null ) {
final AnnotationInstance tuplizerAnnotation = container.getBackingMember().getAnnotations().get(
HibernateDotNames.TUPLIZER
);
@ -108,6 +110,7 @@ public class EmbeddableTypeMetadata extends ManagedTypeMetadata {
return tuplizerAnnotation.value( "impl" ).asString();
}
}
}
// The tuplizer on the embeddable (if one) would be covered by this.getCustomTuplizerClassName()...
return super.getCustomTuplizerClassName();

View File

@ -42,6 +42,7 @@ import org.hibernate.metamodel.source.internal.annotations.attribute.Association
import org.hibernate.metamodel.source.internal.annotations.attribute.AttributeOverride;
import org.hibernate.metamodel.source.internal.annotations.attribute.BasicAttribute;
import org.hibernate.metamodel.source.internal.annotations.attribute.PersistentAttribute;
import org.hibernate.metamodel.source.internal.annotations.attribute.SingularAssociationAttribute;
import org.hibernate.metamodel.source.internal.annotations.attribute.SingularAttribute;
import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames;
import org.hibernate.metamodel.source.internal.annotations.util.JPAListenerHelper;
@ -67,6 +68,7 @@ public class IdentifiableTypeMetadata extends ManagedTypeMetadata {
private IdType idType;
private List<SingularAttribute> identifierAttributes;
private List<SingularAssociationAttribute> mapsIdAssociationAttributes;
private BasicAttribute versionAttribute;
private final Map<AttributePath, AttributeConversionInfo> conversionInfoMap = new HashMap<AttributePath, AttributeConversionInfo>();
@ -418,6 +420,17 @@ public class IdentifiableTypeMetadata extends ManagedTypeMetadata {
identifierAttributes.add( singularAttribute );
return;
}
if ( SingularAssociationAttribute.class.isInstance( singularAttribute ) ) {
final SingularAssociationAttribute toOneAttribute = (SingularAssociationAttribute) singularAttribute;
if ( toOneAttribute.getMapsIdAnnotation() != null ) {
if ( mapsIdAssociationAttributes == null ) {
mapsIdAssociationAttributes = new ArrayList<SingularAssociationAttribute>();
}
mapsIdAssociationAttributes.add( toOneAttribute );
return;
}
}
}
super.categorizeAttribute( persistentAttribute );
@ -446,6 +459,19 @@ public class IdentifiableTypeMetadata extends ManagedTypeMetadata {
return identifierAttributes == null ? Collections.<SingularAttribute>emptyList() : identifierAttributes;
}
public List<SingularAssociationAttribute> getMapsIdAttributes() {
collectAttributesIfNeeded();
if ( mapsIdAssociationAttributes == null ) {
return getSuperType() != null
? getSuperType().getMapsIdAttributes()
: Collections.<SingularAssociationAttribute>emptyList();
}
else {
return mapsIdAssociationAttributes;
}
}
public BasicAttribute getVersionAttribute() {
collectAttributesIfNeeded();

View File

@ -355,14 +355,28 @@ public abstract class ManagedTypeMetadata implements OverrideAndConverterCollect
final ClassDescriptor subclassTypeDescriptor = (ClassDescriptor) bindingContext.getJavaTypeDescriptorRepository().getType( classInfo.name() );
final IdentifiableTypeMetadata subclassMeta;
if ( isMappedSuperclass( javaTypeDescriptor ) ) {
subclassMeta = new MappedSuperclassTypeMetadata( subclassTypeDescriptor, superType, defaultAccessType, bindingContext );
if ( isEntity( subclassTypeDescriptor ) ) {
subclassMeta = new EntityTypeMetadata(
subclassTypeDescriptor,
superType,
defaultAccessType,
bindingContext
);
( (ManagedTypeMetadata) superType ).addSubclass( subclassMeta );
}
else if ( isMappedSuperclass( subclassTypeDescriptor ) ) {
subclassMeta = new MappedSuperclassTypeMetadata(
subclassTypeDescriptor,
superType,
defaultAccessType,
bindingContext
);
( (ManagedTypeMetadata) superType ).addSubclass( subclassMeta );
}
else {
subclassMeta = new EntityTypeMetadata( subclassTypeDescriptor, superType, defaultAccessType, bindingContext );
subclassMeta = superType;
}
( (ManagedTypeMetadata) superType ).addSubclass( subclassMeta );
walkSubclasses( subclassTypeDescriptor, subclassMeta, defaultAccessType, bindingContext );
}
}
@ -416,16 +430,12 @@ public abstract class ManagedTypeMetadata implements OverrideAndConverterCollect
protected void collectAttributesIfNeeded() {
if ( persistentAttributeMap == null ) {
persistentAttributeMap = new HashMap<String, PersistentAttribute>();
// TODO: This probably isn't the best place for this. Walking and creating the ManagedTypeMetadatas,
// for the entire subclass tree, including subclasses that are not an @Entity/@MappedSuperclass/@Embeddable,
// is entirely necessary. But, we need to skip processing the attributes in this case. Cleaner way to do
// it in the new architecture?
if (isEntity( javaTypeDescriptor )
|| isMappedSuperclass( javaTypeDescriptor )
|| isEmbeddableType( javaTypeDescriptor )) {
collectPersistentAttributes();
}
}
public AccessType getClassLevelAccessType() {
return classLevelAccessType;
}
public String getCustomTuplizerClassName() {

View File

@ -48,6 +48,7 @@ import org.hibernate.metamodel.source.internal.annotations.util.JandexHelper;
import org.hibernate.metamodel.spi.binding.AttributeBinding;
import org.hibernate.metamodel.spi.binding.EmbeddedAttributeBinding;
import org.hibernate.metamodel.spi.binding.EntityBinding;
import org.hibernate.metamodel.spi.binding.EntityIdentifier;
import org.hibernate.metamodel.spi.binding.ManyToOneAttributeBinding;
import org.hibernate.metamodel.spi.binding.SingularAssociationAttributeBinding;
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
@ -283,14 +284,21 @@ public class SqlResultSetProcessor {
// case COMPOSITE:
// referencedEntityBinding.getHierarchyDetails().getEntityIdentifier().isSingleAttribute();//.isIdentifierMapper();
// }
//todo check if this logic is correct
SingularAttributeBinding identifierAttributeBinding = referencedEntityBinding.getHierarchyDetails()
.getEntityIdentifier()
.getAttributeBinding();
if ( EmbeddedAttributeBinding.class.isInstance( identifierAttributeBinding ) ) {
attributeBindings = EmbeddedAttributeBinding.class.cast( identifierAttributeBinding )
.getEmbeddableBinding()
.attributeBindings();
final EntityIdentifier idInfo = referencedEntityBinding.getHierarchyDetails()
.getEntityIdentifier();
if ( EntityIdentifier.AggregatedCompositeIdentifierBinding.class.isInstance( idInfo.getEntityIdentifierBinding() ) ) {
final EntityIdentifier.AggregatedCompositeIdentifierBinding identifierBinding =
(EntityIdentifier.AggregatedCompositeIdentifierBinding) idInfo.getEntityIdentifierBinding();
attributeBindings = identifierBinding.getAttributeBinding()
.getEmbeddableBinding().attributeBindings();
}
else if ( EntityIdentifier.NonAggregatedCompositeIdentifierBinding.class.isInstance( idInfo.getEntityIdentifierBinding() ) ) {
final EntityIdentifier.NonAggregatedCompositeIdentifierBinding identifierBinding =
(EntityIdentifier.NonAggregatedCompositeIdentifierBinding) idInfo.getEntityIdentifierBinding();
attributeBindings = identifierBinding.getVirtualEmbeddableBinding().attributeBindings();
}
else {
throw new MappingException(

View File

@ -268,8 +268,8 @@ public class AssociationHelper {
}
// only valid for to-one associations
if ( !PersistentAttribute.Nature.MANY_TO_ONE.equals( attributeNature )
&& !PersistentAttribute.Nature.MANY_TO_ONE.equals( attributeNature ) ) {
if ( PersistentAttribute.Nature.MANY_TO_ONE != attributeNature
&& PersistentAttribute.Nature.ONE_TO_ONE != attributeNature ) {
throw localBindingContext.makeMappingException(
"@MapsId can only be specified on a many-to-one or one-to-one " +
"associations, property: " + member.toString()

View File

@ -92,21 +92,7 @@ public abstract class AbstractPluralAttributeSourceImpl
this.caching = Helper.createCaching( pluralAttributeElement.getCache() );
this.typeInformation = new HibernateTypeSource() {
@Override
public String getName() {
return pluralAttributeElement.getCollectionType();
}
@Override
public Map<String, String> getParameters() {
return Collections.emptyMap();
}
@Override
public JavaTypeDescriptor getJavaType() {
return null;
}
};
this.typeInformation = new HibernateTypeSourceImpl( pluralAttributeElement.getCollectionType() );
this.filterSources = buildFilterSources();
}

View File

@ -35,7 +35,6 @@ import org.hibernate.mapping.PropertyGeneration;
import org.hibernate.metamodel.internal.binder.Binder;
import org.hibernate.metamodel.source.spi.AttributeSource;
import org.hibernate.metamodel.source.spi.AttributeSourceResolutionContext;
import org.hibernate.metamodel.source.spi.HibernateTypeSource;
import org.hibernate.metamodel.source.spi.MappedByAssociationSource;
import org.hibernate.metamodel.source.spi.MappingException;
import org.hibernate.metamodel.source.spi.ToOneAttributeSource;
@ -60,11 +59,6 @@ public abstract class AbstractToOneAttributeSourceImpl extends AbstractHbmSource
super( sourceMappingDocument );
this.naturalIdMutability = naturalIdMutability;
this.propertyRef = propertyRef;
}
@Override
public HibernateTypeSource getTypeInformation() {
return Helper.TO_ONE_ATTRIBUTE_TYPE_SOURCE;
}
@Override
@ -229,7 +223,12 @@ public abstract class AbstractToOneAttributeSourceImpl extends AbstractHbmSource
}
@Override
public void resolveToOneAttributeSource(AttributeSourceResolutionContext context) {
public void resolveToOneAttributeSourceNature(AttributeSourceResolutionContext context) {
// nothing to do
}
@Override
public void resolveToOneAttributeSourceNatureAsPartOfIdentifier() {
// nothing to do
}
@ -268,26 +267,4 @@ public abstract class AbstractToOneAttributeSourceImpl extends AbstractHbmSource
// TODO: Can HBM do something like JPA's @ForeignKey(NO_CONSTRAINT)?
return true;
}
@Override
public MapsIdSource getMapsIdSource() {
return MapsIdSourceImpl.INSTANCE;
}
private static class MapsIdSourceImpl implements MapsIdSource {
/**
* Singleton access
*/
public static final MapsIdSourceImpl INSTANCE = new MapsIdSourceImpl();
@Override
public boolean isDefined() {
return false;
}
@Override
public String getLookupClassAttributeName() {
return null;
}
}
}

View File

@ -25,6 +25,7 @@ package org.hibernate.metamodel.source.internal.hbm;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.hibernate.EntityMode;
@ -32,6 +33,7 @@ import org.hibernate.TruthValue;
import org.hibernate.engine.OptimisticLockStyle;
import org.hibernate.id.EntityIdentifierNature;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor;
import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbClassElement;
import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbCompositeIdElement;
import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbDiscriminatorElement;
@ -40,12 +42,16 @@ import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbKeyPropertyElement;
import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbMultiTenancyElement;
import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbPolymorphismAttribute;
import org.hibernate.metamodel.source.spi.AggregatedCompositeIdentifierSource;
import org.hibernate.metamodel.source.spi.AttributeSource;
import org.hibernate.metamodel.source.spi.AttributeSourceContainer;
import org.hibernate.metamodel.source.spi.DiscriminatorSource;
import org.hibernate.metamodel.source.spi.EmbeddableSource;
import org.hibernate.metamodel.source.spi.EmbeddedAttributeSource;
import org.hibernate.metamodel.source.spi.EntityHierarchySource;
import org.hibernate.metamodel.source.spi.EntitySource;
import org.hibernate.metamodel.source.spi.IdentifierSource;
import org.hibernate.metamodel.source.spi.MappingException;
import org.hibernate.metamodel.source.spi.MapsIdSource;
import org.hibernate.metamodel.source.spi.MultiTenancySource;
import org.hibernate.metamodel.source.spi.NonAggregatedCompositeIdentifierSource;
import org.hibernate.metamodel.source.spi.RelationalValueSource;
@ -56,6 +62,7 @@ import org.hibernate.metamodel.source.spi.ToolingHintSource;
import org.hibernate.metamodel.source.spi.VersionAttributeSource;
import org.hibernate.metamodel.spi.AttributePath;
import org.hibernate.metamodel.spi.AttributeRole;
import org.hibernate.metamodel.spi.LocalBindingContext;
import org.hibernate.metamodel.spi.NaturalIdMutability;
import org.hibernate.metamodel.spi.binding.Caching;
import org.hibernate.metamodel.spi.binding.IdentifierGeneratorDefinition;
@ -121,7 +128,8 @@ public class EntityHierarchySourceImpl implements EntityHierarchySource {
return new SimpleIdentifierSourceImpl();
}
else {
// if we get here, we should have a composite identifier. Just need to determine if it is aggregated, or not...
// if we get here, we should have a composite identifier. Just need
// to determine if it is aggregated, or non-aggregated...
if ( StringHelper.isEmpty( entityElement().getCompositeId().getName() ) ) {
if ( entityElement().getCompositeId().isMapped() &&
StringHelper.isEmpty( entityElement().getCompositeId().getClazz() ) ) {
@ -391,16 +399,6 @@ public class EntityHierarchySourceImpl implements EntityHierarchySource {
public Collection<? extends ToolingHintSource> getToolingHintSources() {
return entityElement().getId().getMeta();
}
@Override
public Class getLookupIdClass() {
return determineJpaIdClass();
}
@Override
public String getIdClassPropertyAccessorName() {
return null;
}
}
private class AggregatedCompositeIdentifierSourceImpl implements AggregatedCompositeIdentifierSource {
@ -412,6 +410,11 @@ public class EntityHierarchySourceImpl implements EntityHierarchySource {
return componentAttributeSource;
}
@Override
public List<MapsIdSource> getMapsIdSources() {
return Collections.emptyList();
}
@Override
public IdentifierGeneratorDefinition getIndividualAttributeIdGenerator(String identifierAttributeName) {
// for now, return null. this is that stupid specj bs
@ -447,16 +450,6 @@ public class EntityHierarchySourceImpl implements EntityHierarchySource {
return entityElement().getCompositeId().getUnsavedValue().value();
}
@Override
public Class getLookupIdClass() {
return determineJpaIdClass();
}
@Override
public String getIdClassPropertyAccessorName() {
return null;
}
@Override
public Collection<? extends ToolingHintSource> getToolingHintSources() {
return entityElement().getId().getMeta();
@ -529,47 +522,41 @@ public class EntityHierarchySourceImpl implements EntityHierarchySource {
}
}
private class NonAggregatedCompositeIdentifierSourceImpl implements NonAggregatedCompositeIdentifierSource {
@Override
public Class getLookupIdClass() {
return determineJpaIdClass();
private final List<SingularAttributeSource> attributeSources;
private final EmbeddableSource idClassSource;
private NonAggregatedCompositeIdentifierSourceImpl() {
this.attributeSources = new ArrayList<SingularAttributeSource>();
collectCompositeIdAttributes( attributeSources, rootEntitySource );
// NOTE : the HBM support for IdClass is very limited. Essentially
// we assume that all identifier attributes occur in the IdClass
// using the same name and type.
this.idClassSource = interpretIdClass();
}
@Override
public String getIdClassPropertyAccessorName() {
private EmbeddableSource interpretIdClass() {
final JaxbCompositeIdElement compositeId = entityElement().getCompositeId();
// if <composite-id/> is null here we have much bigger problems :)
final String className = compositeId.getClazz();
if ( StringHelper.isEmpty( className ) ) {
return null;
}
return new IdClassSource( rootEntitySource.getLocalBindingContext().typeDescriptor( className ) );
}
@Override
public List<SingularAttributeSource> getAttributeSourcesMakingUpIdentifier() {
final List<SingularAttributeSource> attributeSources = new ArrayList<SingularAttributeSource>();
final JaxbCompositeIdElement compositeId = entityElement().getCompositeId();
final List list = compositeId.getKeyPropertyOrKeyManyToOne();
for ( final Object obj : list ) {
if ( JaxbKeyPropertyElement.class.isInstance( obj ) ) {
JaxbKeyPropertyElement key = JaxbKeyPropertyElement.class.cast( obj );
attributeSources.add(
new IdentifierKeyAttributeSourceImpl(
sourceMappingDocument(),
rootEntitySource,
key
)
);
}
if ( JaxbKeyManyToOneElement.class.isInstance( obj ) ) {
JaxbKeyManyToOneElement key = JaxbKeyManyToOneElement.class.cast( obj );
attributeSources.add(
new IdentifierKeyManyToOneSourceImpl(
sourceMappingDocument(),
rootEntitySource,
key
)
);
}
return attributeSources;
}
return attributeSources;
@Override
public EmbeddableSource getIdClassSource() {
return idClassSource;
}
@Override
@ -613,6 +600,81 @@ public class EntityHierarchySourceImpl implements EntityHierarchySource {
}
}
@SuppressWarnings("unchecked")
private void collectCompositeIdAttributes(
List attributeSources,
AttributeSourceContainer attributeSourceContainer) {
final JaxbCompositeIdElement compositeId = entityElement().getCompositeId();
final List list = compositeId.getKeyPropertyOrKeyManyToOne();
for ( final Object obj : list ) {
if ( JaxbKeyPropertyElement.class.isInstance( obj ) ) {
JaxbKeyPropertyElement key = JaxbKeyPropertyElement.class.cast( obj );
attributeSources.add(
new IdentifierKeyAttributeSourceImpl(
sourceMappingDocument(),
attributeSourceContainer,
key
)
);
}
if ( JaxbKeyManyToOneElement.class.isInstance( obj ) ) {
JaxbKeyManyToOneElement key = JaxbKeyManyToOneElement.class.cast( obj );
attributeSources.add(
new IdentifierKeyManyToOneSourceImpl(
sourceMappingDocument(),
attributeSourceContainer,
key
)
);
}
}
}
private class IdClassSource implements EmbeddableSource {
private final JavaTypeDescriptor idClassDescriptor;
private final List<AttributeSource> attributeSources;
private IdClassSource(JavaTypeDescriptor idClassDescriptor) {
this.idClassDescriptor = idClassDescriptor;
this.attributeSources = new ArrayList<AttributeSource>();
collectCompositeIdAttributes( attributeSources, this );
}
@Override
public JavaTypeDescriptor getTypeDescriptor() {
return idClassDescriptor;
}
@Override
public String getParentReferenceAttributeName() {
return null;
}
@Override
public String getExplicitTuplizerClassName() {
return null;
}
@Override
public AttributePath getAttributePathBase() {
return rootEntitySource.getAttributePathBase().append( "<IdClass>" );
}
@Override
public AttributeRole getAttributeRoleBase() {
return rootEntitySource.getAttributeRoleBase().append( "<IdClass>" );
}
@Override
public List<AttributeSource> attributeSources() {
return attributeSources;
}
@Override
public LocalBindingContext getLocalBindingContext() {
return rootEntitySource.getLocalBindingContext();
}
}
public static class EmbeddableJaxbSourceImpl extends AbstractEmbeddableJaxbSource {
private final JaxbCompositeIdElement compositeIdElement;
@ -662,30 +724,6 @@ public class EntityHierarchySourceImpl implements EntityHierarchySource {
}
private Class determineJpaIdClass() {
// this would be a <composite-id/> defined with mapped="false"
final JaxbCompositeIdElement compositeId = entityElement().getCompositeId();
if ( compositeId == null ) {
return null;
}
if ( !"".equals( compositeId.getName() ) ) {
return null;
}
if ( compositeId.isMapped() ) {
return null;
}
if ( compositeId.getClazz() == null ) {
return null;
}
// todo : do we really want to be loading this?
return rootEntitySource.bindingContext().getClassLoaderAccess().classForName( rootEntitySource.bindingContext().qualifyClassName( compositeId.getClazz() )
);
}
private String getEntityName() {
return rootEntitySource.getEntityName();
}

View File

@ -68,22 +68,6 @@ import org.hibernate.metamodel.spi.binding.MetaAttribute;
* @author Gail Badner
*/
public class Helper {
public static final HibernateTypeSource TO_ONE_ATTRIBUTE_TYPE_SOURCE = new HibernateTypeSource() {
@Override
public String getName() {
return null;
}
@Override
public Map<String, String> getParameters() {
return null;
}
@Override
public JavaTypeDescriptor getJavaType() {
return null;
}
};
public static LockMode interpretLockMode(JaxbLockModeAttribute lockModeAttribute, LocalBindingContext context){
if ( lockModeAttribute == null ) {
return LockMode.READ;

View File

@ -0,0 +1,83 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2014, 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.metamodel.source.internal.hbm;
import java.util.Collections;
import java.util.Map;
import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor;
import org.hibernate.metamodel.source.spi.HibernateTypeSource;
import org.hibernate.metamodel.source.spi.JavaTypeDescriptorResolvable;
/**
* @author Steve Ebersole
*/
public class HibernateTypeSourceImpl implements HibernateTypeSource, JavaTypeDescriptorResolvable {
private final String name;
private final Map<String, String> parameters;
private JavaTypeDescriptor javaTypeDescriptor;
public HibernateTypeSourceImpl(String name) {
this( name, Collections.<String, String>emptyMap() );
}
public HibernateTypeSourceImpl(String name, Map<String, String> parameters) {
this.name = name;
this.parameters = parameters;
}
public HibernateTypeSourceImpl(JavaTypeDescriptor javaTypeDescriptor) {
this( null, javaTypeDescriptor );
}
public HibernateTypeSourceImpl(String name, JavaTypeDescriptor javaTypeDescriptor) {
this( name );
this.javaTypeDescriptor = javaTypeDescriptor;
}
@Override
public String getName() {
return name;
}
@Override
public Map<String, String> getParameters() {
return parameters;
}
@Override
public JavaTypeDescriptor getJavaType() {
return javaTypeDescriptor;
}
@Override
public void resolveJavaTypeDescriptor(JavaTypeDescriptor descriptor) {
if ( this.javaTypeDescriptor != null ) {
if ( this.javaTypeDescriptor != descriptor ) {
throw new IllegalStateException( "Attempt to resolve an already resolved JavaTypeDescriptor" );
}
}
this.javaTypeDescriptor = descriptor;
}
}

View File

@ -23,18 +23,14 @@
*/
package org.hibernate.metamodel.source.internal.hbm;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor;
import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbBagElement;
import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbColumnElement;
import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbIdbagElement;
import org.hibernate.metamodel.source.spi.CollectionIdSource;
import org.hibernate.metamodel.source.spi.ColumnSource;
import org.hibernate.metamodel.source.spi.HibernateTypeSource;
import org.hibernate.metamodel.source.spi.Orderable;
import org.hibernate.metamodel.source.spi.RelationalValueSource;
import org.hibernate.metamodel.source.spi.SizeSource;
@ -100,25 +96,7 @@ public class IdBagSourceImpl extends AbstractPluralAttributeSourceImpl implement
collectionIdColumnSource = (ColumnSource) relationalValueSource;
}
final HibernateTypeSource typeSource = new HibernateTypeSource() {
private final String name = element.getCollectionId().getType();
@Override
public String getName() {
return name;
}
@Override
public Map<String, String> getParameters() {
return Collections.emptyMap();
}
@Override
public JavaTypeDescriptor getJavaType() {
return null;
}
};
final HibernateTypeSourceImpl typeSource = new HibernateTypeSourceImpl( element.getCollectionId().getType() );
this.collectionIdSource = new CollectionIdSourceImpl(
collectionIdColumnSource,
typeSource,
@ -148,12 +126,12 @@ public class IdBagSourceImpl extends AbstractPluralAttributeSourceImpl implement
private static class CollectionIdSourceImpl implements CollectionIdSource {
private final ColumnSource columnSource;
private final HibernateTypeSource typeSource;
private final HibernateTypeSourceImpl typeSource;
private final String generator;
public CollectionIdSourceImpl(
ColumnSource columnSource,
HibernateTypeSource typeSource,
HibernateTypeSourceImpl typeSource,
String generator) {
this.columnSource = columnSource;
this.typeSource = typeSource;
@ -166,7 +144,7 @@ public class IdBagSourceImpl extends AbstractPluralAttributeSourceImpl implement
}
@Override
public HibernateTypeSource getTypeInformation() {
public HibernateTypeSourceImpl getTypeInformation() {
return typeSource;
}

View File

@ -28,11 +28,9 @@ import java.util.List;
import java.util.Map;
import org.hibernate.mapping.PropertyGeneration;
import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor;
import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbColumnElement;
import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbKeyPropertyElement;
import org.hibernate.metamodel.source.spi.AttributeSourceContainer;
import org.hibernate.metamodel.source.spi.HibernateTypeSource;
import org.hibernate.metamodel.source.spi.RelationalValueSource;
import org.hibernate.metamodel.source.spi.SingularAttributeSource;
import org.hibernate.metamodel.source.spi.SizeSource;
@ -52,7 +50,7 @@ class KeyAttributeSourceImpl
implements SingularAttributeSource {
private final JaxbKeyPropertyElement keyPropertyElement;
private final NaturalIdMutability naturalIdMutability;
private final HibernateTypeSource typeSource;
private final HibernateTypeSourceImpl typeSource;
private final List<RelationalValueSource> valueSources;
private final AttributePath attributePath;
@ -65,30 +63,17 @@ class KeyAttributeSourceImpl
super( mappingDocument );
this.keyPropertyElement = keyPropertyElement;
this.naturalIdMutability = naturalIdMutability;
this.typeSource = new HibernateTypeSource() {
private final String name = keyPropertyElement.getTypeAttribute() != null
final String name = keyPropertyElement.getTypeAttribute() != null
? keyPropertyElement.getTypeAttribute()
: keyPropertyElement.getType() != null
? keyPropertyElement.getType().getName()
: null;
private final Map<String, String> parameters = ( keyPropertyElement.getType() != null )
final Map<String, String> parameters = ( keyPropertyElement.getType() != null )
? Helper.extractParameters( keyPropertyElement.getType().getParam() )
: null;
this.typeSource = new HibernateTypeSourceImpl( name, parameters );
@Override
public String getName() {
return name;
}
@Override
public Map<String, String> getParameters() {
return parameters;
}
@Override
public JavaTypeDescriptor getJavaType() {
return null;
}
};
this.valueSources = Helper.buildValueSources(
sourceMappingDocument(),
new Helper.ValueSourcesAdapter() {
@ -144,7 +129,7 @@ class KeyAttributeSourceImpl
}
@Override
public HibernateTypeSource getTypeInformation() {
public HibernateTypeSourceImpl getTypeInformation() {
return typeSource;
}

View File

@ -30,6 +30,8 @@ import java.util.Set;
import org.hibernate.engine.spi.CascadeStyle;
import org.hibernate.engine.spi.CascadeStyles;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor;
import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbColumnElement;
import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbKeyManyToOneElement;
import org.hibernate.metamodel.source.spi.AttributeSourceContainer;
@ -51,6 +53,7 @@ class KeyManyToOneSourceImpl
extends AbstractToOneAttributeSourceImpl
implements SingularAttributeSource {
private final JaxbKeyManyToOneElement keyManyToOneElement;
private final HibernateTypeSourceImpl typeSource;
private final List<RelationalValueSource> valueSources;
private final AttributePath attributePath;
@ -63,6 +66,18 @@ class KeyManyToOneSourceImpl
final NaturalIdMutability naturalIdMutability) {
super( mappingDocument, naturalIdMutability, null );
this.keyManyToOneElement = keyManyToOneElement;
final String referencedClassName = keyManyToOneElement.getClazz();
JavaTypeDescriptor referencedClass = null;
if ( StringHelper.isNotEmpty( referencedClassName ) ) {
referencedClass = bindingContext().getJavaTypeDescriptorRepository().getType(
bindingContext().getJavaTypeDescriptorRepository().buildName(
bindingContext().qualifyClassName( keyManyToOneElement.getClazz() )
)
);
}
this.typeSource = new HibernateTypeSourceImpl( referencedClass );
this.valueSources = Helper.buildValueSources(
sourceMappingDocument(),
new Helper.ValueSourcesAdapter() {
@ -122,6 +137,11 @@ class KeyManyToOneSourceImpl
return attributeRole;
}
@Override
public HibernateTypeSourceImpl getTypeInformation() {
return typeSource;
}
@Override
public String getPropertyAccessorName() {
return keyManyToOneElement.getAccess();

View File

@ -28,6 +28,8 @@ import java.util.List;
import java.util.Set;
import org.hibernate.engine.spi.CascadeStyle;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor;
import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbColumnElement;
import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbManyToOneElement;
import org.hibernate.metamodel.source.spi.AttributeSourceContainer;
@ -46,6 +48,8 @@ import org.hibernate.type.ForeignKeyDirection;
*/
class ManyToOneAttributeSourceImpl extends AbstractToOneAttributeSourceImpl {
private final JaxbManyToOneElement manyToOneElement;
private final HibernateTypeSourceImpl typeSource;
private final String containingTableName;
private final List<RelationalValueSource> valueSources;
@ -60,6 +64,18 @@ class ManyToOneAttributeSourceImpl extends AbstractToOneAttributeSourceImpl {
NaturalIdMutability naturalIdMutability) {
super( sourceMappingDocument, naturalIdMutability, manyToOneElement.getPropertyRef() );
this.manyToOneElement = manyToOneElement;
final String referencedClassName = manyToOneElement.getClazz();
JavaTypeDescriptor referencedClass = null;
if ( StringHelper.isNotEmpty( referencedClassName ) ) {
referencedClass = bindingContext().getJavaTypeDescriptorRepository().getType(
bindingContext().getJavaTypeDescriptorRepository().buildName(
bindingContext().qualifyClassName( manyToOneElement.getClazz() )
)
);
}
this.typeSource = new HibernateTypeSourceImpl( referencedClass );
this.containingTableName = logicalTableName;
this.valueSources = Helper.buildValueSources(
sourceMappingDocument(),
@ -120,6 +136,11 @@ class ManyToOneAttributeSourceImpl extends AbstractToOneAttributeSourceImpl {
return attributeRole;
}
@Override
public HibernateTypeSourceImpl getTypeInformation() {
return typeSource;
}
@Override
public String getPropertyAccessorName() {
return manyToOneElement.getAccess();

View File

@ -29,11 +29,9 @@ import java.util.Map;
import org.hibernate.cfg.NamingStrategy;
import org.hibernate.metamodel.internal.binder.Binder;
import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor;
import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbColumnElement;
import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbIndexElement;
import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbMapKeyElement;
import org.hibernate.metamodel.source.spi.HibernateTypeSource;
import org.hibernate.metamodel.source.spi.PluralAttributeMapKeySourceBasic;
import org.hibernate.metamodel.source.spi.RelationalValueSource;
import org.hibernate.metamodel.source.spi.SizeSource;
@ -45,11 +43,18 @@ import org.hibernate.metamodel.spi.PluralAttributeIndexNature;
public class MapKeySourceBasicImpl extends AbstractHbmSourceNode implements PluralAttributeMapKeySourceBasic {
private final PluralAttributeIndexNature nature;
private final List<RelationalValueSource> valueSources;
private final HibernateTypeSource typeSource;
private final HibernateTypeSourceImpl typeSource;
public MapKeySourceBasicImpl(MappingDocument sourceMappingDocument, final JaxbMapKeyElement mapKey) {
super( sourceMappingDocument );
valueSources = Helper.buildValueSources(
final String typeName = extractTypeName( mapKey );
final Map<String, String> typeParams = mapKey.getType() != null
? Helper.extractParameters( mapKey.getType().getParam() )
: java.util.Collections.<String, String>emptyMap();
this.typeSource = new HibernateTypeSourceImpl( typeName, typeParams );
this.valueSources = Helper.buildValueSources(
sourceMappingDocument(),
new Helper.ValueSourcesAdapter() {
@ -94,9 +99,11 @@ public class MapKeySourceBasicImpl extends AbstractHbmSourceNode implements Plur
}
}
);
this.typeSource = new HibernateTypeSource() {
@Override
public String getName() {
this.nature = PluralAttributeIndexNature.BASIC;
}
private String extractTypeName(JaxbMapKeyElement mapKey) {
if ( mapKey.getTypeAttribute() != null ) {
return mapKey.getTypeAttribute();
}
@ -106,23 +113,11 @@ public class MapKeySourceBasicImpl extends AbstractHbmSourceNode implements Plur
return null;
}
@Override
public Map<String, String> getParameters() {
return mapKey.getType() != null
? Helper.extractParameters( mapKey.getType().getParam() )
: java.util.Collections.<String, String>emptyMap();
}
@Override
public JavaTypeDescriptor getJavaType() {
return null;
}
};
this.nature = PluralAttributeIndexNature.BASIC;
}
public MapKeySourceBasicImpl(MappingDocument sourceMappingDocument, final JaxbIndexElement indexElement) {
super( sourceMappingDocument );
valueSources = Helper.buildValueSources(
this.typeSource = new HibernateTypeSourceImpl( indexElement.getType() );
this.valueSources = Helper.buildValueSources(
sourceMappingDocument,
new Helper.ValueSourcesAdapter() {
@ -157,22 +152,6 @@ public class MapKeySourceBasicImpl extends AbstractHbmSourceNode implements Plur
}
}
);
typeSource = new HibernateTypeSource() {
@Override
public String getName() {
return indexElement.getType();
}
@Override
public Map<String, String> getParameters() {
return java.util.Collections.emptyMap();
}
@Override
public JavaTypeDescriptor getJavaType() {
return null;
}
};
this.nature = PluralAttributeIndexNature.BASIC;
}
@ -210,7 +189,7 @@ public class MapKeySourceBasicImpl extends AbstractHbmSourceNode implements Plur
}
@Override
public HibernateTypeSource getTypeInformation() {
public HibernateTypeSourceImpl getTypeInformation() {
return typeSource;
}

View File

@ -28,6 +28,8 @@ import java.util.List;
import java.util.Set;
import org.hibernate.engine.spi.CascadeStyle;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor;
import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbColumnElement;
import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbOneToOneElement;
import org.hibernate.metamodel.source.spi.AttributeSourceContainer;
@ -43,11 +45,14 @@ import org.hibernate.type.ForeignKeyDirection;
* Implementation for {@code <one-to-one/>} mappings
*
* @author Gail Badner
* @author Steve Ebersole
*/
class OneToOneAttributeSourceImpl extends AbstractToOneAttributeSourceImpl {
private final JaxbOneToOneElement oneToOneElement;
private final List<RelationalValueSource> valueSources;
private final HibernateTypeSourceImpl typeSource;
private final String containingTableName;
private final List<RelationalValueSource> valueSources;
private final AttributeRole attributeRole;
private final AttributePath attributePath;
@ -60,6 +65,18 @@ class OneToOneAttributeSourceImpl extends AbstractToOneAttributeSourceImpl {
NaturalIdMutability naturalIdMutability) {
super( sourceMappingDocument, naturalIdMutability, oneToOneElement.getPropertyRef() );
this.oneToOneElement = oneToOneElement;
final String referencedClassName = oneToOneElement.getClazz();
JavaTypeDescriptor referencedClass = null;
if ( StringHelper.isNotEmpty( referencedClassName ) ) {
referencedClass = bindingContext().getJavaTypeDescriptorRepository().getType(
bindingContext().getJavaTypeDescriptorRepository().buildName(
bindingContext().qualifyClassName( oneToOneElement.getClazz() )
)
);
}
this.typeSource = new HibernateTypeSourceImpl( referencedClass );
this.containingTableName = logicalTableName;
this.valueSources = Helper.buildValueSources(
sourceMappingDocument(),
@ -122,6 +139,11 @@ class OneToOneAttributeSourceImpl extends AbstractToOneAttributeSourceImpl {
return attributeRole;
}
@Override
public HibernateTypeSourceImpl getTypeInformation() {
return typeSource;
}
@Override
public String getPropertyAccessorName() {
return oneToOneElement.getAccess();

View File

@ -26,10 +26,8 @@ package org.hibernate.metamodel.source.internal.hbm;
import java.util.List;
import java.util.Map;
import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor;
import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbColumnElement;
import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbElementElement;
import org.hibernate.metamodel.source.spi.HibernateTypeSource;
import org.hibernate.metamodel.source.spi.PluralAttributeElementSourceBasic;
import org.hibernate.metamodel.source.spi.RelationalValueSource;
import org.hibernate.metamodel.source.spi.SizeSource;
@ -41,13 +39,20 @@ import org.hibernate.metamodel.spi.PluralAttributeElementNature;
public class PluralAttributeElementSourceBasicImpl
extends AbstractHbmSourceNode
implements PluralAttributeElementSourceBasic {
private final HibernateTypeSourceImpl typeSource;
private final List<RelationalValueSource> valueSources;
private final HibernateTypeSource typeSource;
public PluralAttributeElementSourceBasicImpl(
MappingDocument sourceMappingDocument,
final JaxbElementElement elementElement) {
super( sourceMappingDocument );
final String typeName = extractTypeName( elementElement );
final Map<String, String> typeParams = elementElement.getType() != null
? Helper.extractParameters( elementElement.getType().getParam() )
: java.util.Collections.<String, String>emptyMap();
this.typeSource = new HibernateTypeSourceImpl( typeName, typeParams );
this.valueSources = Helper.buildValueSources(
sourceMappingDocument(),
new Helper.ValueSourcesAdapter() {
@ -96,10 +101,9 @@ public class PluralAttributeElementSourceBasicImpl
}
}
);
}
this.typeSource = new HibernateTypeSource() {
@Override
public String getName() {
private String extractTypeName(JaxbElementElement elementElement) {
if ( elementElement.getTypeAttribute() != null ) {
return elementElement.getTypeAttribute();
}
@ -111,19 +115,6 @@ public class PluralAttributeElementSourceBasicImpl
}
}
@Override
public Map<String, String> getParameters() {
return elementElement.getType() != null
? Helper.extractParameters( elementElement.getType().getParam() )
: java.util.Collections.<String, String>emptyMap();
}
@Override
public JavaTypeDescriptor getJavaType() {
return null;
}
};
}
@Override
public PluralAttributeElementNature getNature() {
return PluralAttributeElementNature.BASIC;
@ -150,7 +141,7 @@ public class PluralAttributeElementSourceBasicImpl
}
@Override
public HibernateTypeSource getExplicitHibernateTypeSource() {
public HibernateTypeSourceImpl getExplicitHibernateTypeSource() {
return typeSource;
}
}

View File

@ -25,16 +25,13 @@ package org.hibernate.metamodel.source.internal.hbm;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.hibernate.cfg.NamingStrategy;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.metamodel.internal.binder.Binder;
import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor;
import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbColumnElement;
import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbIndexElement;
import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbListIndexElement;
import org.hibernate.metamodel.source.spi.HibernateTypeSource;
import org.hibernate.metamodel.source.spi.PluralAttributeSequentialIndexSource;
import org.hibernate.metamodel.source.spi.RelationalValueSource;
import org.hibernate.metamodel.source.spi.SizeSource;
@ -43,19 +40,25 @@ import org.hibernate.metamodel.spi.PluralAttributeIndexNature;
/**
*
*/
public class PluralAttributeSequentialIndexSourceImpl extends AbstractHbmSourceNode implements
PluralAttributeSequentialIndexSource {
private final List< RelationalValueSource > valueSources;
private final HibernateTypeSource typeSource;
public class PluralAttributeSequentialIndexSourceImpl
extends AbstractHbmSourceNode
implements PluralAttributeSequentialIndexSource {
private final int base;
private final HibernateTypeSourceImpl typeSource;
private final List<RelationalValueSource> valueSources;
public PluralAttributeSequentialIndexSourceImpl(
MappingDocument sourceMappingDocument,
final JaxbListIndexElement indexElement) {
super( sourceMappingDocument );
valueSources = Helper.buildValueSources( sourceMappingDocument, new Helper.ValueSourcesAdapter() {
List< JaxbColumnElement > columnElements = indexElement.getColumn() == null ? Collections.EMPTY_LIST : Collections.singletonList( indexElement.getColumn() );
base = Integer.parseInt( indexElement.getBase() );
typeSource = new HibernateTypeSourceImpl( "integer", bindingContext().typeDescriptor( "int" ) );
valueSources = Helper.buildValueSources(
sourceMappingDocument,
new Helper.ValueSourcesAdapter() {
List<JaxbColumnElement> columnElements = indexElement.getColumn() == null
? Collections.<JaxbColumnElement>emptyList()
: Collections.singletonList( indexElement.getColumn() );
@Override
public String getColumnAttribute() {
@ -76,32 +79,22 @@ public class PluralAttributeSequentialIndexSourceImpl extends AbstractHbmSourceN
public boolean isIncludedInUpdateByDefault() {
return areValuesIncludedInUpdateByDefault();
}
} );
typeSource = new HibernateTypeSource() {
@Override
public String getName() {
return "integer";
}
@Override
public Map< String, String > getParameters() {
return java.util.Collections.< String, String >emptyMap();
}
@Override
public JavaTypeDescriptor getJavaType() {
return null;
}
};
base = Integer.parseInt( indexElement.getBase() );
);
}
public PluralAttributeSequentialIndexSourceImpl(
MappingDocument sourceMappingDocument,
final JaxbIndexElement indexElement) {
super( sourceMappingDocument );
valueSources = Helper.buildValueSources( sourceMappingDocument, new Helper.ValueSourcesAdapter() {
base = 0;
typeSource = new HibernateTypeSourceImpl(
StringHelper.isEmpty( indexElement.getType() ) ? "integer" : indexElement.getType(),
bindingContext().typeDescriptor( "int" )
);
valueSources = Helper.buildValueSources(
sourceMappingDocument,
new Helper.ValueSourcesAdapter() {
@Override
public String getColumnAttribute() {
return indexElement.getColumnAttribute();
@ -129,24 +122,8 @@ public class PluralAttributeSequentialIndexSourceImpl extends AbstractHbmSourceN
public boolean isIncludedInUpdateByDefault() {
return areValuesIncludedInUpdateByDefault();
}
} );
typeSource = new HibernateTypeSource() {
@Override
public String getName() {
return StringHelper.isEmpty( indexElement.getType() ) ? "integer" : indexElement.getType();
}
@Override
public Map< String, String > getParameters() {
return java.util.Collections.< String, String >emptyMap();
}
@Override
public JavaTypeDescriptor getJavaType() {
return null;
}
};
base = 0;
);
}
@Override
@ -185,7 +162,7 @@ public class PluralAttributeSequentialIndexSourceImpl extends AbstractHbmSourceN
}
@Override
public HibernateTypeSource getTypeInformation() {
public HibernateTypeSourceImpl getTypeInformation() {
return typeSource;
}

View File

@ -28,11 +28,9 @@ import java.util.List;
import java.util.Map;
import org.hibernate.mapping.PropertyGeneration;
import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor;
import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbColumnElement;
import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbPropertyElement;
import org.hibernate.metamodel.source.spi.AttributeSourceContainer;
import org.hibernate.metamodel.source.spi.HibernateTypeSource;
import org.hibernate.metamodel.source.spi.RelationalValueSource;
import org.hibernate.metamodel.source.spi.SingularAttributeSource;
import org.hibernate.metamodel.source.spi.SizeSource;
@ -49,7 +47,7 @@ import org.hibernate.metamodel.spi.SingularAttributeNature;
*/
class PropertyAttributeSourceImpl extends AbstractHbmSourceNode implements SingularAttributeSource {
private final JaxbPropertyElement propertyElement;
private final HibernateTypeSource typeSource;
private final HibernateTypeSourceImpl typeSource;
private final List<RelationalValueSource> valueSources;
private final NaturalIdMutability naturalIdMutability;
private final String containingTableName;
@ -65,30 +63,17 @@ class PropertyAttributeSourceImpl extends AbstractHbmSourceNode implements Singu
NaturalIdMutability naturalIdMutability) {
super( sourceMappingDocument );
this.propertyElement = propertyElement;
this.typeSource = new HibernateTypeSource() {
private final String name = propertyElement.getTypeAttribute() != null
final String name = propertyElement.getTypeAttribute() != null
? propertyElement.getTypeAttribute()
: propertyElement.getType() != null
? propertyElement.getType().getName()
: null;
private final Map<String, String> parameters = ( propertyElement.getType() != null )
final Map<String, String> parameters = ( propertyElement.getType() != null )
? Helper.extractParameters( propertyElement.getType().getParam() )
: null;
this.typeSource = new HibernateTypeSourceImpl( name, parameters );
@Override
public String getName() {
return name;
}
@Override
public Map<String, String> getParameters() {
return parameters;
}
@Override
public JavaTypeDescriptor getJavaType() {
return null;
}
};
this.containingTableName = logicalTableName;
this.valueSources = Helper.buildValueSources(
sourceMappingDocument(),
@ -162,7 +147,7 @@ class PropertyAttributeSourceImpl extends AbstractHbmSourceNode implements Singu
}
@Override
public HibernateTypeSource getTypeInformation() {
public HibernateTypeSourceImpl getTypeInformation() {
return typeSource;
}

View File

@ -28,11 +28,9 @@ import java.util.List;
import java.util.Map;
import org.hibernate.mapping.PropertyGeneration;
import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor;
import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbColumnElement;
import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbIdElement;
import org.hibernate.metamodel.source.spi.AttributeSourceContainer;
import org.hibernate.metamodel.source.spi.HibernateTypeSource;
import org.hibernate.metamodel.source.spi.RelationalValueSource;
import org.hibernate.metamodel.source.spi.SingularAttributeSource;
import org.hibernate.metamodel.source.spi.SizeSource;
@ -52,7 +50,7 @@ class SingularIdentifierAttributeSourceImpl
implements SingularAttributeSource {
private final JaxbIdElement idElement;
private final HibernateTypeSource typeSource;
private final HibernateTypeSourceImpl typeSource;
private final List<RelationalValueSource> valueSources;
private final AttributeRole attributeRole;
@ -64,31 +62,17 @@ class SingularIdentifierAttributeSourceImpl
final JaxbIdElement idElement) {
super( mappingDocument );
this.idElement = idElement;
this.typeSource = new HibernateTypeSource() {
private final String name = idElement.getTypeAttribute() != null
final String name = idElement.getTypeAttribute() != null
? idElement.getTypeAttribute()
: idElement.getType() != null
? idElement.getType().getName()
: null;
private final Map<String, String> parameters = ( idElement.getType() != null )
final Map<String, String> parameters = ( idElement.getType() != null )
? Helper.extractParameters( idElement.getType().getParam() )
: null;
this.typeSource = new HibernateTypeSourceImpl( name, parameters );
@Override
public String getName() {
return name;
}
@Override
public Map<String, String> getParameters() {
return parameters;
}
@Override
public JavaTypeDescriptor getJavaType() {
return null;
}
};
this.valueSources = Helper.buildValueSources(
sourceMappingDocument(),
new Helper.ValueSourcesAdapter() {
@ -145,7 +129,7 @@ class SingularIdentifierAttributeSourceImpl
}
@Override
public HibernateTypeSource getTypeInformation() {
public HibernateTypeSourceImpl getTypeInformation() {
return typeSource;
}

View File

@ -25,13 +25,10 @@ package org.hibernate.metamodel.source.internal.hbm;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.hibernate.internal.util.ValueHolder;
import org.hibernate.mapping.PropertyGeneration;
import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor;
import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbTimestampElement;
import org.hibernate.metamodel.source.spi.HibernateTypeSource;
import org.hibernate.metamodel.source.spi.RelationalValueSource;
import org.hibernate.metamodel.source.spi.ToolingHintSource;
import org.hibernate.metamodel.source.spi.VersionAttributeSource;
@ -49,6 +46,8 @@ class TimestampAttributeSourceImpl
extends AbstractHbmSourceNode
implements VersionAttributeSource {
private final JaxbTimestampElement timestampElement;
private final HibernateTypeSourceImpl typeSource;
private final List<RelationalValueSource> valueSources;
private final AttributePath attributePath;
@ -60,6 +59,13 @@ class TimestampAttributeSourceImpl
final JaxbTimestampElement timestampElement) {
super( mappingDocument );
this.timestampElement = timestampElement;
this.typeSource = new HibernateTypeSourceImpl(
"db".equals( timestampElement.getSource().value() )
? "dbtimestamp"
: "timestamp"
);
this.valueSources = Helper.buildValueSources(
sourceMappingDocument(),
new Helper.ValueSourcesAdapter() {
@ -83,22 +89,6 @@ class TimestampAttributeSourceImpl
this.attributeRole = rootEntitySource.getAttributeRoleBase().append( getName() );
}
private final HibernateTypeSource typeSource = new HibernateTypeSource() {
@Override
public String getName() {
return "db".equals( timestampElement.getSource() ) ? "dbtimestamp" : "timestamp";
}
@Override
public Map<String, String> getParameters() {
return null;
}
@Override
public JavaTypeDescriptor getJavaType() {
return null;
}
};
@Override
public String getName() {
return timestampElement.getName();
@ -115,7 +105,7 @@ class TimestampAttributeSourceImpl
}
@Override
public HibernateTypeSource getTypeInformation() {
public HibernateTypeSourceImpl getTypeInformation() {
return typeSource;
}

View File

@ -25,14 +25,11 @@ package org.hibernate.metamodel.source.internal.hbm;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.hibernate.internal.util.ValueHolder;
import org.hibernate.mapping.PropertyGeneration;
import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor;
import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbColumnElement;
import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbVersionElement;
import org.hibernate.metamodel.source.spi.HibernateTypeSource;
import org.hibernate.metamodel.source.spi.RelationalValueSource;
import org.hibernate.metamodel.source.spi.ToolingHintSource;
import org.hibernate.metamodel.source.spi.VersionAttributeSource;
@ -51,6 +48,8 @@ class VersionAttributeSourceImpl
extends AbstractHbmSourceNode
implements VersionAttributeSource {
private final JaxbVersionElement versionElement;
private final HibernateTypeSourceImpl typeSource;
private final List<RelationalValueSource> valueSources;
private final AttributePath attributePath;
@ -62,6 +61,13 @@ class VersionAttributeSourceImpl
final JaxbVersionElement versionElement) {
super( mappingDocument );
this.versionElement = versionElement;
this.typeSource = new HibernateTypeSourceImpl(
versionElement.getType() == null
? "integer"
: versionElement.getType()
);
this.valueSources = Helper.buildValueSources(
sourceMappingDocument(),
new Helper.ValueSourcesAdapter() {
@ -90,21 +96,6 @@ class VersionAttributeSourceImpl
this.attributeRole = rootEntitySource.getAttributeRoleBase().append( getName() );
}
private final HibernateTypeSource typeSource = new HibernateTypeSource() {
@Override
public String getName() {
return versionElement.getType() == null ? "integer" : versionElement.getType();
}
@Override
public Map<String, String> getParameters() {
return null;
}
@Override
public JavaTypeDescriptor getJavaType() {
return null;
}
};
@Override
public String getUnsavedValue() {
@ -127,7 +118,7 @@ class VersionAttributeSourceImpl
}
@Override
public HibernateTypeSource getTypeInformation() {
public HibernateTypeSourceImpl getTypeInformation() {
return typeSource;
}

View File

@ -23,10 +23,15 @@
*/
package org.hibernate.metamodel.source.spi;
import java.util.List;
/**
* Additional contract describing the source of an identifier mapping whose {@link #getNature() nature} 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.
* Additional contract describing the source of an identifier mapping whose
* {@link #getNature() nature} is
* {@link org.hibernate.id.EntityIdentifierNature#AGGREGATED_COMPOSITE}.
* <p/>
* This equates to an identifier which is made up of multiple values which are
* defined as part of a component/embedded; i.e. {@link javax.persistence.EmbeddedId}
*
* @author Strong Liu
* @author Steve Ebersole
@ -38,4 +43,11 @@ public interface AggregatedCompositeIdentifierSource extends CompositeIdentifier
* @return The identifier attribute source.
*/
public EmbeddedAttributeSource getIdentifierAttributeSource();
/**
* Obtain the mapping of attributes annotated with {@link javax.persistence.MapsId}.
*
* @return The MapsId sources.
*/
public List<MapsIdSource> getMapsIdSources();
}

View File

@ -26,6 +26,10 @@ package org.hibernate.metamodel.source.spi;
import org.hibernate.metamodel.spi.binding.IdentifierGeneratorDefinition;
/**
* Common contract for composite identifiers. Specific sub-types include aggregated
* (think {@link javax.persistence.EmbeddedId}) and non-aggregated (think
* {@link javax.persistence.IdClass}).
*
* @author Steve Ebersole
*/
public interface CompositeIdentifierSource extends IdentifierSource {

View File

@ -59,19 +59,4 @@ public interface IdentifierSource extends ToolingHintSourceContainer {
* @return the "unsaved" entity identifier value
*/
public String getUnsavedValue();
/**
* Retrieve the class specified as the {@link javax.persistence.IdClass}, if one.
*
* @return The class specified as the {@link javax.persistence.IdClass}, or {@code null} if none.
*/
public Class getLookupIdClass();
/**
* Obtain the property accessor name for the {@link javax.persistence.IdClass}, if one.
*
* @return The property accessor name for the {@link javax.persistence.IdClass}, or {@code null} if none.
**/
public String getIdClassPropertyAccessorName();
}

View File

@ -0,0 +1,33 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2014, 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.metamodel.source.spi;
import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor;
/**
* @author Steve Ebersole
*/
public interface JavaTypeDescriptorResolvable {
public void resolveJavaTypeDescriptor(JavaTypeDescriptor descriptor);
}

View File

@ -0,0 +1,46 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2014, 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.metamodel.source.spi;
/**
* Describes a relationship annotated with {@link javax.persistence.MapsId}
*
* @author Steve Ebersole
*/
public interface MapsIdSource {
/**
* Obtain the {@link javax.persistence.MapsId#value()} naming the attribute
* within the EmbeddedId mapped by this relationship.
*
* @return The corresponding id attribute name.
*/
public String getMappedIdAttributeName();
/**
* The attribute source information
*
* @return The association attribute information
*/
public ToOneAttributeSource getAssociationAttributeSource();
}

View File

@ -28,6 +28,8 @@ import java.util.List;
/**
* Additional contract describing the source of an identifier mapping whose {@link #getNature() nature} is
* {@link org.hibernate.id.EntityIdentifierNature#NON_AGGREGATED_COMPOSITE }.
* <p/>
* Think {@link javax.persistence.IdClass}
*
* @author Steve Ebersole
*/
@ -38,4 +40,11 @@ public interface NonAggregatedCompositeIdentifierSource extends CompositeIdentif
* @return The identifier attribute source.
*/
public List<SingularAttributeSource> getAttributeSourcesMakingUpIdentifier();
/**
* Retrieve the source information for the {@link javax.persistence.IdClass} definition
*
* @return The IdClass source information, or {@code null} if none.
*/
public EmbeddableSource getIdClassSource();
}

View File

@ -41,29 +41,9 @@ public interface ToOneAttributeSource
FetchableAttributeSource,
AssociationSource {
public MapsIdSource getMapsIdSource();
public boolean isUnique();
public boolean isUnWrapProxy();
ForeignKeyDirection getForeignKeyDirection();
public List<Binder.DefaultNamingStrategy> getDefaultNamingStrategies(final String entityName, final String tableName, final AttributeBinding referencedAttributeBinding);
/**
* Source for JPA {@link javax.persistence.MapsId} annotation information
*/
public static interface MapsIdSource {
/**
* Was a MapsId annotation present on the to-one?
*
* @return {@code true} if MapsId annotation was present; {@code false} otherwise.
*/
public boolean isDefined();
/**
* The {@link javax.persistence.MapsId#value()} value.
*
* @return The indicated name
*/
public String getLookupClassAttributeName();
}
}

View File

@ -25,11 +25,12 @@ package org.hibernate.metamodel.source.spi;
/**
* @author Gail Badner
* @author Steve Ebersole
*/
public interface ToOneAttributeSourceNatureResolver {
/**
* Perform any steps to completely resolve this attribute source.
* Perform any steps to completely resolve nature of this attribute source.
*
* If this is a {@link MappedByAssociationSource}, resolution must
* resolve the association owner, and this association must be added
@ -37,5 +38,11 @@ public interface ToOneAttributeSourceNatureResolver {
*
* @param context
*/
void resolveToOneAttributeSource(AttributeSourceResolutionContext context);
void resolveToOneAttributeSourceNature(AttributeSourceResolutionContext context);
/**
* Like {@link #resolveToOneAttributeSourceNature} but specifically for to-one
* attributes that are part of an identifier.
*/
void resolveToOneAttributeSourceNatureAsPartOfIdentifier();
}

View File

@ -32,11 +32,18 @@ public abstract class AbstractAttributeKey {
private final AbstractAttributeKey parent;
private final String property;
private final String fullPath;
private final int depth;
/**
* Constructor for the base AttributePath
*/
protected AbstractAttributeKey() {
this( null, "" );
}
/**
* Constructor for the base AttributeRole
*/
protected AbstractAttributeKey(String base) {
this( null, base );
}
@ -54,14 +61,20 @@ public abstract class AbstractAttributeKey {
else {
prefix = resolvedParent + getDelimiter();
}
depth = parent.getDepth() + 1;
}
else {
prefix = "";
depth = 0;
}
this.fullPath = prefix + property;
}
public int getDepth() {
return depth;
}
protected abstract char getDelimiter();
public abstract AbstractAttributeKey append(String property);

View File

@ -154,7 +154,7 @@ public abstract class AbstractPersistentAttributeMemberResolver implements Persi
}
@SuppressWarnings("RedundantIfStatement")
protected boolean isPersistable(FieldDescriptor fieldDescriptor) {
public static boolean isPersistable(FieldDescriptor fieldDescriptor) {
if ( Modifier.isTransient( fieldDescriptor.getModifiers() ) ) {
return false;
}
@ -188,7 +188,7 @@ public abstract class AbstractPersistentAttributeMemberResolver implements Persi
}
@SuppressWarnings("RedundantIfStatement")
protected boolean isPersistable(MethodDescriptor methodDescriptor) {
public static boolean isPersistable(MethodDescriptor methodDescriptor) {
if ( !methodDescriptor.getArgumentTypes().isEmpty() ) {
return false;
}

View File

@ -28,6 +28,11 @@ import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptorRepository;
import org.hibernate.metamodel.source.internal.annotations.JandexAccess;
import org.hibernate.metamodel.source.spi.MappingDefaults;
import org.hibernate.metamodel.source.spi.MetaAttributeContext;
import org.hibernate.metamodel.spi.domain.Aggregate;
import org.hibernate.metamodel.spi.domain.BasicType;
import org.hibernate.metamodel.spi.domain.Entity;
import org.hibernate.metamodel.spi.domain.Hierarchical;
import org.hibernate.metamodel.spi.domain.MappedSuperclass;
import org.hibernate.metamodel.spi.domain.Type;
import org.hibernate.service.ServiceRegistry;
@ -97,6 +102,53 @@ public abstract class BaseDelegatingBindingContext implements BindingContext {
return parent.quoteIdentifiersInContext();
}
@Override
public BasicType buildBasicDomainType(JavaTypeDescriptor typeDescriptor) {
return parent().buildBasicDomainType( typeDescriptor );
}
@Override
public MappedSuperclass buildMappedSuperclassDomainType(JavaTypeDescriptor typeDescriptor) {
return parent().buildMappedSuperclassDomainType( typeDescriptor );
}
@Override
public MappedSuperclass buildMappedSuperclassDomainType(
JavaTypeDescriptor typeDescriptor, Hierarchical superType) {
return parent().buildMappedSuperclassDomainType( typeDescriptor, superType );
}
@Override
public Aggregate buildComponentDomainType(JavaTypeDescriptor typeDescriptor) {
return parent().buildComponentDomainType( typeDescriptor );
}
@Override
public Aggregate buildComponentDomainType(
JavaTypeDescriptor typeDescriptor, Hierarchical superType) {
return parent().buildComponentDomainType( typeDescriptor, superType );
}
@Override
public Entity buildEntityDomainType(JavaTypeDescriptor typeDescriptor) {
return parent().buildEntityDomainType( typeDescriptor );
}
@Override
public Entity buildEntityDomainType(JavaTypeDescriptor typeDescriptor, Hierarchical superType) {
return parent().buildEntityDomainType( typeDescriptor, superType );
}
@Override
public Type locateDomainType(JavaTypeDescriptor typeDescriptor) {
return parent().locateDomainType( typeDescriptor );
}
@Override
public Type locateOrBuildDomainType(JavaTypeDescriptor typeDescriptor, boolean isAggregate) {
return parent().locateOrBuildDomainType( typeDescriptor, isAggregate );
}
@Override
public Type makeDomainType(String className) {
return parent.makeDomainType( className );

View File

@ -29,7 +29,12 @@ import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptorRepository;
import org.hibernate.metamodel.source.internal.annotations.JandexAccess;
import org.hibernate.metamodel.source.spi.MappingDefaults;
import org.hibernate.metamodel.source.spi.MetaAttributeContext;
import org.hibernate.metamodel.spi.domain.Aggregate;
import org.hibernate.metamodel.spi.domain.BasicType;
import org.hibernate.metamodel.spi.domain.Entity;
import org.hibernate.metamodel.spi.domain.Hierarchical;
import org.hibernate.metamodel.spi.domain.JavaClassReference;
import org.hibernate.metamodel.spi.domain.MappedSuperclass;
import org.hibernate.metamodel.spi.domain.Type;
import org.hibernate.service.ServiceRegistry;
@ -104,6 +109,27 @@ public interface BindingContext {
public JavaTypeDescriptor typeDescriptor(String name);
public BasicType buildBasicDomainType(JavaTypeDescriptor typeDescriptor);
public MappedSuperclass buildMappedSuperclassDomainType(JavaTypeDescriptor typeDescriptor);
public MappedSuperclass buildMappedSuperclassDomainType(JavaTypeDescriptor typeDescriptor, Hierarchical superType);
public Aggregate buildComponentDomainType(JavaTypeDescriptor typeDescriptor);
public Aggregate buildComponentDomainType(JavaTypeDescriptor typeDescriptor, Hierarchical superType);
public Entity buildEntityDomainType(JavaTypeDescriptor typeDescriptor);
public Entity buildEntityDomainType(JavaTypeDescriptor typeDescriptor, Hierarchical superType);
public Type locateDomainType(JavaTypeDescriptor typeDescriptor);
/**
* It is expected that Entity types already exist and are known. Therefore,
* in the "build" case, the expectation is that the domain type is either
* a basic type or a component.
*
* @param typeDescriptor The Java type descriptor
*
* @return The domain type.
*/
public Type locateOrBuildDomainType(JavaTypeDescriptor typeDescriptor, boolean isAggregate);
// todo : go away
/**

View File

@ -93,7 +93,7 @@ public abstract class AbstractAttributeBindingContainer implements AttributeBind
return attributeBindingMapInternal().values();
}
protected void collectRelationalValueBindings(RelationalValueBindingContainer relationalValueBindingContainer) {
public void collectRelationalValueBindings(RelationalValueBindingContainer relationalValueBindingContainer) {
for ( AttributeBinding subAttributeBinding : attributeBindings() ) {
if ( AbstractSingularAttributeBinding.class.isInstance( subAttributeBinding ) ) {
( (AbstractSingularAttributeBinding) subAttributeBinding ).collectRelationalValueBindings( relationalValueBindingContainer );

View File

@ -46,7 +46,7 @@ import org.hibernate.tuple.component.ComponentTuplizer;
*/
public abstract class AbstractEmbeddableBinding
extends AbstractAttributeBindingContainer
implements EmbeddableBinding {
implements EmbeddableBindingImplementor {
private final EntityBinding entityBinding;
private final AttributeContainer attributeContainer;
private final TableSpecification primaryTable;
@ -116,7 +116,8 @@ public abstract class AbstractEmbeddableBinding
protected abstract boolean isModifiable();
protected RelationalValueBindingContainer getRelationalValueBindingContainer() {
@Override
public RelationalValueBindingContainer getRelationalValueBindingContainer() {
final RelationalValueBindingContainer bindingContainer = new RelationalValueBindingContainer();
collectRelationalValueBindings( bindingContainer );
return bindingContainer;

View File

@ -42,7 +42,7 @@ public class BasicAttributeBinding
private final RelationalValueBindingContainer relationalValueBindingContainer;
private final PropertyGeneration generation;
BasicAttributeBinding(
public BasicAttributeBinding(
AttributeBindingContainer container,
SingularAttribute attribute,
List<RelationalValueBinding> relationalValueBindings,

View File

@ -27,6 +27,7 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor;
import org.hibernate.metamodel.source.spi.MetaAttributeContext;
import org.hibernate.metamodel.spi.PluralAttributeIndexNature;
import org.hibernate.metamodel.spi.domain.Aggregate;
@ -54,7 +55,7 @@ public class CompositePluralAttributeIndexBinding extends AbstractPluralAttribut
}
public EmbeddableBinding createCompositeAttributeBindingContainer(
Aggregate aggregate,
final Aggregate aggregate,
MetaAttributeContext metaAttributeContext,
SingularAttribute parentReference,
Class<? extends ComponentTuplizer> tuplizerClass) {
@ -83,6 +84,11 @@ public class CompositePluralAttributeIndexBinding extends AbstractPluralAttribut
public boolean isAggregated() {
return true;
}
@Override
public JavaTypeDescriptor getTypeDescriptor() {
return aggregate.getDescriptor();
}
};
return compositeAttributeBindingContainer;
}

View File

@ -23,6 +23,7 @@
*/
package org.hibernate.metamodel.spi.binding;
import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor;
import org.hibernate.metamodel.spi.domain.SingularAttribute;
import org.hibernate.tuple.component.ComponentTuplizer;
@ -33,6 +34,8 @@ public interface EmbeddableBinding extends AttributeBindingContainer {
boolean isAggregated();
SingularAttribute getParentReference();
JavaTypeDescriptor getTypeDescriptor();
@Override
Class<? extends ComponentTuplizer> getCustomTuplizerClass();
}

View File

@ -0,0 +1,32 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2014, 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.metamodel.spi.binding;
/**
* @author Steve Ebersole
*/
public interface EmbeddableBindingImplementor extends EmbeddableBinding {
public RelationalValueBindingContainer getRelationalValueBindingContainer();
public void collectRelationalValueBindings(RelationalValueBindingContainer relationalValueBindingContainer);
}

View File

@ -30,6 +30,7 @@ import java.util.Map;
import org.hibernate.engine.spi.CascadeStyle;
import org.hibernate.engine.spi.CascadeStyles;
import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor;
import org.hibernate.metamodel.source.spi.MetaAttributeContext;
import org.hibernate.metamodel.spi.AttributePath;
import org.hibernate.metamodel.spi.AttributeRole;
@ -48,9 +49,9 @@ public class EmbeddedAttributeBinding
extends AbstractSingularAttributeBinding
implements SingularNonAssociationAttributeBinding, Cascadeable, EmbeddableBindingContributor {
private final AbstractEmbeddableBinding embeddableBinding;
private final EmbeddableBindingImplementor embeddableBinding;
private EmbeddedAttributeBinding(
public EmbeddedAttributeBinding(
AttributeBindingContainer container,
SingularAttribute attribute,
String propertyAccessorName,
@ -60,7 +61,7 @@ public class EmbeddedAttributeBinding
MetaAttributeContext metaAttributeContext,
AttributeRole attributeRole,
AttributePath attributePath,
AbstractEmbeddableBinding embeddableBinding) {
EmbeddableBindingImplementor embeddableBinding) {
super(
container,
attribute,
@ -79,7 +80,7 @@ public class EmbeddedAttributeBinding
public static EmbeddedAttributeBinding createEmbeddedAttributeBinding(
final AttributeBindingContainer container,
SingularAttribute attribute,
final SingularAttribute attribute,
String propertyAccessorName,
boolean includedInOptimisticLocking,
boolean lazy,
@ -114,6 +115,11 @@ public class EmbeddedAttributeBinding
public boolean isAggregated() {
return true;
}
@Override
public JavaTypeDescriptor getTypeDescriptor() {
return attribute.getSingularAttributeType().getDescriptor();
}
};
if ( ! attribute.getSingularAttributeType().isAggregate() ) {
@ -134,61 +140,61 @@ public class EmbeddedAttributeBinding
embeddableBinding
);
}
// TODO: Get rid of this when non-aggregated composite IDs is no longer modelled as a EmbeddedAttributeBinding.
public static EmbeddedAttributeBinding createVirtualEmbeddedAttributeBinding(
final AttributeBindingContainer container,
SingularAttribute syntheticAttribute,
NaturalIdMutability naturalIdMutability,
MetaAttributeContext metaAttributeContext,
AttributeRole attributeRole,
AttributePath attributePath,
final List<SingularAttributeBinding> subAttributeBindings) {
AbstractEmbeddableBinding embeddableBinding = new AbstractEmbeddableBinding(
container.seekEntityBinding(),
(AttributeContainer) syntheticAttribute.getSingularAttributeType(),
container.getPrimaryTable(),
attributeRole,
attributePath,
metaAttributeContext,
null,
null) {
private final Map<String, AttributeBinding> attributeBindingMap = createUnmodifiableAttributeBindingMap( subAttributeBindings );
@Override
protected boolean isModifiable() {
return false;
}
@Override
protected Map<String, AttributeBinding> attributeBindingMapInternal() {
return this.attributeBindingMap;
}
@Override
public boolean isAggregated() {
return false;
}
};
if ( syntheticAttribute.getSingularAttributeType().isAggregate() ) {
throw new IllegalArgumentException(
"Cannot create a non-aggregated EmbeddableBinding with an aggregate attribute type"
);
}
return new EmbeddedAttributeBinding(
container,
syntheticAttribute,
"embedded", // TODO: get rid of "magic" string.
false,
false,
naturalIdMutability,
metaAttributeContext,
attributeRole,
attributePath,
embeddableBinding
);
}
//
// // TODO: Get rid of this when non-aggregated composite IDs is no longer modelled as a EmbeddedAttributeBinding.
// public static EmbeddedAttributeBinding createVirtualEmbeddedAttributeBinding(
// final AttributeBindingContainer container,
// SingularAttribute syntheticAttribute,
// NaturalIdMutability naturalIdMutability,
// MetaAttributeContext metaAttributeContext,
// AttributeRole attributeRole,
// AttributePath attributePath,
// final List<SingularAttributeBinding> subAttributeBindings) {
// AbstractEmbeddableBinding embeddableBinding = new AbstractEmbeddableBinding(
// container.seekEntityBinding(),
// (AttributeContainer) syntheticAttribute.getSingularAttributeType(),
// container.getPrimaryTable(),
// attributeRole,
// attributePath,
// metaAttributeContext,
// null,
// null) {
// private final Map<String, AttributeBinding> attributeBindingMap = createUnmodifiableAttributeBindingMap( subAttributeBindings );
//
// @Override
// protected boolean isModifiable() {
// return false;
// }
//
// @Override
// protected Map<String, AttributeBinding> attributeBindingMapInternal() {
// return this.attributeBindingMap;
// }
//
// @Override
// public boolean isAggregated() {
// return false;
// }
// };
//
// if ( syntheticAttribute.getSingularAttributeType().isAggregate() ) {
// throw new IllegalArgumentException(
// "Cannot create a non-aggregated EmbeddableBinding with an aggregate attribute type"
// );
// }
// return new EmbeddedAttributeBinding(
// container,
// syntheticAttribute,
// "embedded", // TODO: get rid of "magic" string.
// false,
// false,
// naturalIdMutability,
// metaAttributeContext,
// attributeRole,
// attributePath,
// embeddableBinding
// );
// }
private static Map<String, AttributeBinding> createUnmodifiableAttributeBindingMap(
List<SingularAttributeBinding> subAttributeBindings) {

View File

@ -32,6 +32,7 @@ import java.util.Map;
import org.hibernate.AssertionFailure;
import org.hibernate.MappingException;
import org.hibernate.id.EntityIdentifierNature;
import org.hibernate.internal.FilterConfiguration;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.collections.ArrayHelper;
@ -228,11 +229,7 @@ public class EntityBinding extends AbstractAttributeBindingContainer implements
TableSpecification table,
List<? extends Value> values,
boolean searchParent) {
SingularAttributeBinding attributeBinding = null;
SingularAttributeBinding idAttributeBinding = hierarchyDetails.getEntityIdentifier().getAttributeBinding();
if ( primaryTable.equals( table ) && idAttributeBinding.getValues().equals( values ) ) {
attributeBinding = hierarchyDetails.getEntityIdentifier().getAttributeBinding();
}
SingularAttributeBinding attributeBinding = locateAttributeBindingFromIdentifier( table, values );
if ( attributeBinding == null ) {
attributeBinding = locateAttributeBinding( table, values );
}
@ -242,6 +239,28 @@ public class EntityBinding extends AbstractAttributeBindingContainer implements
return attributeBinding;
}
private SingularAttributeBinding locateAttributeBindingFromIdentifier(
TableSpecification table,
List<? extends Value> values) {
if ( !primaryTable.equals( table ) ) {
return null;
}
final EntityIdentifier idInfo = hierarchyDetails.getEntityIdentifier();
final SingularAttributeBinding idAttributeBinding = idInfo.getEntityIdentifierBinding().getAttributeBinding();
final List<? extends Value> idAttributeValues = idAttributeBinding.getValues();
// order-insensitive check (column order handled later)
if ( idAttributeValues.size() == values.size()
&& idAttributeValues.containsAll( values ) ) {
return idAttributeBinding;
}
// if ( idAttributeValues.equals( values ) ) {
// return idAttributeBinding;
// }
return null;
}
public AttributeBinding locateAttributeBindingByPath(String path, boolean searchParent) {
if ( path == null ) {
throw new IllegalArgumentException( "path must be non-null." );
@ -519,27 +538,29 @@ public class EntityBinding extends AbstractAttributeBindingContainer implements
);
}
public EmbeddedAttributeBinding makeVirtualCompositeAttributeBinding(
SingularAttribute syntheticAttribute,
MetaAttributeContext metaAttributeContext,
List<SingularAttributeBinding> idAttributeBindings) {
EmbeddableBindingImplementor virtualEmbeddableBinding,
MetaAttributeContext metaAttributeContext) {
if ( !syntheticAttribute.isSynthetic() ) {
throw new AssertionFailure(
"Illegal attempt to create synthetic attribute binding from non-synthetic attribute reference"
);
}
// TODO: make sure all attributes are singular
final EmbeddedAttributeBinding binding = EmbeddedAttributeBinding.createVirtualEmbeddedAttributeBinding(
return new EmbeddedAttributeBinding(
this,
syntheticAttribute,
"embedded", // TODO: get rid of "magic" string.
false,
false,
NaturalIdMutability.NOT_NATURAL_ID,
metaAttributeContext,
getRoleBase(),
getPathBase(),
idAttributeBindings
virtualEmbeddableBinding
);
// registerAttributeBinding( binding );
return binding;
}
public BackRefAttributeBinding makeBackRefAttributeBinding(
@ -664,7 +685,9 @@ public class EntityBinding extends AbstractAttributeBindingContainer implements
public List<AttributeBinding> getNonIdAttributeBindings() {
final List<AttributeBinding> list = new ArrayList<AttributeBinding>();
for ( final AttributeBinding ab : attributeBindings() ) {
boolean isId = getHierarchyDetails().getEntityIdentifier().isIdentifierAttributeBinding( ab );
boolean isId = getHierarchyDetails().getEntityIdentifier()
.getEntityIdentifierBinding()
.isIdentifierAttributeBinding( ab );
if ( !isId ) {
list.add( ab );
}
@ -813,8 +836,10 @@ public class EntityBinding extends AbstractAttributeBindingContainer implements
private List<RelationalValueBinding> keyRelationalValueBindings;
public List<RelationalValueBinding> getKeyRelationalValueBindings() {
if(keyRelationalValueBindings == null){
keyRelationalValueBindings = getHierarchyDetails().getEntityIdentifier().getAttributeBinding().getRelationalValueBindings();
if ( keyRelationalValueBindings == null ) {
keyRelationalValueBindings = getHierarchyDetails().getEntityIdentifier()
.getEntityIdentifierBinding()
.getRelationalValueBindings();
}
return keyRelationalValueBindings;
}
@ -837,5 +862,4 @@ public class EntityBinding extends AbstractAttributeBindingContainer implements
}
return 0;
}
}

View File

@ -25,10 +25,10 @@ package org.hibernate.metamodel.spi.binding;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.Locale;
import java.util.Properties;
import org.hibernate.MappingException;
import org.hibernate.AnnotationException;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.id.CompositeNestedGeneratedValueGenerator;
@ -37,11 +37,15 @@ import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.PersistentIdentifierGenerator;
import org.hibernate.id.factory.IdentifierGeneratorFactory;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor;
import org.hibernate.metamodel.spi.relational.Column;
import org.hibernate.metamodel.spi.relational.Schema;
import org.hibernate.metamodel.spi.relational.Table;
import org.hibernate.metamodel.spi.relational.TableSpecification;
import org.hibernate.property.Setter;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.tuple.component.ComponentMetamodel;
import org.hibernate.type.Type;
import org.hibernate.type.TypeFactory;
import static org.hibernate.id.EntityIdentifierNature.AGGREGATED_COMPOSITE;
import static org.hibernate.id.EntityIdentifierNature.NON_AGGREGATED_COMPOSITE;
@ -58,6 +62,19 @@ import static org.hibernate.id.EntityIdentifierNature.SIMPLE;
* multi-attribute identifier - non-aggregated composite identifiers
* </li>
* </ul>
* <p/>
* The EntityIdentifier instance is created when the entity hierarchy is, but at
* that time we do not know all the information needed for interpreting the nature
* of the identifier. So at some point after creation, one of the prepare methods
* must be called:<ul>
* <li>{@link #prepareAsSimpleIdentifier}</li>
* <li>{@link #prepareAsAggregatedCompositeIdentifier}</li>
* <li>{@link #prepareAsNonAggregatedCompositeIdentifier}</li>
* </ul>
* Attempts to prepare the EntityIdentifier more than once will result in an
* exception. Attempts to access the information contained in the
* EntityIdentifier prior to binding will (generally) result in an
* exception.
*
* @author Steve Ebersole
* @author Hardy Ferentschik
@ -66,8 +83,7 @@ import static org.hibernate.id.EntityIdentifierNature.SIMPLE;
public class EntityIdentifier {
private final EntityBinding entityBinding;
private Binding binding;
private LookupClassBinding lookupClassBinding;
private BindingImplementor identifierBinding;
private IdentifierGenerator identifierGenerator;
@ -84,129 +100,158 @@ public class EntityIdentifier {
return entityBinding;
}
public void prepareAsSimpleIdentifier(
public SimpleIdentifierBinding prepareAsSimpleIdentifier(
SingularAttributeBinding attributeBinding,
IdentifierGeneratorDefinition identifierGeneratorDefinition,
String unsavedValue,
Class lookupIdClass,
String lookupIdClassAccessType) {
String unsavedValue) {
ensureNotBound();
this.entityIdentifierBinding = new SimpleAttributeIdentifierBindingImpl(
this.identifierBinding = new SimpleIdentifierBindingImpl(
this.getEntityBinding(),
attributeBinding,
identifierGeneratorDefinition,
unsavedValue
);
this.lookupClassBinding = new LookupClassBindingImpl( lookupIdClass, lookupIdClassAccessType );
return (SimpleIdentifierBinding) identifierBinding;
}
public void prepareAsAggregatedCompositeIdentifier(
public AggregatedCompositeIdentifierBinding prepareAsAggregatedCompositeIdentifier(
EmbeddedAttributeBinding attributeBinding,
IdentifierGeneratorDefinition identifierGeneratorDefinition,
String unsavedValue,
Class lookupIdClass,
String lookupIdClassAccessType) {
String unsavedValue) {
ensureNotBound();
this.entityIdentifierBinding = new AggregatedComponentIdentifierBindingImpl(
this.identifierBinding = new AggregatedCompositeIdentifierBindingImpl(
this.getEntityBinding(),
attributeBinding,
identifierGeneratorDefinition,
unsavedValue
);
this.lookupClassBinding = new LookupClassBindingImpl( lookupIdClass, lookupIdClassAccessType );
return (AggregatedCompositeIdentifierBinding) identifierBinding;
}
public void prepareAsNonAggregatedCompositeIdentifier(
EmbeddedAttributeBinding embeddedAttributeBinding,
public NonAggregatedCompositeIdentifierBinding prepareAsNonAggregatedCompositeIdentifier(
EmbeddableBindingImplementor virtualEmbeddableBinding,
EmbeddedAttributeBinding virtualAttributeBinding,
EmbeddableBindingImplementor idClassEmbeddableBinding,
IdentifierGeneratorDefinition identifierGeneratorDefinition,
String unsavedValue,
Class lookupIdClass,
String lookupIdClassAccessType) {
String unsavedValue) {
ensureNotBound();
this.entityIdentifierBinding = new NonAggregatedCompositeIdentifierBindingImpl(
embeddedAttributeBinding,
this.identifierBinding = new NonAggregatedCompositeIdentifierBindingImpl(
this.getEntityBinding(),
virtualEmbeddableBinding,
virtualAttributeBinding,
idClassEmbeddableBinding,
identifierGeneratorDefinition,
unsavedValue,
lookupIdClass,
lookupIdClassAccessType
unsavedValue
);
this.lookupClassBinding = new LookupClassBindingImpl( lookupIdClass, lookupIdClassAccessType );
return (NonAggregatedCompositeIdentifierBinding) identifierBinding;
}
public EntityIdentifierBinding getEntityIdentifierBinding() {
return entityIdentifierBinding;
}
public LookupClassBinding getLookupClassBinding() {
return lookupClassBinding;
}
public EntityIdentifierNature getNature() {
ensureBound();
return binding.getNature();
return identifierBinding.getNature();
}
public SingularAttributeBinding getAttributeBinding() {
public Binding getEntityIdentifierBinding() {
ensureBound();
return entityIdentifierBinding.getAttributeBinding();
return identifierBinding;
}
public boolean isIdentifierAttributeBinding(AttributeBinding attributeBinding) {
public boolean definesIdClass() {
ensureBound();
return entityIdentifierBinding.isIdentifierAttributeBinding( attributeBinding );
return getNature() == NON_AGGREGATED_COMPOSITE
&& ( (NonAggregatedCompositeIdentifierBinding) identifierBinding ).getIdClassMetadata() != null;
}
public boolean isCascadeDeleteEnabled() {
if ( getAttributeBinding() instanceof Cascadeable ) {
Cascadeable cascadeable = Cascadeable.class.cast( getAttributeBinding() );
cascadeable.getCascadeStyle();//todo
}
return false;
}
public String getUnsavedValue() {
ensureBound();
return binding.getUnsavedValue();
}
public boolean isNonAggregatedComposite() {
ensureBound();
return getNature() == EntityIdentifierNature.NON_AGGREGATED_COMPOSITE;
}
/**
* Get the Class of the {@link javax.persistence.IdClass} associated with the entity, if one.
*
* @deprecated Use {@link #getLookupClassBinding()} instead
*/
@Deprecated
public Class getIdClassClass() {
ensureBound();
return getLookupClassBinding().getIdClassType();
}
/**
* @deprecated Use {@link #getLookupClassBinding()} instead
*/
@Deprecated
public String getIdClassPropertyAccessorName() {
ensureBound();
return getLookupClassBinding().getAccessStrategy();
}
/**
* @deprecated Use {@link #getLookupClassBinding()} instead
*/
@Deprecated
public boolean isIdentifierMapper() {
ensureBound();
return isNonAggregatedComposite() && getLookupClassBinding().getIdClassType() != null;
}
// public IdClassMetadata getIdClassMetadata() {
// return idClassMetadata;
// }
//
//
// /**
// * @deprecated Use the {@link #getEntityIdentifierBinding} instead
// */
// @Deprecated
// public SingularAttributeBinding getAttributeBinding() {
// ensureBound();
// return identifierBinding.getAttributeBinding();
// }
//
// /**
// * @deprecated Use the {@link #getEntityIdentifierBinding} instead
// */
// @Deprecated
// public boolean isIdentifierAttributeBinding(AttributeBinding attributeBinding) {
// ensureBound();
// return identifierBinding.isIdentifierAttributeBinding( attributeBinding );
// }
//
// /**
// * @deprecated No real replacement; not even used atm
// */
// @Deprecated
// public boolean isCascadeDeleteEnabled() {
// if ( getAttributeBinding() instanceof Cascadeable ) {
// Cascadeable cascadeable = Cascadeable.class.cast( getAttributeBinding() );
// cascadeable.getCascadeStyle();//todo
// }
// return false;
// }
//
// /**
// * @deprecated Use the {@link #getEntityIdentifierBinding} instead
// */
// @Deprecated
// public String getUnsavedValue() {
// ensureBound();
// return identifierBinding.getUnsavedValue();
// }
//
// /**
// * @deprecated Check nature
// */
// @Deprecated
// public boolean isNonAggregatedComposite() {
// ensureBound();
// return getNature() == EntityIdentifierNature.NON_AGGREGATED_COMPOSITE;
// }
//
// /**
// * Get the Class of the {@link javax.persistence.IdClass} associated with the entity, if one.
// *
// * @deprecated Use {@link #getIdClassMetadata()} instead
// */
// @Deprecated
// public JavaTypeDescriptor getIdClassClass() {
// ensureBound();
// return getIdClassMetadata().getIdClassType();
// }
//
// /**
// * @deprecated Use {@link #getIdClassMetadata()} instead
// */
// @Deprecated
// public String getIdClassPropertyAccessorName() {
// ensureBound();
// return null;
// }
//
// /**
// * @deprecated Use {@link #getIdClassMetadata()} instead
// */
// @Deprecated
// public boolean isIdentifierMapper() {
// ensureBound();
// return isNonAggregatedComposite() && getIdClassMetadata().getIdClassType() != null;
// }
// todo do we really need this createIdentifierGenerator and how do we make sure the getter is not called too early
// maybe some sort of visitor pattern here!? (HF)
public IdentifierGenerator createIdentifierGenerator(IdentifierGeneratorFactory factory, Properties properties) {
ensureBound();
if ( identifierGenerator == null ) {
identifierGenerator = entityIdentifierBinding.createIdentifierGenerator( factory, properties );
identifierGenerator = identifierBinding.createIdentifierGenerator( factory, properties );
}
return identifierGenerator;
}
@ -228,117 +273,218 @@ public class EntityIdentifier {
}
}
protected boolean isBound() {
return entityIdentifierBinding != null;
public boolean isBound() {
return identifierBinding != null;
}
public int getColumnCount() {
ensureBound();
return entityIdentifierBinding.getColumnCount();
}
/**
* For now simply models {@link javax.persistence.IdClass} information. Ultimately should
* handle {@link javax.persistence.MapsId} information as well.
* @deprecated Use {@link #getEntityIdentifierBinding()} instead
*/
public static interface LookupClassBinding {
public boolean definedIdClass();
public Class getIdClassType();
public String getAccessStrategy();
@Deprecated
public int getColumnCount() {
ensureBound();
return identifierBinding.getColumnCount();
}
private static class LookupClassBindingImpl implements LookupClassBinding {
private final Class idClassType;
private final String accessStrategy;
// todo : expose IdClassMetadata just from NonAggregatedCompositeIdentifierBindingImpl ?
// - that is the only place it has relevance
private LookupClassBindingImpl(Class idClassType, String accessStrategy) {
this.idClassType = idClassType;
this.accessStrategy = idClassType == null ? null : accessStrategy;
/**
* Models {@link javax.persistence.IdClass} information.
*/
public static interface IdClassMetadata {
public EmbeddableBinding getEmbeddableBinding();
public JavaTypeDescriptor getIdClassType();
public String getAccessStrategy(String attributeName);
public Type getHibernateType(ServiceRegistry serviceRegistry, TypeFactory typeFactory);
}
private static class IdClassMetadataImpl implements IdClassMetadata {
private final EmbeddableBinding idClassBinding;
private Type type;
private IdClassMetadataImpl(EmbeddableBinding idClassBinding) {
this.idClassBinding = idClassBinding;
}
@Override
public boolean definedIdClass() {
return getIdClassType() != null;
public EmbeddableBinding getEmbeddableBinding() {
return idClassBinding;
}
@Override
public Class getIdClassType() {
return idClassType;
public JavaTypeDescriptor getIdClassType() {
return idClassBinding.getTypeDescriptor();
}
@Override
public String getAccessStrategy() {
return accessStrategy;
public String getAccessStrategy(String attributeName) {
final AttributeBinding attributeBinding = idClassBinding.locateAttributeBinding( attributeName );
if ( attributeBinding == null ) {
throw new AnnotationException(
String.format(
Locale.ENGLISH,
"Unable to locate IdClass attribute by that name : %s, %s",
getIdClassType().getName().toString(),
attributeName
)
);
}
return attributeBinding.getPropertyAccessorName();
}
@Override
public Type getHibernateType(ServiceRegistry serviceRegistry, TypeFactory typeFactory) {
if ( type == null && idClassBinding != null ) {
type = typeFactory.embeddedComponent(
new ComponentMetamodel( serviceRegistry, idClassBinding, true, false )
);
}
return type;
}
}
private abstract class EntityIdentifierBinding {
private final EntityIdentifierNature nature;
private final SingularAttributeBinding identifierAttributeBinding;
public static interface Binding {
public EntityIdentifierNature getNature();
public SingularAttributeBinding getAttributeBinding();
public String getUnsavedValue();
public List<RelationalValueBinding> getRelationalValueBindings();
public boolean isIdentifierAttributeBinding(AttributeBinding attributeBinding);
public Type getHibernateType();
}
public static interface AttributeBasedIdentifierBinding extends Binding {
}
public static interface SimpleIdentifierBinding extends AttributeBasedIdentifierBinding {
}
public static interface AggregatedCompositeIdentifierBinding extends AttributeBasedIdentifierBinding {
@Override
public EmbeddedAttributeBinding getAttributeBinding();
}
public static interface NonAggregatedCompositeIdentifierBinding extends Binding {
/**
* Obtain the virtual Embeddable representation of the identifier. This
* maps to the entity class, but handles just the id attributes.
*
* @return The virtual Embeddable binding
*/
public EmbeddableBinding getVirtualEmbeddableBinding();
/**
* Obtain metadata about the IdClass, if one.
*
* @return Metadata about the defined IdClass, or {@code null} if
* no IdClass was defined.
*/
public IdClassMetadata getIdClassMetadata();
/**
* Builds the Type for the "virtual embeddable". See
* {@link IdClassMetadata#getHibernateType} for obtaining the Type
* relating to the IdClass
*
* Caches the Type reference after first call.
*
* @param serviceRegistry The ServiceRegistry
* @param typeFactory The TypeFactory
*
* @return The resolved Type
*/
public Type getHibernateType(ServiceRegistry serviceRegistry, TypeFactory typeFactory);
}
private static interface BindingImplementor extends Binding {
public int getColumnCount();
public IdentifierGenerator createIdentifierGenerator(
IdentifierGeneratorFactory identifierGeneratorFactory,
Properties properties);
}
private static abstract class AbstractIdentifierBinding implements BindingImplementor {
private final EntityBinding entityBinding;
private final IdentifierGeneratorDefinition identifierGeneratorDefinition;
private final String unsavedValue;
protected AbstractIdentifierBinding(
EntityBinding entityBinding,
IdentifierGeneratorDefinition identifierGeneratorDefinition,
String unsavedValue) {
this.entityBinding = entityBinding;
this.identifierGeneratorDefinition = identifierGeneratorDefinition;
this.unsavedValue = unsavedValue;
}
public EntityBinding getEntityBinding() {
return entityBinding;
}
@Override
public String getUnsavedValue() {
return unsavedValue;
}
public IdentifierGeneratorDefinition getGeneratorDefinition() {
return identifierGeneratorDefinition;
}
}
private static abstract class AbstractAttributeBasedIdentifierBinding
extends AbstractIdentifierBinding
implements AttributeBasedIdentifierBinding {
private final SingularAttributeBinding identifierAttributeBinding;
private final int columnCount;
protected EntityIdentifierBinding(
EntityIdentifierNature nature,
protected AbstractAttributeBasedIdentifierBinding(
EntityBinding entityBinding,
SingularAttributeBinding identifierAttributeBinding,
IdentifierGeneratorDefinition identifierGeneratorDefinition,
String unsavedValue) {
this.nature = nature;
super( entityBinding, identifierGeneratorDefinition, unsavedValue );
this.identifierAttributeBinding = identifierAttributeBinding;
this.identifierGeneratorDefinition = identifierGeneratorDefinition;
this.unsavedValue = unsavedValue;
// Configure primary key in relational model
final List<RelationalValueBinding> relationalValueBindings = identifierAttributeBinding.getRelationalValueBindings();
this.columnCount = relationalValueBindings.size();
for ( final RelationalValueBinding valueBinding : relationalValueBindings ) {
entityBinding.getPrimaryTable().getPrimaryKey().addColumn( (Column) valueBinding.getValue() );
entityBinding.getPrimaryTable()
.getPrimaryKey()
.addColumn( (Column) valueBinding.getValue() );
}
}
public EntityIdentifierNature getNature() {
return nature;
}
@Override
public SingularAttributeBinding getAttributeBinding() {
return identifierAttributeBinding;
}
public String getUnsavedValue() {
return unsavedValue;
}
protected IdentifierGeneratorDefinition getIdentifierGeneratorDefinition() {
return identifierGeneratorDefinition;
}
@Override
public int getColumnCount() {
return columnCount;
}
@Override
public List<RelationalValueBinding> getRelationalValueBindings() {
return getAttributeBinding().getRelationalValueBindings();
}
@Override
public boolean isIdentifierAttributeBinding(AttributeBinding attributeBinding) {
return getAttributeBinding().equals( attributeBinding );
}
@Override
public IdentifierGenerator createIdentifierGenerator(
IdentifierGeneratorFactory identifierGeneratorFactory,
Properties properties) {
final List<RelationalValueBinding> relationalValueBindings =
getAttributeBinding().getRelationalValueBindings();
// TODO: If multiple @Column annotations exist within an id's
// @Columns, we need a more solid solution than simply grabbing
// the first one to get the TableSpecification.
final RelationalValueBinding relationalValueBinding = relationalValueBindings.get( 0 );
final TableSpecification table = relationalValueBinding.getTable();
if ( !Column.class.isInstance( relationalValueBinding.getValue() ) ) {
throw new MappingException(
"Cannot create an IdentifierGenerator because the value is not a column: " +
relationalValueBinding.getValue().toLoggableString()
);
}
final List<RelationalValueBinding> valueBindings = getAttributeBinding().getRelationalValueBindings();
final TableSpecification table = getEntityBinding().getPrimaryTable();
Properties params = new Properties();
params.putAll( properties );
@ -356,8 +502,8 @@ public class EntityIdentifier {
}
}
params.setProperty( IdentifierGenerator.ENTITY_NAME, entityBinding.getEntityName() );
params.setProperty( IdentifierGenerator.JPA_ENTITY_NAME, entityBinding.getJpaEntityName() );
params.setProperty( IdentifierGenerator.ENTITY_NAME, getEntityBinding().getEntityName() );
params.setProperty( IdentifierGenerator.JPA_ENTITY_NAME, getEntityBinding().getJpaEntityName() );
//init the table here instead of earlier, so that we can get a quoted table name
//TODO: would it be better to simply pass the qualified table name, instead of
@ -365,38 +511,33 @@ public class EntityIdentifier {
String tableName = table.getQualifiedName( identifierGeneratorFactory.getDialect() );
params.setProperty( PersistentIdentifierGenerator.TABLE, tableName );
if ( valueBindings.size() == 1 ) {
final RelationalValueBinding rvBinding = valueBindings.get( 0 );
if ( Column.class.isInstance( rvBinding.getValue() ) ) {
final Column pkColumn = (Column) rvBinding.getValue();
params.setProperty(
PersistentIdentifierGenerator.PK,
( (Column) relationalValueBinding.getValue() ).getColumnName().getText(
identifierGeneratorFactory.getDialect()
)
);
if ( entityBinding.getHierarchyDetails().getInheritanceType() != InheritanceType.TABLE_PER_CLASS ) {
params.setProperty( PersistentIdentifierGenerator.TABLES, tableName );
} else {
params.setProperty(
PersistentIdentifierGenerator.TABLES,
resolveTableNames( identifierGeneratorFactory.getDialect(), entityBinding )
pkColumn.getColumnName().getText( identifierGeneratorFactory.getDialect() )
);
}
params.putAll( getIdentifierGeneratorDefinition().getParameters() );
}
if ( getEntityBinding().getHierarchyDetails().getInheritanceType() != InheritanceType.TABLE_PER_CLASS ) {
params.setProperty( PersistentIdentifierGenerator.TABLES, tableName );
}
else {
params.setProperty(
PersistentIdentifierGenerator.TABLES,
resolveTableNames( identifierGeneratorFactory.getDialect(), getEntityBinding() )
);
}
params.putAll( getGeneratorDefinition().getParameters() );
return identifierGeneratorFactory.createIdentifierGenerator(
getIdentifierGeneratorDefinition().getStrategy(),
getGeneratorDefinition().getStrategy(),
getAttributeBinding().getHibernateTypeDescriptor().getResolvedTypeMapping(),
params
);
}
}
private class SimpleAttributeIdentifierBindingImpl extends EntityIdentifierBinding {
SimpleAttributeIdentifierBindingImpl(
SingularAttributeBinding identifierAttributeBinding,
IdentifierGeneratorDefinition identifierGeneratorDefinition,
String unsavedValue) {
super( SIMPLE, identifierAttributeBinding, identifierGeneratorDefinition, unsavedValue );
}
}
private String resolveTableNames(Dialect dialect, EntityBinding entityBinding) {
EntityBinding[] ebs = entityBinding.getPostOrderSubEntityBindingClosure();
@ -426,12 +567,38 @@ public class EntityIdentifier {
return null;
}
private class AggregatedComponentIdentifierBindingImpl extends EntityIdentifierBinding {
AggregatedComponentIdentifierBindingImpl(
@Override
public Type getHibernateType() {
return getAttributeBinding().getHibernateTypeDescriptor().getResolvedTypeMapping();
}
}
private class SimpleIdentifierBindingImpl
extends AbstractAttributeBasedIdentifierBinding
implements SimpleIdentifierBinding {
SimpleIdentifierBindingImpl(
EntityBinding entityBinding,
SingularAttributeBinding identifierAttributeBinding,
IdentifierGeneratorDefinition identifierGeneratorDefinition,
String unsavedValue) {
super( entityBinding, identifierAttributeBinding, identifierGeneratorDefinition, unsavedValue );
}
@Override
public EntityIdentifierNature getNature() {
return SIMPLE;
}
}
private class AggregatedCompositeIdentifierBindingImpl
extends AbstractAttributeBasedIdentifierBinding
implements AggregatedCompositeIdentifierBinding {
AggregatedCompositeIdentifierBindingImpl(
EntityBinding entityBinding,
EmbeddedAttributeBinding identifierAttributeBinding,
IdentifierGeneratorDefinition identifierGeneratorDefinition,
String unsavedValue) {
super( AGGREGATED_COMPOSITE, identifierAttributeBinding, identifierGeneratorDefinition, unsavedValue );
super( entityBinding, identifierAttributeBinding, identifierGeneratorDefinition, unsavedValue );
if ( ! identifierAttributeBinding.getEmbeddableBinding().isAggregated() ) {
throw new IllegalArgumentException(
String.format(
@ -442,20 +609,31 @@ public class EntityIdentifier {
}
}
@Override
public EntityIdentifierNature getNature() {
return AGGREGATED_COMPOSITE;
}
@Override
public EmbeddedAttributeBinding getAttributeBinding() {
return (EmbeddedAttributeBinding) super.getAttributeBinding();
}
@Override
public IdentifierGenerator createIdentifierGenerator(
IdentifierGeneratorFactory factory,
Properties properties) {
if ( entityBinding.getSuperEntityBinding() != null ) {
throw new AssertionError( "Creating an identifier generator for a component on a subclass." );
}
final EntityIdentifier entityIdentifier = entityBinding.getHierarchyDetails().getEntityIdentifier();
final boolean hasCustomGenerator = ! "assigned".equals( getIdentifierGeneratorDefinition().getStrategy() );
final boolean hasCustomGenerator = ! "assigned".equals( getGeneratorDefinition().getStrategy() );
if ( hasCustomGenerator ) {
return super.createIdentifierGenerator(
factory, properties
);
}
// IMPL NOTE : See the javadoc discussion on CompositeNestedGeneratedValueGenerator wrt the
// various scenarios for which we need to account here
// we have the "@EmbeddedId" / <composite-id name="idName"/> case
@ -471,98 +649,83 @@ public class EntityIdentifier {
}
}
private static class ValueGenerationPlan implements CompositeNestedGeneratedValueGenerator.GenerationPlan {
private final String propertyName;
private final IdentifierGenerator subGenerator;
private final Setter injector;
private class NonAggregatedCompositeIdentifierBindingImpl
extends AbstractIdentifierBinding
implements NonAggregatedCompositeIdentifierBinding {
private final EmbeddableBindingImplementor virtualEmbeddableBinding;
private final EmbeddedAttributeBinding virtualAttributeBinding;
public ValueGenerationPlan(
String propertyName,
IdentifierGenerator subGenerator,
Setter injector) {
this.propertyName = propertyName;
this.subGenerator = subGenerator;
this.injector = injector;
}
private final IdClassMetadata idClassMetadata;
/**
* {@inheritDoc}
*/
public void execute(SessionImplementor session, Object incomingObject, Object injectionContext) {
final Object generatedValue = subGenerator.generate( session, incomingObject );
injector.set( injectionContext, generatedValue, session.getFactory() );
}
private Type type;
public void registerPersistentGenerators(Map generatorMap) {
if ( PersistentIdentifierGenerator.class.isInstance( subGenerator ) ) {
generatorMap.put( ( (PersistentIdentifierGenerator) subGenerator ).generatorKey(), subGenerator );
}
}
}
private class NonAggregatedCompositeIdentifierBindingImpl extends EntityIdentifierBinding {
private final Class externalAggregatingClass;
private final String externalAggregatingPropertyAccessorName;
NonAggregatedCompositeIdentifierBindingImpl(
EmbeddedAttributeBinding identifierAttributeBinding,
public NonAggregatedCompositeIdentifierBindingImpl(
EntityBinding entityBinding,
EmbeddableBindingImplementor virtualEmbeddableBinding,
EmbeddedAttributeBinding virtualAttributeBinding,
EmbeddableBindingImplementor idClassEmbeddableBinding,
IdentifierGeneratorDefinition identifierGeneratorDefinition,
String unsavedValue,
Class externalAggregatingClass,
String externalAggregatingPropertyAccessorName) {
super( NON_AGGREGATED_COMPOSITE, identifierAttributeBinding, identifierGeneratorDefinition, unsavedValue );
if ( identifierAttributeBinding.getEmbeddableBinding().isAggregated() ) {
throw new IllegalArgumentException(
String.format(
"identifierAttributeBinding must be a non-aggregated EmbeddedAttributeBinding: %s",
identifierAttributeBinding.getAttribute().getName()
)
);
}
this.externalAggregatingClass = externalAggregatingClass;
this.externalAggregatingPropertyAccessorName = externalAggregatingPropertyAccessorName;
if ( identifierAttributeBinding.getEmbeddableBinding().attributeBindingSpan() == 0 ) {
throw new MappingException(
"A composite ID has 0 attributes for " + entityBinding.getEntityName()
);
}
for ( AttributeBinding attributeBinding : identifierAttributeBinding.getEmbeddableBinding().attributeBindings() ) {
if ( ! attributeBinding.getAttribute().isSingular() ) {
throw new MappingException(
String.format(
"The composite ID for [%s] contains an attribute [%s} that is plural.",
entityBinding.getEntityName(),
attributeBinding.getAttribute().getName()
)
);
}
String unsavedValue) {
super( entityBinding, identifierGeneratorDefinition, unsavedValue );
this.virtualEmbeddableBinding = virtualEmbeddableBinding;
this.virtualAttributeBinding = virtualAttributeBinding;
this.idClassMetadata = idClassEmbeddableBinding == null
? null
: new IdClassMetadataImpl( idClassEmbeddableBinding );
final List<RelationalValueBinding> relationalValueBindings = virtualAttributeBinding.getRelationalValueBindings();
for ( final RelationalValueBinding valueBinding : relationalValueBindings ) {
entityBinding.getPrimaryTable()
.getPrimaryKey()
.addColumn( (Column) valueBinding.getValue() );
}
}
private EmbeddedAttributeBinding getNonAggregatedCompositeAttributeBinding() {
return (EmbeddedAttributeBinding) getAttributeBinding();
@Override
public EntityIdentifierNature getNature() {
return NON_AGGREGATED_COMPOSITE;
}
@Override
public EmbeddableBinding getVirtualEmbeddableBinding() {
return virtualEmbeddableBinding;
}
@Override
public SingularAttributeBinding getAttributeBinding() {
return virtualAttributeBinding;
}
@Override
public IdClassMetadata getIdClassMetadata() {
return idClassMetadata;
}
@Override
public List<RelationalValueBinding> getRelationalValueBindings() {
return virtualAttributeBinding.getRelationalValueBindings();
}
@Override
public int getColumnCount() {
return getRelationalValueBindings().size();
}
@Override
public boolean isIdentifierAttributeBinding(AttributeBinding attributeBinding) {
if ( !isIdentifierMapper() && getNonAggregatedCompositeAttributeBinding().equals( attributeBinding ) ) {
if ( virtualAttributeBinding.equals( attributeBinding ) ) {
return true;
}
for ( AttributeBinding idAttributeBindings : getNonAggregatedCompositeAttributeBinding().getEmbeddableBinding().attributeBindings() ) {
if ( idAttributeBindings.equals( attributeBinding ) ) {
for ( AttributeBinding embAttrBinding : virtualEmbeddableBinding.attributeBindings() ) {
if ( embAttrBinding.equals( attributeBinding ) ) {
return true;
}
}
return false;
}
public Class getIdClassClass() {
return externalAggregatingClass;
}
public String getIdClassPropertyAccessorName() {
return externalAggregatingPropertyAccessorName;
}
@Override
public IdentifierGenerator createIdentifierGenerator(
IdentifierGeneratorFactory factory,
Properties properties) {
@ -589,14 +752,56 @@ public class EntityIdentifier {
// TODO: set up IdentifierGenerator for non-assigned sub-attributes
return new CompositeNestedGeneratedValueGenerator( locator );
}
@Override
public Type getHibernateType(ServiceRegistry serviceRegistry, TypeFactory typeFactory) {
if ( type == null ) {
type = typeFactory.embeddedComponent(
new ComponentMetamodel(
serviceRegistry,
virtualEmbeddableBinding,
true,
false
)
);
}
return type;
}
public static interface Binding {
public EntityIdentifierNature getNature();
public String getUnsavedValue();
public IdentifierGeneratorDefinition getGeneratorDefinition();
@Override
public Type getHibernateType() {
return type;
}
}
// private static class ValueGenerationPlan implements CompositeNestedGeneratedValueGenerator.GenerationPlan {
// private final String propertyName;
// private final IdentifierGenerator subGenerator;
// private final Setter injector;
//
// public ValueGenerationPlan(
// String propertyName,
// IdentifierGenerator subGenerator,
// Setter injector) {
// this.propertyName = propertyName;
// this.subGenerator = subGenerator;
// this.injector = injector;
// }
//
// /**
// * {@inheritDoc}
// */
// public void execute(SessionImplementor session, Object incomingObject, Object injectionContext) {
// final Object generatedValue = subGenerator.generate( session, incomingObject );
// injector.set( injectionContext, generatedValue, session.getFactory() );
// }
//
// public void registerPersistentGenerators(Map generatorMap) {
// if ( PersistentIdentifierGenerator.class.isInstance( subGenerator ) ) {
// generatorMap.put( ( (PersistentIdentifierGenerator) subGenerator ).generatorKey(), subGenerator );
// }
// }
// }
}

View File

@ -23,7 +23,9 @@
*/
package org.hibernate.metamodel.spi.binding;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor;
@ -41,6 +43,8 @@ public class HibernateTypeDescriptor {
private Type resolvedTypeMapping;
private JavaTypeDescriptor typeDescriptor;
private List<ResolutionListener> resolutionListeners;
public String getExplicitTypeName() {
return explicitTypeName;
}
@ -71,6 +75,10 @@ public class HibernateTypeDescriptor {
public void setResolvedTypeMapping(Type resolvedTypeMapping) {
this.resolvedTypeMapping = resolvedTypeMapping;
if ( this.resolvedTypeMapping != null ) {
notifyResolutionListeners();
}
}
public void copyFrom(HibernateTypeDescriptor hibernateTypeDescriptor) {
@ -79,4 +87,25 @@ public class HibernateTypeDescriptor {
getTypeParameters().putAll( hibernateTypeDescriptor.getTypeParameters() );
setResolvedTypeMapping( hibernateTypeDescriptor.getResolvedTypeMapping() );
}
public static interface ResolutionListener {
public void typeResolved(HibernateTypeDescriptor typeDescriptor);
}
public void addResolutionListener(ResolutionListener listener) {
if ( resolutionListeners == null ) {
resolutionListeners = new ArrayList<ResolutionListener>();
}
resolutionListeners.add( listener );
}
private void notifyResolutionListeners() {
if ( resolutionListeners == null ) {
return;
}
for ( ResolutionListener resolutionListener : resolutionListeners ) {
resolutionListener.typeResolved( this );
}
}
}

View File

@ -27,6 +27,7 @@ import java.util.LinkedHashMap;
import java.util.Map;
import org.hibernate.engine.spi.CascadeStyle;
import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor;
import org.hibernate.metamodel.source.spi.MetaAttributeContext;
import org.hibernate.metamodel.spi.PluralAttributeElementNature;
import org.hibernate.metamodel.spi.PluralAttributeNature;
@ -78,7 +79,7 @@ public class PluralAttributeElementBindingEmbedded
}
public EmbeddableBinding createBindingContainer(
Aggregate aggregate,
final Aggregate aggregate,
MetaAttributeContext metaAttributeContext,
SingularAttribute parentReference,
Class<? extends ComponentTuplizer> tuplizerClass) {
@ -115,6 +116,11 @@ public class PluralAttributeElementBindingEmbedded
public boolean isAggregated() {
return true;
}
@Override
public JavaTypeDescriptor getTypeDescriptor() {
return aggregate.getDescriptor();
}
};
return embeddableBinding;

View File

@ -48,9 +48,9 @@ public class RelationalValueBindingContainer {
}
public List<RelationalValueBinding> relationalValueBindings() {
return isListModifiable ?
Collections.unmodifiableList( relationalValueBindings ) :
relationalValueBindings;
return isListModifiable
? Collections.unmodifiableList( relationalValueBindings )
: relationalValueBindings;
}
public List<Value> values() {

View File

@ -187,7 +187,9 @@ public abstract class AbstractAttributeContainer implements AttributeContainer,
protected void addAttribute(Attribute attribute) {
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 : " + getName()
);
}
attributeSet.add( attribute );
}

View File

@ -2147,8 +2147,12 @@ public abstract class AbstractEntityPersister
}
protected static boolean isIdentifierAttributeBinding(final AttributeBinding prop){
return prop.getContainer().seekEntityBinding().getHierarchyDetails().getEntityIdentifier().isIdentifierAttributeBinding( prop );
protected static boolean isIdentifierAttributeBinding(final AttributeBinding prop) {
return prop.getContainer().seekEntityBinding()
.getHierarchyDetails()
.getEntityIdentifier()
.getEntityIdentifierBinding()
.isIdentifierAttributeBinding( prop );
}
private void internalInitSubclassPropertyAliasesMap(String path, AttributeBinding[] attributeBindings) {
@ -2289,16 +2293,39 @@ public abstract class AbstractEntityPersister
private void initIdentifierPropertyPaths(Mapping mapping) throws MappingException {
String idProp = getIdentifierPropertyName();
if ( idProp != null ) {
propertyMapping.initPropertyPaths( idProp, getIdentifierType(), getIdentifierColumnNames(),
getIdentifierColumnReaders(), getIdentifierColumnReaderTemplates(), null, mapping );
propertyMapping.initPropertyPaths(
idProp,
getIdentifierType(),
getIdentifierColumnNames(),
getIdentifierColumnReaders(),
getIdentifierColumnReaderTemplates(),
null,
mapping
);
}
if ( entityMetamodel.getIdentifierProperty().isEmbedded() ) {
propertyMapping.initPropertyPaths( null, getIdentifierType(), getIdentifierColumnNames(),
getIdentifierColumnReaders(), getIdentifierColumnReaderTemplates(), null, mapping );
propertyMapping.initPropertyPaths(
null,
getIdentifierType(),
getIdentifierColumnNames(),
getIdentifierColumnReaders(),
getIdentifierColumnReaderTemplates(),
null,
mapping
);
}
if ( ! entityMetamodel.hasNonIdentifierPropertyNamedId() ) {
propertyMapping.initPropertyPaths( ENTITY_ID, getIdentifierType(), getIdentifierColumnNames(),
getIdentifierColumnReaders(), getIdentifierColumnReaderTemplates(), null, mapping );
propertyMapping.initPropertyPaths(
ENTITY_ID,
getIdentifierType(),
getIdentifierColumnNames(),
getIdentifierColumnReaders(),
getIdentifierColumnReaderTemplates(),
null,
mapping
);
}
}

View File

@ -24,6 +24,7 @@
package org.hibernate.tuple;
import org.hibernate.engine.spi.IdentifierValue;
import org.hibernate.engine.spi.SyntheticAttributeHelper;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.PostInsertIdentifierGenerator;
import org.hibernate.type.Type;
@ -87,7 +88,7 @@ public class IdentifierProperty extends AbstractAttribute implements IdentifierA
boolean hasIdentifierMapper,
IdentifierValue unsavedValue,
IdentifierGenerator identifierGenerator) {
super( null, type );
super( SyntheticAttributeHelper.SYNTHETIC_COMPOSITE_ID_ATTRIBUTE_NAME, type );
this.virtual = true;
this.embedded = embedded;
this.hasIdentifierMapper = hasIdentifierMapper;

View File

@ -32,6 +32,7 @@ import org.hibernate.InstantiationException;
import org.hibernate.PropertyNotFoundException;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.bytecode.spi.ReflectionOptimizer;
import org.hibernate.id.EntityIdentifierNature;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.metamodel.spi.binding.EmbeddableBinding;
@ -61,13 +62,17 @@ public class PojoInstantiator implements Instantiator, Serializable {
EmbeddableBinding embeddableBinding,
boolean isIdentifierMapper,
ReflectionOptimizer.InstantiationOptimizer optimizer) {
final ClassLoaderService cls = serviceRegistry.getService( ClassLoaderService.class );
if ( isIdentifierMapper ) {
final EntityIdentifier entityIdentifier =
embeddableBinding.seekEntityBinding().getHierarchyDetails().getEntityIdentifier();
this.mappedClass = entityIdentifier.getLookupClassBinding().getIdClassType();
final EntityIdentifier.NonAggregatedCompositeIdentifierBinding idBinding =
(EntityIdentifier.NonAggregatedCompositeIdentifierBinding) entityIdentifier.getEntityIdentifierBinding();
this.mappedClass = cls.classForName(
idBinding.getIdClassMetadata().getIdClassType().getName().toString()
);
}
else {
final ClassLoaderService cls = serviceRegistry.getService( ClassLoaderService.class );
this.mappedClass = cls.classForName(
embeddableBinding.getAttributeContainer().getDescriptor().getName().toString()
);
@ -102,7 +107,7 @@ public class PojoInstantiator implements Instantiator, Serializable {
entityBinding.getProxyInterfaceType().getName().toString()
);
}
this.embeddedIdentifier = entityBinding.getHierarchyDetails().getEntityIdentifier().isNonAggregatedComposite();
this.embeddedIdentifier = entityBinding.getHierarchyDetails().getEntityIdentifier().getNature() == EntityIdentifierNature.NON_AGGREGATED_COMPOSITE;
this.optimizer = optimizer;
try {

View File

@ -45,8 +45,8 @@ import org.hibernate.metamodel.spi.binding.AbstractPluralAttributeBinding;
import org.hibernate.metamodel.spi.binding.AttributeBinding;
import org.hibernate.metamodel.spi.binding.BasicAttributeBinding;
import org.hibernate.metamodel.spi.binding.Cascadeable;
import org.hibernate.metamodel.spi.binding.EmbeddedAttributeBinding;
import org.hibernate.metamodel.spi.binding.EntityBinding;
import org.hibernate.metamodel.spi.binding.EntityIdentifier;
import org.hibernate.metamodel.spi.binding.Fetchable;
import org.hibernate.metamodel.spi.binding.SingularAttributeBinding;
import org.hibernate.persister.entity.EntityPersister;
@ -132,25 +132,24 @@ public final class PropertyFactory {
IdentifierGenerator generator,
SessionFactoryImplementor sessionFactory) {
final SingularAttributeBinding attributeBinding =
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.
// see org.hibernate.metamodel.spi.domain.AbstractAttributeContainer.locateOrCreateVirtualAttribute()
final String mappedUnsavedValue = mappedEntity.getHierarchyDetails().getEntityIdentifier().getUnsavedValue();
final EntityIdentifier idInfo = mappedEntity.getHierarchyDetails().getEntityIdentifier();
final SingularAttributeBinding attributeBinding = idInfo.getEntityIdentifierBinding().getAttributeBinding();
final String mappedUnsavedValue = idInfo.getEntityIdentifierBinding().getUnsavedValue();
if ( idInfo.getNature() == EntityIdentifierNature.NON_AGGREGATED_COMPOSITE ) {
final EntityIdentifier.NonAggregatedCompositeIdentifierBinding idBinding
= (EntityIdentifier.NonAggregatedCompositeIdentifierBinding) idInfo.getEntityIdentifierBinding();
if ( mappedEntity.getHierarchyDetails().getEntityIdentifier().getNature()
== EntityIdentifierNature.NON_AGGREGATED_COMPOSITE ) {
// the "attribute" will need to be virtual since there is no single
// attribute identifying the identifier
final ComponentType type = sessionFactory.getTypeResolver().getTypeFactory().component(
new ComponentMetamodel(
sessionFactory.getServiceRegistry(),
( (EmbeddedAttributeBinding) attributeBinding ).getEmbeddableBinding(),
idBinding.getVirtualEmbeddableBinding(),
true,
mappedEntity.getHierarchyDetails().getEntityIdentifier().getLookupClassBinding().definedIdClass()
idInfo.definesIdClass()
)
);
@ -167,17 +166,22 @@ public final class PropertyFactory {
return new IdentifierProperty(
type,
true,
mappedEntity.getHierarchyDetails().getEntityIdentifier().getLookupClassBinding().definedIdClass(),
idInfo.definesIdClass(),
unsavedValue,
generator
);
}
else {
final Type type = attributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping();
final EntityIdentifier.AttributeBasedIdentifierBinding idBinding
= (EntityIdentifier.AttributeBasedIdentifierBinding) idInfo.getEntityIdentifierBinding();
final SingularAttributeBinding idAttributeBinding = idBinding.getAttributeBinding();
final Type type = idAttributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping();
final IdentifierValue unsavedValue = UnsavedValueFactory.getUnsavedIdentifierValue(
mappedUnsavedValue,
getGetter( attributeBinding, sessionFactory ),
getGetter( idAttributeBinding, sessionFactory ),
type,
getConstructor(
mappedEntity,
@ -186,7 +190,7 @@ public final class PropertyFactory {
);
return new IdentifierProperty(
attributeBinding.getAttribute().getName(),
idAttributeBinding.getAttribute().getName(),
null,
type,
false,

View File

@ -67,14 +67,19 @@ public class PojoComponentTuplizer extends AbstractComponentTuplizer {
boolean isIdentifierMapper) {
super( serviceRegistry, component, isIdentifierMapper );
final EntityIdentifier entityIdentifier =
component.seekEntityBinding().getHierarchyDetails().getEntityIdentifier();
final ClassLoaderService cls = serviceRegistry.getService( ClassLoaderService.class );
if ( isIdentifierMapper ) {
this.componentClass = entityIdentifier.getLookupClassBinding().getIdClassType();
final EntityIdentifier idInfo = component.seekEntityBinding()
.getHierarchyDetails()
.getEntityIdentifier();
final EntityIdentifier.NonAggregatedCompositeIdentifierBinding idBinding =
(EntityIdentifier.NonAggregatedCompositeIdentifierBinding) idInfo.getEntityIdentifierBinding();
final EntityIdentifier.IdClassMetadata idClassMetadata = idBinding.getIdClassMetadata();
this.componentClass = cls.classForName(
idClassMetadata.getIdClassType().getName().toString()
);
}
else {
final ClassLoaderService cls = serviceRegistry.getService( ClassLoaderService.class );
this.componentClass = cls.classForName(
component.getAttributeContainer().getDescriptor().getName().toString()
);
@ -198,20 +203,37 @@ public class PojoComponentTuplizer extends AbstractComponentTuplizer {
// TODO: when compositeAttributeBinding is wrapped for an identifier mapper
// there will be no need for PropertyFactory.getIdentifierMapperGetter()
// and PropertyFactory.getIdentifierMapperSetter
// this.componentClass is not set yet because of ctor calls - yucky bad design
if ( isIdentifierMapper ) {
// HACK ALERT: when isIdentifierMapper is true, the entity identifier
// must be completely bound when this method is called.
final EntityIdentifier entityIdentifier =
embeddableBinding.seekEntityBinding().getHierarchyDetails().getEntityIdentifier();
// (steve w/ metamodel) : utterly confused here. What exactly is the
// thing we are trying to accomplish here? it *seems* like we
// are trying to build a getter for the id class (isIdentifierMapper == true),
// so why do we pass in the composite representing the virtual,
// non-aggregated id? why not just pass in the IdClass composite?
// so confusing :)
final EntityIdentifier idInfo = embeddableBinding.seekEntityBinding()
.getHierarchyDetails()
.getEntityIdentifier();
final EntityIdentifier.NonAggregatedCompositeIdentifierBinding idBinding =
(EntityIdentifier.NonAggregatedCompositeIdentifierBinding) idInfo.getEntityIdentifierBinding();
final EntityIdentifier.IdClassMetadata idClassMetadata = idBinding.getIdClassMetadata();
final Class componentClass = classForName(
idClassMetadata.getIdClassType().getName().toString()
);
return getGetter(
entityIdentifier.getLookupClassBinding().getIdClassType(),
componentClass,
attributeBinding.getAttribute().getName(),
PropertyAccessorFactory.getPropertyAccessor( entityIdentifier.getLookupClassBinding().getAccessStrategy() )
PropertyAccessorFactory.getPropertyAccessor(
idClassMetadata.getAccessStrategy( attributeBinding.getAttribute().getName() )
)
);
}
else {
final ClassLoaderService cls = serviceRegistry().getService( ClassLoaderService.class );
final Class clazz = cls.classForName(
final Class clazz = classForName(
embeddableBinding.getAttributeContainer().getDescriptor().getName().toString()
);
return getGetter(
@ -228,16 +250,25 @@ public class PojoComponentTuplizer extends AbstractComponentTuplizer {
boolean isIdentifierMapper,
AttributeBinding attributeBinding) {
if ( isIdentifierMapper ) {
// HACK ALERT: when isIdentifierMapper is true, the entity identifier
// must be completely bound when this method is called.
final EntityIdentifier entityIdentifier =
embeddableBinding.seekEntityBinding().getHierarchyDetails().getEntityIdentifier();
return getSetter(
entityIdentifier.getLookupClassBinding().getIdClassType(),
attributeBinding.getAttribute().getName(),
PropertyAccessorFactory.getPropertyAccessor( entityIdentifier.getLookupClassBinding().getAccessStrategy() )
);
// see discussion about confusing in #buildGetter
final EntityIdentifier idInfo = embeddableBinding.seekEntityBinding()
.getHierarchyDetails()
.getEntityIdentifier();
final EntityIdentifier.NonAggregatedCompositeIdentifierBinding idBinding =
(EntityIdentifier.NonAggregatedCompositeIdentifierBinding) idInfo.getEntityIdentifierBinding();
final EntityIdentifier.IdClassMetadata idClassMetadata = idBinding.getIdClassMetadata();
final Class componentClass = classForName(
idClassMetadata.getIdClassType().getName().toString()
);
return getSetter(
componentClass,
attributeBinding.getAttribute().getName(),
PropertyAccessorFactory.getPropertyAccessor(
idClassMetadata.getAccessStrategy( attributeBinding.getAttribute().getName() )
)
);
}
else {
final Class clazz = classForName(

View File

@ -43,6 +43,7 @@ import org.hibernate.event.spi.EventType;
import org.hibernate.event.spi.PersistEvent;
import org.hibernate.event.spi.PersistEventListener;
import org.hibernate.id.Assigned;
import org.hibernate.id.EntityIdentifierNature;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.loader.PropertyPath;
@ -60,6 +61,7 @@ import org.hibernate.type.ComponentType;
import org.hibernate.type.CompositeType;
import org.hibernate.type.EntityType;
import org.hibernate.type.Type;
import org.hibernate.type.TypeFactory;
/**
@ -95,9 +97,12 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
this.serviceRegistry = serviceRegistry;
this.entityMetamodel = entityMetamodel;
if ( !entityMetamodel.getIdentifierProperty().isVirtual() ) {
idGetter = buildPropertyGetter( mappingInfo.getHierarchyDetails().getEntityIdentifier().getAttributeBinding() );
idSetter = buildPropertySetter( mappingInfo.getHierarchyDetails().getEntityIdentifier().getAttributeBinding() );
final EntityIdentifier idInfo = mappingInfo.getHierarchyDetails().getEntityIdentifier();
if ( idInfo.getNature() != EntityIdentifierNature.NON_AGGREGATED_COMPOSITE ) {
final EntityIdentifier.AttributeBasedIdentifierBinding identifierBinding =
(EntityIdentifier.AttributeBasedIdentifierBinding) idInfo.getEntityIdentifierBinding();
idGetter = buildPropertyGetter( identifierBinding.getAttributeBinding() );
idSetter = buildPropertySetter( identifierBinding.getAttributeBinding() );
}
else {
idGetter = null;
@ -134,23 +139,19 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
proxyFactory = null;
}
final EntityIdentifier entityIdentifier = mappingInfo.getHierarchyDetails().getEntityIdentifier();
if ( !entityIdentifier.isIdentifierMapper() ) {
if ( !idInfo.definesIdClass() ) {
identifierMapperType = null;
mappedIdentifierValueMarshaller = null;
}
else {
identifierMapperType = (CompositeType) entityMetamodel.getIdentifierProperty().getType();
// TODO: this only deals with normal IdClass; still need to deal with MapsId
final EntityIdentifier.NonAggregatedCompositeIdentifierBinding identifierBinding =
(EntityIdentifier.NonAggregatedCompositeIdentifierBinding) idInfo.getEntityIdentifierBinding();
mappedIdentifierValueMarshaller = buildMappedIdentifierValueMarshaller(
(ComponentType) identifierMapperType,
(ComponentType) mappingInfo
.getHierarchyDetails()
.getEntityIdentifier()
.getAttributeBinding()
.getHibernateTypeDescriptor()
.getResolvedTypeMapping()
(ComponentType) identifierBinding.getHibernateType()
);
}
}

View File

@ -192,13 +192,11 @@ public class PojoEntityTuplizer extends AbstractEntityTuplizer {
proxyInterfaces,
proxyGetIdentifierMethod,
proxySetIdentifierMethod,
entityBinding.getHierarchyDetails().getEntityIdentifier().isIdentifierMapper()
? ( CompositeType ) entityBinding
.getHierarchyDetails()
entityBinding.getHierarchyDetails().getEntityIdentifier().definesIdClass()
? ( CompositeType ) entityBinding.getHierarchyDetails()
.getEntityIdentifier()
.getAttributeBinding()
.getHibernateTypeDescriptor()
.getResolvedTypeMapping()
.getEntityIdentifierBinding()
.getHibernateType()
: null
);
}

View File

@ -50,8 +50,7 @@ public class EmbeddedIdTest extends BaseAnnotationBindingTestCase {
public void testEmbeddable() {
EntityBinding binding = getEntityBinding( User.class );
EntityIdentifier identifier = binding.getHierarchyDetails().getEntityIdentifier();
assertTrue( !identifier.isNonAggregatedComposite() );
assertEquals( identifier.getNature(), EntityIdentifierNature.AGGREGATED_COMPOSITE );
assertEquals( EntityIdentifierNature.AGGREGATED_COMPOSITE, identifier.getNature() );
}
@Entity

View File

@ -33,6 +33,7 @@ import org.hibernate.annotations.GenericGenerator;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.dialect.H2Dialect;
import org.hibernate.id.Assigned;
import org.hibernate.id.EntityIdentifierNature;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.IdentityGenerator;
import org.hibernate.id.MultipleHiLoPerTableGenerator;
@ -73,8 +74,7 @@ public class IdentifierGeneratorTest extends BaseAnnotationBindingTestCase {
IdentifierGenerator generator =identifier.getIdentifierGenerator();
assertNotNull( generator );
assertEquals( "Wrong generator", Assigned.class, generator.getClass() );
assertFalse( identifier.isNonAggregatedComposite() );
assertEquals( EntityIdentifierNature.SIMPLE, identifier.getNature() );
}
@Entity

View File

@ -135,24 +135,27 @@ public class InheritanceBindingTest extends BaseAnnotationBindingTestCase {
}
assertEquals( 1, directAttributeBindings.size() );
assertSame(
noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(),
noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getEntityIdentifierBinding().getAttributeBinding(),
directAttributeBindings.iterator().next()
);
assertEquals( 1, noInheritanceEntityBinding.getAttributeBindingClosureSpan() );
Iterator<AttributeBinding> iterator = noInheritanceEntityBinding.attributeBindings().iterator();
assertTrue( iterator.hasNext() );
assertSame( noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(), iterator.next() );
assertSame(
noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getEntityIdentifierBinding().getAttributeBinding(),
iterator.next()
);
assertFalse( iterator.hasNext() );
AttributeBinding[] attributeBindings = noInheritanceEntityBinding.getAttributeBindingClosure();
assertTrue( attributeBindings.length > 0 );
int index =0;
assertSame( noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(), attributeBindings[index++] );
assertSame( noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getEntityIdentifierBinding().getAttributeBinding(), attributeBindings[index++] );
assertFalse( index < attributeBindings.length );
attributeBindings = noInheritanceEntityBinding.getEntitiesAttributeBindingClosure();
index = 0;
assertTrue( attributeBindings.length > 0 );
assertSame( noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(), attributeBindings[index++] );
assertSame( noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getEntityIdentifierBinding().getAttributeBinding(), attributeBindings[index++] );
assertFalse( index < attributeBindings.length );
}

View File

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

View File

@ -74,7 +74,7 @@ public abstract class AbstractUnsavedValueTests extends BaseUnitTestCase {
MetadataImpl metadata = (MetadataImpl) sources.buildMetadata();
EntityBinding entityBinding = metadata.getEntityBinding( EntityWithAssignedId.class.getName() );
// Generator is explicitly "assigned", so unsaved ID value should be "undefined"
assertEquals( "undefined", entityBinding.getHierarchyDetails().getEntityIdentifier().getUnsavedValue() );
assertEquals( "undefined", entityBinding.getHierarchyDetails().getEntityIdentifier().getEntityIdentifierBinding().getUnsavedValue() );
}
@Test
@ -84,7 +84,7 @@ public abstract class AbstractUnsavedValueTests extends BaseUnitTestCase {
MetadataImpl metadata = (MetadataImpl) sources.buildMetadata();
EntityBinding entityBinding = metadata.getEntityBinding( EntityWithSequenceId.class.getName() );
// Generator is explicitly "increment", so unsaved ID value should be null
assertEquals( null, entityBinding.getHierarchyDetails().getEntityIdentifier().getUnsavedValue() );
assertEquals( null, entityBinding.getHierarchyDetails().getEntityIdentifier().getEntityIdentifierBinding().getUnsavedValue() );
}
@Test
@ -94,7 +94,7 @@ public abstract class AbstractUnsavedValueTests extends BaseUnitTestCase {
MetadataImpl metadata = (MetadataImpl) sources.buildMetadata();
EntityBinding entityBinding = metadata.getEntityBinding( EntityWithVersion.class.getName() );
// Generator is explicitly "assigned", so unsaved ID value should be "undefined"
assertEquals( "undefined", entityBinding.getHierarchyDetails().getEntityIdentifier().getUnsavedValue() );
assertEquals( "undefined", entityBinding.getHierarchyDetails().getEntityIdentifier().getEntityIdentifierBinding().getUnsavedValue() );
}
@Test
@ -104,7 +104,7 @@ public abstract class AbstractUnsavedValueTests extends BaseUnitTestCase {
MetadataImpl metadata = (MetadataImpl) sources.buildMetadata();
EntityBinding entityBinding = metadata.getEntityBinding( EntityWithTimestamp.class.getName() );
// Generator is explicitly "assigned", so unsaved ID value should be "undefined"
assertEquals( "undefined", entityBinding.getHierarchyDetails().getEntityIdentifier().getUnsavedValue() );
assertEquals( "undefined", entityBinding.getHierarchyDetails().getEntityIdentifier().getEntityIdentifierBinding().getUnsavedValue() );
}
public abstract void addSourcesForAssignedIdDefaultUnsavedValue(MetadataSources sources);

View File

@ -107,9 +107,7 @@ public class SimpleValueBindingTests extends BaseUnitTestCase {
entityBinding.getHierarchyDetails().getEntityIdentifier().prepareAsSimpleIdentifier(
attributeBinding,
new IdentifierGeneratorDefinition( "assigned", "assigned", Collections.<String,String>emptyMap() ),
"null",
null,
null
"null"
);
}

View File

@ -44,7 +44,7 @@ public class UnsavedValueHbmTests extends AbstractUnsavedValueTests {
MetadataImpl metadata = (MetadataImpl) sources.buildMetadata();
EntityBinding entityBinding = metadata.getEntityBinding( EntityWithAssignedId.class.getName() );
// unsaved-value was mapped as "any"; that should be used, regardless of ID generator.
assertEquals( "any", entityBinding.getHierarchyDetails().getEntityIdentifier().getUnsavedValue() );
assertEquals( "any", entityBinding.getHierarchyDetails().getEntityIdentifier().getEntityIdentifierBinding().getUnsavedValue() );
}
@Test
@ -54,7 +54,7 @@ public class UnsavedValueHbmTests extends AbstractUnsavedValueTests {
MetadataImpl metadata = (MetadataImpl) sources.buildMetadata();
EntityBinding entityBinding = metadata.getEntityBinding( EntityWithSequenceId.class.getName() );
// unsaved-value was mapped as "null"; that should be used, regardless of ID generator.
assertEquals( "null", entityBinding.getHierarchyDetails().getEntityIdentifier().getUnsavedValue() );
assertEquals( "null", entityBinding.getHierarchyDetails().getEntityIdentifier().getEntityIdentifierBinding().getUnsavedValue() );
}
@Test

View File

@ -99,7 +99,7 @@ public abstract class AbstractBasicCollectionBindingTests extends BaseUnitTestCa
BagType.class,
Collection.class,
String.class,
entityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(),
entityBinding.getHierarchyDetails().getEntityIdentifier().getEntityIdentifierBinding().getAttributeBinding(),
Identifier.toIdentifier( "EntityWithBasicCollections_theBag" ),
Identifier.toIdentifier( "owner_id" ),
FetchTiming.IMMEDIATE,
@ -112,7 +112,7 @@ public abstract class AbstractBasicCollectionBindingTests extends BaseUnitTestCa
SetType.class,
Set.class,
String.class,
entityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(),
entityBinding.getHierarchyDetails().getEntityIdentifier().getEntityIdentifierBinding().getAttributeBinding(),
Identifier.toIdentifier( "EntityWithBasicCollections_theSet" ),
Identifier.toIdentifier( "pid" ),
FetchTiming.EXTRA_LAZY,

View File

@ -42,6 +42,7 @@ import org.junit.Test;
import static org.hibernate.metamodel.spi.binding.BindingHelper.locateAttributeBinding;
import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
@ -78,8 +79,8 @@ public class BasicEmbeddedIdTest extends BaseAnnotationBindingTestCase {
EntityIdentifierNature.AGGREGATED_COMPOSITE,
courseBinding.getHierarchyDetails().getEntityIdentifier().getNature()
);
assertNull(
courseBinding.getHierarchyDetails().getEntityIdentifier().getLookupClassBinding().getIdClassType()
assertFalse(
courseBinding.getHierarchyDetails().getEntityIdentifier().definesIdClass()
);
// Course should be interpreted as defining 2 attributes: `key` and `title`
@ -94,7 +95,10 @@ public class BasicEmbeddedIdTest extends BaseAnnotationBindingTestCase {
"key",
EmbeddedAttributeBinding.class
);
SingularAttributeBinding identifierAttribute = courseBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding();
SingularAttributeBinding identifierAttribute = courseBinding.getHierarchyDetails()
.getEntityIdentifier()
.getEntityIdentifierBinding()
.getAttributeBinding();
// NOTE : assertSame() does '=='
assertSame( keyBinding, identifierAttribute );

View File

@ -34,7 +34,9 @@ import org.hibernate.metamodel.spi.binding.BasicAttributeBinding;
import org.hibernate.metamodel.spi.binding.EmbeddableBinding;
import org.hibernate.metamodel.spi.binding.EmbeddedAttributeBinding;
import org.hibernate.metamodel.spi.binding.EntityBinding;
import org.hibernate.metamodel.spi.binding.EntityIdentifier;
import org.hibernate.metamodel.spi.binding.RelationalValueBinding;
import org.hibernate.type.StringType;
import org.hibernate.testing.junit4.BaseAnnotationBindingTestCase;
import org.hibernate.testing.junit4.Resources;
@ -72,7 +74,7 @@ public class BasicIdClassTest extends BaseAnnotationBindingTestCase {
@Test
@Resources( annotatedClasses = Course.class )
public void testBasicUsage() {
public void testBasicUsage() throws Exception {
// get the Course entity binding
EntityBinding courseBinding = getEntityBinding( Course.class );
assertNotNull( courseBinding );
@ -80,10 +82,14 @@ public class BasicIdClassTest extends BaseAnnotationBindingTestCase {
EntityIdentifierNature.NON_AGGREGATED_COMPOSITE,
courseBinding.getHierarchyDetails().getEntityIdentifier().getNature()
);
Class idClassClass = courseBinding.getHierarchyDetails().getEntityIdentifier()
.getLookupClassBinding()
.getIdClassType();
assertNotNull( idClassClass );
EntityIdentifier.NonAggregatedCompositeIdentifierBinding identifierBinding = assertTyping(
EntityIdentifier.NonAggregatedCompositeIdentifierBinding.class,
courseBinding.getHierarchyDetails().getEntityIdentifier().getEntityIdentifierBinding()
);
assertNotNull( identifierBinding.getIdClassMetadata() );
assertNotNull( identifierBinding.getIdClassMetadata().getIdClassType() );
assertNotNull( identifierBinding.getIdClassMetadata().getEmbeddableBinding() );
// Course should be interpreted as defining 3 attributes: `department`, `code` and `title`
assertEquals( 3, courseBinding.getAttributeBindingClosureSpan() );
@ -118,32 +124,31 @@ public class BasicIdClassTest extends BaseAnnotationBindingTestCase {
assertTrue(
courseBinding.getHierarchyDetails().getEntityIdentifier().isIdentifierAttributeBinding(
deptAttribute
)
courseBinding.getHierarchyDetails().getEntityIdentifier().
getEntityIdentifierBinding()
.isIdentifierAttributeBinding( deptAttribute )
);
assertTrue(
courseBinding.getHierarchyDetails().getEntityIdentifier().isIdentifierAttributeBinding(
codeAttribute
)
courseBinding.getHierarchyDetails().getEntityIdentifier()
.getEntityIdentifierBinding()
.isIdentifierAttributeBinding( codeAttribute )
);
// get the virtual (non-aggregated composite) id attribute
// get the non-aggregated composite id (virtual) attribute
EmbeddedAttributeBinding identifierAttribute = (EmbeddedAttributeBinding) courseBinding.getHierarchyDetails()
.getEntityIdentifier()
.getEntityIdentifierBinding()
.getAttributeBinding();
assertNotNull( identifierAttribute );
// NOTE : assertSame() does `==`
assertTrue( identifierAttribute.getAttribute().isSynthetic() );
EmbeddableBinding virtualEmbeddable = identifierAttribute.getEmbeddableBinding();
assertEquals( 2, virtualEmbeddable.attributeBindingSpan() );
for ( AttributeBinding subAttributeBinding : virtualEmbeddable.attributeBindings() ) {
assertTrue(
subAttributeBinding == deptAttribute
|| subAttributeBinding == codeAttribute
);
assertNotNull( subAttributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping() );
assertEquals( StringType.INSTANCE, subAttributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping() );
}
}

View File

@ -104,7 +104,7 @@ public abstract class AbstractUnidirectionalOneToManyBindingTests extends BaseUn
BagType.class,
Collection.class,
simpleEntityBinding,
entityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(),
entityBinding.getHierarchyDetails().getEntityIdentifier().getEntityIdentifierBinding().getAttributeBinding(),
Identifier.toIdentifier( "theBagOwner" ),
FetchTiming.DELAYED,
true
@ -116,7 +116,7 @@ public abstract class AbstractUnidirectionalOneToManyBindingTests extends BaseUn
SetType.class,
Set.class,
simpleEntityBinding,
entityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(),
entityBinding.getHierarchyDetails().getEntityIdentifier().getEntityIdentifierBinding().getAttributeBinding(),
Identifier.toIdentifier( "theSetOwner" ),
FetchTiming.IMMEDIATE,
false
@ -128,7 +128,7 @@ public abstract class AbstractUnidirectionalOneToManyBindingTests extends BaseUn
ListType.class,
List.class,
simpleEntityBinding,
entityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(),
entityBinding.getHierarchyDetails().getEntityIdentifier().getEntityIdentifierBinding().getAttributeBinding(),
Identifier.toIdentifier( "theListOwner" ),
FetchTiming.IMMEDIATE,
false
@ -140,7 +140,7 @@ public abstract class AbstractUnidirectionalOneToManyBindingTests extends BaseUn
MapType.class,
Map.class,
simpleEntityBinding,
entityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(),
entityBinding.getHierarchyDetails().getEntityIdentifier().getEntityIdentifierBinding().getAttributeBinding(),
Identifier.toIdentifier( "theMapOwner" ),
FetchTiming.DELAYED,
false

View File

@ -1,6 +1,7 @@
// $Id$
package org.hibernate.test.annotations.fkcircularity;
import java.io.Serializable;
import javax.persistence.Embeddable;
import javax.persistence.ManyToOne;
/**
@ -9,6 +10,7 @@ import javax.persistence.ManyToOne;
* @author Hardy Ferentschik
*
*/
@Embeddable
@SuppressWarnings("serial")
public class A_PK implements Serializable {
public D d;

View File

@ -10,6 +10,7 @@ import javax.persistence.ManyToOne;
* @author Hardy Ferentschik
*
*/
@Embeddable
@SuppressWarnings("serial")
public class D_PK implements Serializable{
private C c;

View File

@ -14,9 +14,11 @@ public class FkCircularityTest extends BaseUnitTestCase {
public void testJoinedSublcassesInPK() {
MetadataSources metadataSources = new MetadataSources()
.addAnnotatedClass( A.class )
.addAnnotatedClass( A_PK.class )
.addAnnotatedClass( B.class )
.addAnnotatedClass( C.class )
.addAnnotatedClass( D.class );
.addAnnotatedClass( D.class )
.addAnnotatedClass( D_PK.class );
metadataSources.buildMetadata();
}
}

View File

@ -23,13 +23,13 @@
*/
package org.hibernate.test.annotations.id;
import org.junit.Test;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.hibernate.test.annotations.id.entities.Location;
import org.hibernate.test.annotations.id.entities.Tower;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Test;
import static org.junit.Assert.assertNotNull;

View File

@ -29,6 +29,7 @@ import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.test.annotations.id.sequences.entities.Location;
import org.hibernate.test.annotations.id.sequences.entities.Tower;
import org.hibernate.testing.FailureExpectedWithNewMetamodel;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import static org.junit.Assert.assertNotNull;

Some files were not shown because too many files have changed in this diff Show More