HHH-7052 : Bind PluralAttributeBinding

This commit is contained in:
Gail Badner 2012-02-23 01:16:58 -08:00
parent 3f62381d94
commit 5ca5b2287f
10 changed files with 110 additions and 59 deletions

View File

@ -52,7 +52,6 @@ import org.hibernate.metamodel.spi.binding.BasicPluralAttributeElementBinding;
import org.hibernate.metamodel.spi.binding.CompositeAttributeBinding;
import org.hibernate.metamodel.spi.binding.EntityBinding;
import org.hibernate.metamodel.spi.binding.EntityDiscriminator;
import org.hibernate.metamodel.spi.binding.HibernateTypeDescriptor;
import org.hibernate.metamodel.spi.binding.IdGenerator;
import org.hibernate.metamodel.spi.binding.InheritanceType;
import org.hibernate.metamodel.spi.binding.ManyToOneAttributeBinding;
@ -134,6 +133,7 @@ import org.hibernate.type.Type;
*
* @author Steve Ebersole
* @author Hardy Ferentschik
* @author Gail Badner
*/
public class Binder {
private final MetadataImplementor metadata;
@ -898,6 +898,12 @@ public class Binder {
attributeSource.metaAttributes(),
attributeBindingContainer.getMetaAttributeContext()
);
// TODO: referenced attribute binding may not be defined yet; if it doesn't, need to chase it
// before resolving types.
SingularAttributeBinding referencedAttributeBinding = locatePluralAttributeKeyReferencedBinding(
attributeSource, attributeBindingContainer
);
if ( attributeSource.getPluralAttributeNature() == PluralAttributeNature.BAG ) {
final PluralAttribute attribute = existingAttribute != null
? existingAttribute
@ -905,6 +911,7 @@ public class Binder {
pluralAttributeBinding = attributeBindingContainer.makeBagAttributeBinding(
attribute,
convert( attributeSource.getElementSource().getNature() ),
referencedAttributeBinding,
propertyAccessorName,
attributeSource.isIncludedInOptimisticLocking(),
false,
@ -919,6 +926,7 @@ public class Binder {
pluralAttributeBinding = attributeBindingContainer.makeSetAttributeBinding(
attribute,
convert( attributeSource.getElementSource().getNature() ),
referencedAttributeBinding,
propertyAccessorName,
attributeSource.isIncludedInOptimisticLocking(),
false,
@ -941,9 +949,41 @@ public class Binder {
bindCollectionIndex( attributeSource, pluralAttributeBinding );
bindCollectionTablePrimaryKey( attributeSource, pluralAttributeBinding );
typeHelper.bindPluralAttributeTypeInformation( attributeSource, pluralAttributeBinding );
metadata.addCollection( pluralAttributeBinding );
}
private SingularAttributeBinding locatePluralAttributeKeyReferencedBinding(
PluralAttributeSource attributeSource,
AttributeBindingContainer attributeBindingContainer) {
final EntityBinding entityBinding = attributeBindingContainer.seekEntityBinding();
final String referencedAttributeName = attributeSource.getKeySource().getReferencedEntityAttributeName();
AttributeBinding referencedAttributeBinding =
attributeSource.getKeySource().getReferencedEntityAttributeName() == null ?
entityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding() :
entityBinding.locateAttributeBinding( referencedAttributeName );
if ( referencedAttributeBinding == null ) {
throw new MappingException(
String.format(
"Plural atttribute key references an attribute binding that does not exist: %s",
referencedAttributeBinding
),
currentBindingContext.getOrigin()
);
}
if ( ! referencedAttributeBinding.getAttribute().isSingular() ) {
throw new MappingException(
String.format(
"Plural atttribute key references a plural attribute; it must be plural: %s",
referencedAttributeName
),
currentBindingContext.getOrigin()
);
}
return ( SingularAttributeBinding ) referencedAttributeBinding;
}
private void doBasicPluralAttributeBinding(PluralAttributeSource source, AbstractPluralAttributeBinding binding) {
binding.setFetchTiming( source.getFetchTiming() );
binding.setFetchStyle( source.getFetchStyle() );
@ -1063,36 +1103,6 @@ public class Binder {
else {
bindCollectionKeyTargetingPropertyRef( attributeSource.getKeySource(), pluralAttributeBinding );
}
final EntityBinding entityBinding = pluralAttributeBinding.getContainer().seekEntityBinding();
AttributeBinding referencedAttributeBinding =
attributeSource.getKeySource().getReferencedEntityAttributeName() == null ?
entityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding() :
entityBinding.locateAttributeBinding( attributeSource.getKeySource().getReferencedEntityAttributeName() );
if ( referencedAttributeBinding == null ) {
throw new MappingException(
String.format(
"Plural atttribute key references an attribute binding that does not exist: %s",
attributeSource.getKeySource().getReferencedEntityAttributeName()
),
currentBindingContext.getOrigin()
);
}
if ( ! referencedAttributeBinding.getAttribute().isSingular() ) {
throw new MappingException(
String.format(
"Plural attribute key references an attribute that is not singular: %s",
attributeSource.getKeySource().getReferencedEntityAttributeName()
),
currentBindingContext.getOrigin()
);
}
typeHelper.bindPluralAttributeKeyTypeInformation(
pluralAttributeBinding.getPluralAttributeKeyBinding(),
( SingularAttributeBinding ) referencedAttributeBinding
);
}
private void bindCollectionKeyTargetingPrimaryKey(
@ -1263,10 +1273,6 @@ public class Binder {
basicElementSource,
basicCollectionElement
);
typeHelper.bindPluralAttributeTypeInformation(
attributeSource,
pluralAttributeBinding
);
return;
}

View File

@ -91,6 +91,7 @@ import org.hibernate.type.TypeFactory;
* </ul>
*
* @author Steve Ebersole
* @author Gail Badner
*/
public class HibernateTypeHelper {
private static final Logger log = Logger.getLogger( HibernateTypeHelper.class );
@ -159,16 +160,18 @@ public class HibernateTypeHelper {
}
}
//todo : we need to support type descriptors at multiple levels
bindHibernateTypeInformation( attributeSource.getTypeInformation(), attributeBinding.getHibernateTypeDescriptor() );
bindHibernateTypeInformation(
attributeSource.getTypeInformation(),
attributeBinding.getHibernateTypeDescriptor()
);
processPluralAttributeTypeInformation( attributeBinding );
}
public void bindPluralAttributeKeyTypeInformation(
PluralAttributeKeyBinding keyBinding,
SingularAttributeBinding referencedAttributeBinding) {
private void processPluralAttributeKeyTypeInformation(PluralAttributeKeyBinding keyBinding) {
final HibernateTypeDescriptor pluralAttributeKeyTypeDescriptor = keyBinding.getHibernateTypeDescriptor();
final HibernateTypeDescriptor referencedTypeDescriptor = referencedAttributeBinding.getHibernateTypeDescriptor();
final HibernateTypeDescriptor referencedTypeDescriptor =
keyBinding.getReferencedAttributeBinding().getHibernateTypeDescriptor();
pluralAttributeKeyTypeDescriptor.setExplicitTypeName( referencedTypeDescriptor.getExplicitTypeName() );
pluralAttributeKeyTypeDescriptor.setJavaTypeName( referencedTypeDescriptor.getJavaTypeName() );
@ -176,12 +179,10 @@ public class HibernateTypeHelper {
pluralAttributeKeyTypeDescriptor.setToOne( referencedTypeDescriptor.isToOne() );
pluralAttributeKeyTypeDescriptor.getTypeParameters().putAll( referencedTypeDescriptor.getTypeParameters() );
processPluralAttributeKeyInformation( keyBinding, referencedAttributeBinding );
processPluralAttributeKeyInformation( keyBinding );
}
private void processPluralAttributeKeyInformation(
PluralAttributeKeyBinding keyBinding,
SingularAttributeBinding referencedAttributeBinding) {
private void processPluralAttributeKeyInformation(PluralAttributeKeyBinding keyBinding) {
if ( keyBinding.getHibernateTypeDescriptor().getResolvedTypeMapping() != null ) {
return;
}
@ -190,7 +191,9 @@ public class HibernateTypeHelper {
// 2) we know the java type of the attribute
Type resolvedType = determineHibernateTypeFromDescriptor( keyBinding.getHibernateTypeDescriptor() );
if ( resolvedType == null ) {
resolvedType = determineHibernateTypeFromAttributeJavaType( referencedAttributeBinding.getAttribute() );
resolvedType = determineHibernateTypeFromAttributeJavaType(
keyBinding.getReferencedAttributeBinding().getAttribute()
);
}
if ( resolvedType != null ) {
@ -444,6 +447,12 @@ public class HibernateTypeHelper {
}
private void processPluralAttributeTypeInformation(PluralAttributeBinding attributeBinding) {
processCollectionTypeInformation( attributeBinding );
processPluralAttributeElementTypeInformation( attributeBinding.getPluralAttributeElementBinding() );
processPluralAttributeKeyTypeInformation( attributeBinding.getPluralAttributeKeyBinding() );
}
private void processCollectionTypeInformation(PluralAttributeBinding attributeBinding) {
if ( attributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping() != null ) {
return;
}
@ -469,14 +478,8 @@ public class HibernateTypeHelper {
resolvedType = determineHibernateTypeFromCollectionType( attributeBinding );
}
if ( resolvedType != null ) {
// todo : what exactly is getting pushed down here? and to what/where?
// pushHibernateTypeInformationDownIfNeeded(
// attributeBinding.getHibernateTypeDescriptor(),
// null,
// resolvedType
// );
attributeBinding.getHibernateTypeDescriptor().setResolvedTypeMapping( resolvedType );
}
bindCollectionElementTypeInformation( attributeBinding.getPluralAttributeElementBinding() );
}
private Type determineHibernateTypeFromCollectionType(PluralAttributeBinding attributeBinding) {
@ -505,10 +508,12 @@ public class HibernateTypeHelper {
}
}
private void bindCollectionElementTypeInformation(PluralAttributeElementBinding pluralAttributeElementBinding) {
private void processPluralAttributeElementTypeInformation(
PluralAttributeElementBinding pluralAttributeElementBinding
) {
switch ( pluralAttributeElementBinding.getPluralAttributeElementNature() ) {
case BASIC: {
bindBasicCollectionElementTypeInformation(
processBasicCollectionElementTypeInformation(
BasicPluralAttributeElementBinding.class.cast(
pluralAttributeElementBinding
)
@ -528,7 +533,7 @@ public class HibernateTypeHelper {
}
}
private void bindBasicCollectionElementTypeInformation(BasicPluralAttributeElementBinding basicCollectionElement) {
private void processBasicCollectionElementTypeInformation(BasicPluralAttributeElementBinding basicCollectionElement) {
Type resolvedHibernateType = determineHibernateTypeFromDescriptor( basicCollectionElement.getHibernateTypeDescriptor() );
if ( resolvedHibernateType != null ) {
pushHibernateTypeInformationDown(

View File

@ -79,6 +79,7 @@ public abstract class AbstractPluralAttributeBinding extends AbstractAttributeBi
AttributeBindingContainer container,
PluralAttribute attribute,
PluralAttributeElementNature pluralAttributeElementNature,
SingularAttributeBinding referencedAttributeBinding,
String propertyAccessorName,
boolean includedInOptimisticLocking,
boolean isLazy,
@ -91,7 +92,7 @@ public abstract class AbstractPluralAttributeBinding extends AbstractAttributeBi
isLazy,
metaAttributeContext
);
this.pluralAttributeKeyBinding = new PluralAttributeKeyBinding( this );
this.pluralAttributeKeyBinding = new PluralAttributeKeyBinding( this, referencedAttributeBinding );
this.pluralAttributeElementBinding = interpretNature( pluralAttributeElementNature );
}

View File

@ -131,6 +131,7 @@ public interface AttributeBindingContainer {
public BagBinding makeBagAttributeBinding(
PluralAttribute attribute,
PluralAttributeElementNature nature,
SingularAttributeBinding referencedAttributeBinding,
String propertyAccessorName,
boolean includedInOptimisticLocking,
boolean lazy,
@ -147,6 +148,7 @@ public interface AttributeBindingContainer {
public SetBinding makeSetAttributeBinding(
PluralAttribute attribute,
PluralAttributeElementNature nature,
SingularAttributeBinding referencedAttributeBinding,
String propertyAccessorName,
boolean includedInOptimisticLocking,
boolean lazy,

View File

@ -36,6 +36,7 @@ public class BagBinding extends AbstractPluralAttributeBinding {
AttributeBindingContainer container,
PluralAttribute attribute,
PluralAttributeElementNature pluralAttributeElementNature,
SingularAttributeBinding referencedAttributeBinding,
String propertyAccessorName,
boolean includedInOptimisticLocking,
boolean isLazy,
@ -44,6 +45,7 @@ public class BagBinding extends AbstractPluralAttributeBinding {
container,
attribute,
pluralAttributeElementNature,
referencedAttributeBinding,
propertyAccessorName,
includedInOptimisticLocking,
isLazy,

View File

@ -205,6 +205,7 @@ public class CompositeAttributeBinding
public BagBinding makeBagAttributeBinding(
PluralAttribute attribute,
PluralAttributeElementNature nature,
SingularAttributeBinding referencedAttributeBinding,
String propertyAccessorName,
boolean includedInOptimisticLocking,
boolean lazy,
@ -214,6 +215,7 @@ public class CompositeAttributeBinding
this,
attribute,
nature,
referencedAttributeBinding,
propertyAccessorName,
includedInOptimisticLocking,
lazy,
@ -227,6 +229,7 @@ public class CompositeAttributeBinding
public SetBinding makeSetAttributeBinding(
PluralAttribute attribute,
PluralAttributeElementNature nature,
SingularAttributeBinding referencedAttributeBinding,
String propertyAccessorName,
boolean includedInOptimisticLocking,
boolean lazy,
@ -237,6 +240,7 @@ public class CompositeAttributeBinding
this,
attribute,
nature,
referencedAttributeBinding,
propertyAccessorName,
includedInOptimisticLocking,
lazy,

View File

@ -559,6 +559,7 @@ public class EntityBinding implements AttributeBindingContainer {
public BagBinding makeBagAttributeBinding(
PluralAttribute attribute,
PluralAttributeElementNature nature,
SingularAttributeBinding referencedAttributeBinding,
String propertyAccessorName,
boolean includedInOptimisticLocking,
boolean lazy,
@ -568,6 +569,7 @@ public class EntityBinding implements AttributeBindingContainer {
this,
attribute,
nature,
referencedAttributeBinding,
propertyAccessorName,
includedInOptimisticLocking,
lazy,
@ -581,6 +583,7 @@ public class EntityBinding implements AttributeBindingContainer {
public SetBinding makeSetAttributeBinding(
PluralAttribute attribute,
PluralAttributeElementNature nature,
SingularAttributeBinding referencedAttributeBinding,
String propertyAccessorName,
boolean includedInOptimisticLocking,
boolean lazy,
@ -591,6 +594,7 @@ public class EntityBinding implements AttributeBindingContainer {
this,
attribute,
nature,
referencedAttributeBinding,
propertyAccessorName,
includedInOptimisticLocking,
lazy,

View File

@ -41,14 +41,17 @@ public class PluralAttributeKeyBinding {
// this knowledge can be implicitly resolved based on the typing information on the referenced owner attribute
private final HibernateTypeDescriptor hibernateTypeDescriptor = new HibernateTypeDescriptor();
// SingularAttributeBinding referencedAttributeBinding;
private final SingularAttributeBinding referencedAttributeBinding;
// todo : this would be nice to have but we do not always know it, especially in HBM case.
// private BasicAttributeBinding otherSide;
public PluralAttributeKeyBinding(AbstractPluralAttributeBinding pluralAttributeBinding) {
public PluralAttributeKeyBinding(
AbstractPluralAttributeBinding pluralAttributeBinding,
SingularAttributeBinding referencedAttributeBinding) {
this.pluralAttributeBinding = pluralAttributeBinding;
this.referencedAttributeBinding = referencedAttributeBinding;
}
/**
@ -60,6 +63,9 @@ public class PluralAttributeKeyBinding {
return pluralAttributeBinding;
}
public SingularAttributeBinding getReferencedAttributeBinding() {
return referencedAttributeBinding;
}
/**
* The foreign key that defines the scope of this relationship.
*

View File

@ -38,6 +38,7 @@ public class SetBinding extends AbstractPluralAttributeBinding {
AttributeBindingContainer container,
PluralAttribute attribute,
PluralAttributeElementNature pluralAttributeElementNature,
SingularAttributeBinding referencedAttributeBinding,
String propertyAccessorName,
boolean includedInOptimisticLocking,
boolean isLazy,
@ -47,6 +48,7 @@ public class SetBinding extends AbstractPluralAttributeBinding {
container,
attribute,
pluralAttributeElementNature,
referencedAttributeBinding,
propertyAccessorName,
includedInOptimisticLocking,
isLazy,

View File

@ -23,7 +23,10 @@
*/
package org.hibernate.metamodel.spi.binding;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.Set;
import org.junit.After;
import org.junit.Before;
@ -38,6 +41,8 @@ import org.hibernate.metamodel.spi.relational.Identifier;
import org.hibernate.service.ServiceRegistryBuilder;
import org.hibernate.service.internal.StandardServiceRegistryImpl;
import org.hibernate.testing.junit4.BaseUnitTestCase;
import org.hibernate.type.BagType;
import org.hibernate.type.SetType;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@ -89,6 +94,13 @@ public class BasicCollectionBindingTests extends BaseUnitTestCase {
assertEquals( Identifier.toIdentifier( "`EntityWithBasicCollections_theBag`" ), bagBinding.getCollectionTable().getLogicalName() );
PluralAttributeKeyBinding bagKeyBinding = bagBinding.getPluralAttributeKeyBinding();
assertSame( bagBinding, bagKeyBinding.getPluralAttributeBinding() );
HibernateTypeDescriptor bagHibernateTypeDescriptor = bagBinding.getHibernateTypeDescriptor();
assertNull( bagHibernateTypeDescriptor.getExplicitTypeName() );
assertEquals( Collection.class.getName(), bagHibernateTypeDescriptor.getJavaTypeName() );
assertTrue( bagHibernateTypeDescriptor.getTypeParameters().isEmpty() );
assertTrue( bagHibernateTypeDescriptor.getResolvedTypeMapping() instanceof BagType );
assertFalse( bagHibernateTypeDescriptor.getResolvedTypeMapping().isComponentType() );
assertEquals( "theBag", ( (BagType) bagHibernateTypeDescriptor.getResolvedTypeMapping() ).getRole() );
ForeignKey fkBag = bagKeyBinding.getForeignKey();
assertNotNull( fkBag );
@ -130,6 +142,13 @@ public class BasicCollectionBindingTests extends BaseUnitTestCase {
assertEquals( Identifier.toIdentifier( "`EntityWithBasicCollections_theSet`" ), setBinding.getCollectionTable().getLogicalName() );
PluralAttributeKeyBinding setKeyBinding = setBinding.getPluralAttributeKeyBinding();
assertSame( setBinding, setKeyBinding.getPluralAttributeBinding() );
HibernateTypeDescriptor setHibernateTypeDescriptor = setBinding.getHibernateTypeDescriptor();
assertNull( setHibernateTypeDescriptor.getExplicitTypeName() );
assertEquals( Set.class.getName(), setHibernateTypeDescriptor.getJavaTypeName() );
assertTrue( setHibernateTypeDescriptor.getTypeParameters().isEmpty() );
assertTrue( setHibernateTypeDescriptor.getResolvedTypeMapping() instanceof SetType );
assertFalse( setHibernateTypeDescriptor.getResolvedTypeMapping().isComponentType() );
assertEquals( "theSet", ( (SetType) setHibernateTypeDescriptor.getResolvedTypeMapping() ).getRole() );
ForeignKey fkSet = setKeyBinding.getForeignKey();
assertNotNull( fkSet );