From ba459aa00cd535da8c0c4084387340adde976e05 Mon Sep 17 00:00:00 2001 From: Gail Badner Date: Thu, 19 Jul 2012 13:25:48 -0700 Subject: [PATCH] HHH-6569 : Update persisters and tuplizers to use components --- .../hibernate/metamodel/internal/Binder.java | 133 ++++++++++++++---- .../internal/source/hbm/ColumnSourceImpl.java | 3 +- .../binding/CompositeAttributeBinding.java | 18 ++- .../property/PropertyAccessorFactory.java | 38 +++-- .../org/hibernate/tuple/PojoInstantiator.java | 18 +++ .../org/hibernate/tuple/PropertyFactory.java | 65 ++++++--- .../component/AbstractComponentTuplizer.java | 24 ++++ .../tuple/component/ComponentMetamodel.java | 35 ++++- .../component/ComponentTuplizerFactory.java | 84 ++++++++++- .../DynamicMapComponentTuplizer.java | 7 + .../component/PojoComponentTuplizer.java | 67 +++++++++ .../entity/DynamicMapEntityTuplizer.java | 14 +- .../tuple/entity/PojoEntityTuplizer.java | 31 +--- .../entity/EmbeddableBindingTest.java | 19 ++- .../AbstractBidirectionalOneToManyTest.java | 45 ++++++ .../BidirectionalOneToManyInverseTest.java | 16 +-- .../BidirectionalOneToManyNonInverseTest.java | 35 +++++ .../nonindexed/{inverse => }/Child.java | 2 +- .../nonindexed/{inverse => }/Parent.java | 2 +- ...ml => ParentChildInverseOneToMany.hbm.xml} | 2 +- .../ParentChildNonInverseOneToMany.hbm.xml | 19 +++ 21 files changed, 543 insertions(+), 134 deletions(-) create mode 100644 hibernate-core/src/test/java/org/hibernate/test/bidir/onetomany/nonindexed/AbstractBidirectionalOneToManyTest.java rename hibernate-core/src/test/java/org/hibernate/test/bidir/onetomany/nonindexed/{inverse => }/BidirectionalOneToManyInverseTest.java (75%) create mode 100644 hibernate-core/src/test/java/org/hibernate/test/bidir/onetomany/nonindexed/BidirectionalOneToManyNonInverseTest.java rename hibernate-core/src/test/java/org/hibernate/test/bidir/onetomany/nonindexed/{inverse => }/Child.java (91%) rename hibernate-core/src/test/java/org/hibernate/test/bidir/onetomany/nonindexed/{inverse => }/Parent.java (89%) rename hibernate-core/src/test/java/org/hibernate/test/bidir/onetomany/nonindexed/{inverse/ParentChild.hbm.xml => ParentChildInverseOneToMany.hbm.xml} (96%) create mode 100755 hibernate-core/src/test/java/org/hibernate/test/bidir/onetomany/nonindexed/ParentChildNonInverseOneToMany.hbm.xml diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/Binder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/Binder.java index eb053c53c3..7c344e3630 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/Binder.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/Binder.java @@ -50,6 +50,7 @@ import org.hibernate.id.PersistentIdentifierGenerator; import org.hibernate.id.factory.IdentifierGeneratorFactory; import org.hibernate.internal.util.ReflectHelper; import org.hibernate.internal.util.StringHelper; +import org.hibernate.internal.util.ValueHolder; import org.hibernate.metamodel.internal.HibernateTypeHelper.ReflectedCollectionJavaTypes; import org.hibernate.metamodel.internal.source.hbm.ListAttributeSource; import org.hibernate.metamodel.internal.source.hbm.MapAttributeSource; @@ -148,6 +149,7 @@ import org.hibernate.metamodel.spi.source.VersionAttributeSource; import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.service.config.spi.ConfigurationService; +import org.hibernate.tuple.component.ComponentMetamodel; import org.hibernate.tuple.entity.EntityTuplizer; import org.hibernate.type.ComponentType; import org.hibernate.type.EntityType; @@ -210,6 +212,12 @@ public class Binder { } } + private SingularAttributeBinding bindIdentifierAttribute( + final AttributeBindingContainer attributeBindingContainer, + final SingularAttributeSource attributeSource) { + return bindSingularAttribute( attributeBindingContainer, attributeSource, true ); + } + private AttributeBinding bindAttribute( final AttributeBindingContainer attributeBindingContainer, final AttributeSource attributeSource) { @@ -220,15 +228,20 @@ public class Binder { return attributeBinding; } return attributeSource.isSingular() ? - bindSingularAttribute(attributeBindingContainer,SingularAttributeSource.class.cast( attributeSource )) - : bindPluralAttribute( attributeBindingContainer,PluralAttributeSource.class.cast( attributeSource ) ); + bindSingularAttribute( + attributeBindingContainer, + SingularAttributeSource.class.cast( attributeSource ), + false + ) : + bindPluralAttribute( attributeBindingContainer,PluralAttributeSource.class.cast( attributeSource ) ); } // Singular attributes ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ private SingularAttributeBinding bindSingularAttribute( final AttributeBindingContainer attributeBindingContainer, - final SingularAttributeSource attributeSource ) { + final SingularAttributeSource attributeSource, + boolean isIdentifierAttribute) { final SingularAttributeNature nature = attributeSource.getNature(); final SingularAttribute attribute = attributeBindingContainer.getAttributeContainer().locateSingularAttribute( attributeSource.getName() ); @@ -245,7 +258,8 @@ public class Binder { return bindComponentAttribute( attributeBindingContainer, ComponentAttributeSource.class.cast( attributeSource ), - attribute + attribute, + isIdentifierAttribute ); default: throw new NotYetImplementedException( nature.toString() ); @@ -290,27 +304,46 @@ public class Binder { private CompositeAttributeBinding bindComponentAttribute( final AttributeBindingContainer attributeBindingContainer, final ComponentAttributeSource attributeSource, - SingularAttribute attribute ) { + SingularAttribute attribute, + boolean isAttributeIdentifier) { final Composite composite; + ValueHolder> defaultJavaClassReference = null; if ( attribute == null ) { - composite = new Composite( - attributeSource.getPath(), - attributeSource.getClassName(), - attributeSource.getClassReference(), - null ); + if ( attributeSource.getClassName() != null ) { + composite = new Composite( + attributeSource.getPath(), + attributeSource.getClassName(), + attributeSource.getClassReference() != null ? + attributeSource.getClassReference() : + bindingContext().makeClassReference( attributeSource.getClassName() ), + null + ); + // no need for a default because there's an explicit class name provided + } + else { + defaultJavaClassReference = createSingularAttributeJavaType( + attributeBindingContainer.getClassReference(), attributeSource.getName() + ); + composite = new Composite( + attributeSource.getPath(), + defaultJavaClassReference.getValue().getName(), + defaultJavaClassReference, + null + ); + } attribute = attributeBindingContainer.getAttributeContainer().createCompositeAttribute( - attributeSource.getName(), - composite ); - } else { - composite = ( Composite ) attribute.getSingularAttributeType(); + attributeSource.getName(), + composite + ); + } + else { + composite = (Composite) attribute.getSingularAttributeType(); } - final SingularAttribute referencingAttribute; - if ( StringHelper.isEmpty( attributeSource.getParentReferenceAttributeName() ) ) { - referencingAttribute = null; - } else { - referencingAttribute = composite.createSingularAttribute( attributeSource.getParentReferenceAttributeName() ); - } + final SingularAttribute referencingAttribute = + StringHelper.isEmpty( attributeSource.getParentReferenceAttributeName() ) ? + null : + composite.createSingularAttribute( attributeSource.getParentReferenceAttributeName() ); final SingularAttributeBinding.NaturalIdMutability naturalIdMutability = attributeSource.getNaturalIdMutability(); final CompositeAttributeBinding attributeBinding = attributeBindingContainer.makeComponentAttributeBinding( @@ -321,7 +354,28 @@ public class Binder { attributeSource.isLazy(), naturalIdMutability, createMetaAttributeContext( attributeBindingContainer, attributeSource ) ); - bindAttributes( attributeBinding, attributeSource ); + // TODO: binding the HibernateTypeDescriptor should be simplified since we know the class name already + bindHibernateTypeDescriptor( + attributeBinding.getHibernateTypeDescriptor(), + composite.getClassName(), + null, + defaultJavaClassReference == null ? null : defaultJavaClassReference.getValue().getName() + ); + if ( referencingAttribute == null ) { + bindAttributes( attributeBinding, attributeSource ); + } + else { + for ( final AttributeSource subAttributeSource : attributeSource.attributeSources() ) { + // TODO: don't create a "parent" attribute binding??? + if ( ! subAttributeSource.getName().equals( referencingAttribute.getName() ) ) { + bindAttribute( attributeBinding, subAttributeSource ); + } + } + } + Type resolvedType = metadata.getTypeResolver().getTypeFactory().component( + new ComponentMetamodel( attributeBinding, isAttributeIdentifier ) + ); + bindHibernateResolvedType( attributeBinding.getHibernateTypeDescriptor(), resolvedType ); return attributeBinding; } @@ -1040,6 +1094,8 @@ public class Binder { } } + // TODO: simplify how HibernateTypeDescriptor is bound + private void bindHibernateTypeDescriptor( final HibernateTypeDescriptor hibernateTypeDescriptor, final ExplicitHibernateTypeSource explicitTypeSource, @@ -1047,7 +1103,9 @@ public class Binder { // if there is an explicit type name specified, then there's no reason to // initialize the default Java type name; simply pass a null default instead. bindHibernateTypeDescriptor( - hibernateTypeDescriptor, explicitTypeSource, explicitTypeSource.getName() == null + hibernateTypeDescriptor, + explicitTypeSource, + explicitTypeSource == null || explicitTypeSource.getName() == null ? defaultJavaType.getValue().getName() : null ); @@ -1131,8 +1189,9 @@ public class Binder { private void bindSimpleIdentifier( final EntityBinding rootEntityBinding, final SimpleIdentifierSource identifierSource ) { // locate the attribute binding - final BasicAttributeBinding idAttributeBinding = - ( BasicAttributeBinding ) bindAttribute( rootEntityBinding, identifierSource.getIdentifierAttributeSource() ); + final BasicAttributeBinding idAttributeBinding = ( BasicAttributeBinding ) bindIdentifierAttribute( + rootEntityBinding, identifierSource.getIdentifierAttributeSource() + ); // Configure ID generator IdGenerator generator = identifierSource.getIdentifierGeneratorDescriptor(); @@ -1155,8 +1214,9 @@ public class Binder { EntityBinding rootEntityBinding, AggregatedCompositeIdentifierSource identifierSource ) { // locate the attribute binding - final CompositeAttributeBinding idAttributeBinding = - ( CompositeAttributeBinding ) bindAttribute( rootEntityBinding, identifierSource.getIdentifierAttributeSource() ); + final CompositeAttributeBinding idAttributeBinding = ( CompositeAttributeBinding ) bindIdentifierAttribute( + rootEntityBinding, identifierSource.getIdentifierAttributeSource() + ); // Configure ID generator IdGenerator generator = identifierSource.getIdentifierGeneratorDescriptor(); @@ -1181,7 +1241,7 @@ public class Binder { // locate the attribute bindings for the real attributes List< SingularAttributeBinding > idAttributeBindings = new ArrayList< SingularAttributeBinding >(); for ( SingularAttributeSource attributeSource : identifierSource.getAttributeSourcesMakingUpIdentifier() ) { - idAttributeBindings.add( ( SingularAttributeBinding ) bindAttribute( rootEntityBinding, attributeSource ) ); + idAttributeBindings.add( bindIdentifierAttribute( rootEntityBinding, attributeSource ) ); } // Create the synthetic attribute @@ -1571,7 +1631,10 @@ public class Binder { if(isNaturalId){ addUniqueConstraintForNaturalIdColumn( defaultTable, column ); } - valueBindings.add( new RelationalValueBinding( column, true, !isImmutableNaturalId ) ); + valueBindings.add( new RelationalValueBinding( + column, + valueSourceContainer.areValuesIncludedInInsertByDefault(), + valueSourceContainer.areValuesIncludedInUpdateByDefault() && !isImmutableNaturalId ) ); } else { final String name = attribute.getName(); for ( final RelationalValueSource valueSource : valueSourceContainer.relationalValueSources() ) { @@ -2074,17 +2137,27 @@ public class Binder { private static org.hibernate.internal.util.ValueHolder< Class< ? >> createSingularAttributeJavaType( final SingularAttribute attribute ) { + return createSingularAttributeJavaType( + attribute.getAttributeContainer().getClassReference(), + attribute.getName() + ); + } + + private static org.hibernate.internal.util.ValueHolder< Class< ? >> createSingularAttributeJavaType( + final Class< ? > attributeContainerClassReference, + final String attributeName ) { org.hibernate.internal.util.ValueHolder.DeferredInitializer< Class< ? >> deferredInitializer = new org.hibernate.internal.util.ValueHolder.DeferredInitializer< Class< ? >>() { public Class< ? > initialize() { return ReflectHelper.reflectedPropertyClass( - attribute.getAttributeContainer().getClassReference(), - attribute.getName() ); + attributeContainerClassReference, + attributeName ); } }; return new org.hibernate.internal.util.ValueHolder< Class< ? >>( deferredInitializer ); } + private static String interpretIdentifierUnsavedValue( IdentifierSource identifierSource, IdGenerator generator ) { if ( identifierSource == null ) { throw new IllegalArgumentException( "identifierSource must be non-null." ); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ColumnSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ColumnSourceImpl.java index 0258f07126..c973b73cfe 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ColumnSourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ColumnSourceImpl.java @@ -117,7 +117,8 @@ class ColumnSourceImpl @Override public boolean isUnique() { - return columnElement.isUnique(); + // TODO: should TruthValue be returned instead of boolean? + return columnElement.isUnique() != null && columnElement.isUnique().booleanValue(); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/CompositeAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/CompositeAttributeBinding.java index bb46e1c7ee..2e8ae2754e 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/CompositeAttributeBinding.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/CompositeAttributeBinding.java @@ -26,6 +26,7 @@ package org.hibernate.metamodel.spi.binding; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Properties; @@ -116,7 +117,7 @@ public class CompositeAttributeBinding this.path = container.getPathBase() + '.' + attribute.getName(); if ( subAttributeBindings == null ) { - attributeBindingMap = new HashMap(); + attributeBindingMap = new LinkedHashMap(); } else { HashMap map = new HashMap(); @@ -175,8 +176,15 @@ public class CompositeAttributeBinding @Override public boolean isNullable() { - // todo : not sure this is even relevant for components - return false; + // return false if there are any singular attributes are non-nullable + for ( AttributeBinding attributeBinding : attributeBindings() ) { + // only check singular attributes + if ( attributeBinding.getAttribute().isSingular() && + ! ( (SingularAttributeBinding) attributeBinding ).isNullable() ) { + return false; + } + } + return true; } @Override @@ -205,6 +213,10 @@ public class CompositeAttributeBinding return null; } + public int attributeBindingSpan() { + return attributeBindingMap.size(); + } + @Override public Iterable attributeBindings() { return attributeBindingMap.values(); diff --git a/hibernate-core/src/main/java/org/hibernate/property/PropertyAccessorFactory.java b/hibernate-core/src/main/java/org/hibernate/property/PropertyAccessorFactory.java index 48af4132b0..f6f9450511 100644 --- a/hibernate-core/src/main/java/org/hibernate/property/PropertyAccessorFactory.java +++ b/hibernate-core/src/main/java/org/hibernate/property/PropertyAccessorFactory.java @@ -96,22 +96,30 @@ public final class PropertyAccessorFactory { * @throws MappingException */ public static PropertyAccessor getPropertyAccessor(AttributeBinding property, EntityMode mode) throws MappingException { - //TODO: this is temporary in that the end result will probably not take a Property reference per-se. - if ( property.isBackRef() ) { - BackRefAttributeBinding backRefAttributeBinding = (BackRefAttributeBinding) property; - return new BackrefPropertyAccessor( - backRefAttributeBinding.getCollectionRole(), backRefAttributeBinding.getEntityName() - ); + if ( null == mode || EntityMode.POJO.equals( mode ) ) { + if ( property.isBackRef() ) { + //TODO: this is temporary in that the end result will probably not take a Property reference per-se. + BackRefAttributeBinding backRefAttributeBinding = (BackRefAttributeBinding) property; + return new BackrefPropertyAccessor( + backRefAttributeBinding.getCollectionRole(), backRefAttributeBinding.getEntityName() + ); + } + else { + return getPojoPropertyAccessor( property.getPropertyAccessorName() ); + } + } + else if (EntityMode.MAP.equals( mode ) ) { + if ( property.isBackRef() ) { + //TODO: this is temporary in that the end result will probably not take a Property reference per-se. + return PropertyAccessorFactory.getPropertyAccessor( null, property.getPropertyAccessorName() ); + } + else { + return getDynamicMapPropertyAccessor(); + } + } + else { + throw new MappingException( "Unknown entity mode [" + mode + "]" ); } - else if ( null == mode || EntityMode.POJO.equals( mode ) ) { - return getPojoPropertyAccessor( property.getPropertyAccessorName() ); - } - else if ( EntityMode.MAP.equals( mode ) ) { - return getDynamicMapPropertyAccessor(); - } - else { - throw new MappingException( "Unknown entity mode [" + mode + "]" ); - } } /** diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/PojoInstantiator.java b/hibernate-core/src/main/java/org/hibernate/tuple/PojoInstantiator.java index df6228225f..bbaf9cbc12 100755 --- a/hibernate-core/src/main/java/org/hibernate/tuple/PojoInstantiator.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/PojoInstantiator.java @@ -37,6 +37,7 @@ import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.util.ReflectHelper; import org.hibernate.mapping.Component; import org.hibernate.mapping.PersistentClass; +import org.hibernate.metamodel.spi.binding.CompositeAttributeBinding; import org.hibernate.metamodel.spi.binding.EntityBinding; /** @@ -71,6 +72,23 @@ public class PojoInstantiator implements Instantiator, Serializable { } } + public PojoInstantiator(CompositeAttributeBinding component, ReflectionOptimizer.InstantiationOptimizer optimizer) { + this.mappedClass = component.getClassReference(); + this.isAbstract = ReflectHelper.isAbstractClass( mappedClass ); + this.optimizer = optimizer; + + this.proxyInterface = null; + this.embeddedIdentifier = false; + + try { + constructor = ReflectHelper.getDefaultConstructor(mappedClass); + } + catch ( PropertyNotFoundException pnfe ) { + LOG.noDefaultConstructor(mappedClass.getName()); + constructor = null; + } + } + public PojoInstantiator(PersistentClass persistentClass, ReflectionOptimizer.InstantiationOptimizer optimizer) { this.mappedClass = persistentClass.getMappedClass(); this.isAbstract = ReflectHelper.isAbstractClass( mappedClass ); diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/PropertyFactory.java b/hibernate-core/src/main/java/org/hibernate/tuple/PropertyFactory.java index 6672f3f9aa..3025b75a2f 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/PropertyFactory.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/PropertyFactory.java @@ -27,6 +27,7 @@ import java.lang.reflect.Constructor; import org.hibernate.EntityMode; import org.hibernate.FetchMode; +import org.hibernate.PropertyNotFoundException; import org.hibernate.engine.internal.UnsavedValueFactory; import org.hibernate.engine.spi.CascadeStyle; import org.hibernate.engine.spi.IdentifierValue; @@ -48,6 +49,7 @@ import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; import org.hibernate.property.Getter; import org.hibernate.property.PropertyAccessor; import org.hibernate.property.PropertyAccessorFactory; +import org.hibernate.property.Setter; import org.hibernate.type.AssociationType; import org.hibernate.type.Type; import org.hibernate.type.VersionType; @@ -122,7 +124,7 @@ public class PropertyFactory { IdentifierValue unsavedValue = UnsavedValueFactory.getUnsavedIdentifierValue( mappedUnsavedValue, - getGetter( property ), + getGetterOrNull( property ), type, getConstructor( mappedEntity ) ); @@ -201,7 +203,7 @@ public class PropertyFactory { final String mappedUnsavedValue = entityBinding.getHierarchyDetails().getEntityVersion().getUnsavedValue(); final VersionValue unsavedValue = UnsavedValueFactory.getUnsavedVersionValue( mappedUnsavedValue, - getGetter( property ), + getGetterOrNull( property ), (VersionType) property.getHibernateTypeDescriptor().getResolvedTypeMapping(), getConstructor( (EntityBinding) property.getContainer() ) ); @@ -307,13 +309,13 @@ public class PropertyFactory { null, type, lazyAvailable && singularAttributeBinding.isLazy(), - true, // insertable - true, // updatable + areAnyValuesIncludedInInsert( singularAttributeBinding ), // insertable + areAnyValuesIncludedInUpdate( singularAttributeBinding ), // updatable propertyGeneration == PropertyGeneration.INSERT || propertyGeneration == PropertyGeneration.ALWAYS, propertyGeneration == PropertyGeneration.ALWAYS, singularAttributeBinding.isNullable(), - alwaysDirtyCheck || areAllValuesIncludedInUpdate( singularAttributeBinding ), + alwaysDirtyCheck || areAnyValuesIncludedInUpdate( singularAttributeBinding ), singularAttributeBinding.isIncludedInOptimisticLocking(), cascadeStyle, fetchMode @@ -349,16 +351,22 @@ public class PropertyFactory { } } - private static boolean areAllValuesIncludedInUpdate(SingularAttributeBinding attributeBinding) { - if ( attributeBinding.hasDerivedValue() ) { - return false; - } + private static boolean areAnyValuesIncludedInInsert(SingularAttributeBinding attributeBinding) { for ( RelationalValueBinding valueBinding : attributeBinding.getRelationalValueBindings() ) { - if ( ! valueBinding.isIncludeInUpdate() ) { - return false; + if ( valueBinding.isIncludeInInsert() ) { + return true; } } - return true; + return false; + } + + private static boolean areAnyValuesIncludedInUpdate(SingularAttributeBinding attributeBinding) { + for ( RelationalValueBinding valueBinding : attributeBinding.getRelationalValueBindings() ) { + if ( valueBinding.isIncludeInUpdate() ) { + return true; + } + } + return false; } private static Constructor getConstructor(PersistentClass persistentClass) { @@ -396,17 +404,36 @@ public class PropertyFactory { return pa.getGetter( mappingProperty.getPersistentClass().getMappedClass(), mappingProperty.getName() ); } - private static Getter getGetter(AttributeBinding mappingProperty) { - if ( mappingProperty == null || mappingProperty.getContainer().getClassReference() == null ) { - return null; - } - - PropertyAccessor pa = PropertyAccessorFactory.getPropertyAccessor( mappingProperty, EntityMode.POJO ); - return pa.getGetter( + public static Getter getGetter(AttributeBinding mappingProperty) { + return getPropertyAccessor( mappingProperty ).getGetter( mappingProperty.getContainer().getClassReference(), mappingProperty.getAttribute().getName() ); } + private static Getter getGetterOrNull(AttributeBinding mappingProperty) { + try { + return getGetter( mappingProperty ); + } + catch ( PropertyNotFoundException ex ) { + // ignore exception + } + return null; + } + + public static Setter getSetter(AttributeBinding mappingProperty) { + return getPropertyAccessor( mappingProperty ).getSetter( + mappingProperty.getContainer().getClassReference(), + mappingProperty.getAttribute().getName() + ); + } + + private static PropertyAccessor getPropertyAccessor(AttributeBinding mappingProperty) { + // TODO: fix this to work w/ component entity mode also + return PropertyAccessorFactory.getPropertyAccessor( + mappingProperty, + mappingProperty.getContainer().seekEntityBinding().getHierarchyDetails().getEntityMode() + ); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/component/AbstractComponentTuplizer.java b/hibernate-core/src/main/java/org/hibernate/tuple/component/AbstractComponentTuplizer.java index 14158a7b25..0446547594 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/component/AbstractComponentTuplizer.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/component/AbstractComponentTuplizer.java @@ -30,9 +30,12 @@ import org.hibernate.HibernateException; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.mapping.Component; import org.hibernate.mapping.Property; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.CompositeAttributeBinding; import org.hibernate.property.Getter; import org.hibernate.property.Setter; import org.hibernate.tuple.Instantiator; +import org.hibernate.tuple.PropertyFactory; /** * Support for tuplizers relating to components. @@ -51,6 +54,8 @@ public abstract class AbstractComponentTuplizer implements ComponentTuplizer { protected abstract Getter buildGetter(Component component, Property prop); protected abstract Setter buildSetter(Component component, Property prop); + protected abstract Instantiator buildInstantiator(CompositeAttributeBinding component); + protected AbstractComponentTuplizer(Component component) { propertySpan = component.getPropertySpan(); getters = new Getter[propertySpan]; @@ -72,6 +77,25 @@ public abstract class AbstractComponentTuplizer implements ComponentTuplizer { instantiator = buildInstantiator( component ); } + protected AbstractComponentTuplizer(CompositeAttributeBinding component) { + propertySpan = component.attributeBindingSpan(); + getters = new Getter[propertySpan]; + setters = new Setter[propertySpan]; + + boolean foundCustomAccessor=false; + int i = 0; + for ( AttributeBinding attributeBinding : component.attributeBindings() ) { + getters[i] = PropertyFactory.getGetter( attributeBinding ); + setters[i] = PropertyFactory.getSetter( attributeBinding ); + if ( !attributeBinding.isBasicPropertyAccessor() ) { + foundCustomAccessor = true; + } + i++; + } + hasCustomAccessors = foundCustomAccessor; + instantiator = buildInstantiator( component ); + } + public Object getPropertyValue(Object component, int i) throws HibernateException { return getters[i].get( component ); } diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/component/ComponentMetamodel.java b/hibernate-core/src/main/java/org/hibernate/tuple/component/ComponentMetamodel.java index ae97415678..7a44de48e4 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/component/ComponentMetamodel.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/component/ComponentMetamodel.java @@ -32,6 +32,8 @@ import org.hibernate.EntityMode; import org.hibernate.HibernateException; import org.hibernate.mapping.Component; import org.hibernate.mapping.Property; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.CompositeAttributeBinding; import org.hibernate.tuple.PropertyFactory; import org.hibernate.tuple.StandardProperty; @@ -45,7 +47,6 @@ public class ComponentMetamodel implements Serializable { // TODO : will need reference to session factory to fully complete HHH-1907 // private final SessionFactoryImplementor sessionFactory; - private final String role; private final boolean isKey; private final StandardProperty[] properties; @@ -54,12 +55,11 @@ public class ComponentMetamodel implements Serializable { // cached for efficiency... private final int propertySpan; - private final Map propertyIndexes = new HashMap(); + private final Map propertyIndexes = new HashMap(); // public ComponentMetamodel(Component component, SessionFactoryImplementor sessionFactory) { public ComponentMetamodel(Component component) { // this.sessionFactory = sessionFactory; - this.role = component.getRoleName(); this.isKey = component.isKey(); propertySpan = component.getPropertySpan(); properties = new StandardProperty[propertySpan]; @@ -83,6 +83,31 @@ public class ComponentMetamodel implements Serializable { ) : componentTuplizerFactory.constructTuplizer( tuplizerClassName, component ); } + public ComponentMetamodel(CompositeAttributeBinding component, boolean isIdentifierAttributeBinding) { + this.isKey = isIdentifierAttributeBinding; + propertySpan = component.attributeBindingSpan(); + properties = new StandardProperty[propertySpan]; + int i = 0; + for ( AttributeBinding attributeBinding : component.attributeBindings() ) { + properties[i] = PropertyFactory.buildStandardProperty( attributeBinding, false ); + propertyIndexes.put( attributeBinding.getAttribute().getName(), i ); + i++; + } + + entityMode = component.seekEntityBinding().getHierarchyDetails().getEntityMode(); + + // todo : move this to SF per HHH-3517; also see HHH-1907 and ComponentMetamodel + final ComponentTuplizerFactory componentTuplizerFactory = new ComponentTuplizerFactory(); + // TODO: provide support for custom tuplizer + final String tuplizerClassName = null; + if ( tuplizerClassName == null ) { + componentTuplizer = componentTuplizerFactory.constructDefaultTuplizer( entityMode, component ); + } + else { + componentTuplizer = componentTuplizerFactory.constructTuplizer( tuplizerClassName, component ); + } + } + public boolean isKey() { return isKey; } @@ -103,11 +128,11 @@ public class ComponentMetamodel implements Serializable { } public int getPropertyIndex(String propertyName) { - Integer index = ( Integer ) propertyIndexes.get( propertyName ); + Integer index = propertyIndexes.get( propertyName ); if ( index == null ) { throw new HibernateException( "component does not contain such a property [" + propertyName + "]" ); } - return index.intValue(); + return index; } public StandardProperty getProperty(String propertyName) { diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/component/ComponentTuplizerFactory.java b/hibernate-core/src/main/java/org/hibernate/tuple/component/ComponentTuplizerFactory.java index 5910eb6b48..92645a0fef 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/component/ComponentTuplizerFactory.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/component/ComponentTuplizerFactory.java @@ -32,6 +32,7 @@ import org.hibernate.EntityMode; import org.hibernate.HibernateException; import org.hibernate.internal.util.ReflectHelper; import org.hibernate.mapping.Component; +import org.hibernate.metamodel.spi.binding.CompositeAttributeBinding; /** * A registry allowing users to define the default {@link ComponentTuplizer} class to use per {@link EntityMode}. @@ -40,6 +41,8 @@ import org.hibernate.mapping.Component; */ public class ComponentTuplizerFactory implements Serializable { private static final Class[] COMPONENT_TUP_CTOR_SIG = new Class[] { Component.class }; + private static final Class[] COMPONENT_TUP_CTOR_SIG_NEW = new Class[] { CompositeAttributeBinding.class }; + private Map> defaultImplClassByMode = buildBaseMapping(); @@ -53,9 +56,11 @@ public class ComponentTuplizerFactory implements Serializable { public void registerDefaultTuplizerClass(EntityMode entityMode, Class tuplizerClass) { assert isComponentTuplizerImplementor( tuplizerClass ) : "Specified tuplizer class [" + tuplizerClass.getName() + "] does not implement " + ComponentTuplizer.class.getName(); - assert hasProperConstructor( tuplizerClass ) + // TODO: for now we need constructors for both PersistentClass and EntityBinding + assert hasProperConstructor( tuplizerClass, COMPONENT_TUP_CTOR_SIG ) + : "Specified tuplizer class [" + tuplizerClass.getName() + "] is not properly instantiatable"; + assert hasProperConstructor( tuplizerClass, COMPONENT_TUP_CTOR_SIG_NEW ) : "Specified tuplizer class [" + tuplizerClass.getName() + "] is not properly instantiatable"; - defaultImplClassByMode.put( entityMode, tuplizerClass ); } @@ -81,6 +86,28 @@ public class ComponentTuplizerFactory implements Serializable { } } + /** + * Construct an instance of the given tuplizer class. + * + * @param tuplizerClassName The name of the tuplizer class to instantiate + * @param metadata The metadata for the component. + * + * @return The instantiated tuplizer + * + * @throws HibernateException If class name cannot be resolved to a class reference, or if the + * {@link Constructor#newInstance} call fails. + */ + @SuppressWarnings({ "unchecked" }) + public ComponentTuplizer constructTuplizer(String tuplizerClassName, CompositeAttributeBinding metadata) { + try { + Class tuplizerClass = ReflectHelper.classForName( tuplizerClassName ); + return constructTuplizer( tuplizerClass, metadata ); + } + catch ( ClassNotFoundException e ) { + throw new HibernateException( "Could not locate specified tuplizer class [" + tuplizerClassName + "]" ); + } + } + /** * Construct an instance of the given tuplizer class. * @@ -92,7 +119,28 @@ public class ComponentTuplizerFactory implements Serializable { * @throws HibernateException if the {@link java.lang.reflect.Constructor#newInstance} call fails. */ public ComponentTuplizer constructTuplizer(Class tuplizerClass, Component metadata) { - Constructor constructor = getProperConstructor( tuplizerClass ); + Constructor constructor = getProperConstructor( tuplizerClass, COMPONENT_TUP_CTOR_SIG ); + assert constructor != null : "Unable to locate proper constructor for tuplizer [" + tuplizerClass.getName() + "]"; + try { + return constructor.newInstance( metadata ); + } + catch ( Throwable t ) { + throw new HibernateException( "Unable to instantiate default tuplizer [" + tuplizerClass.getName() + "]", t ); + } + } + + /** + * Construct an instance of the given tuplizer class. + * + * @param tuplizerClass The tuplizer class to instantiate + * @param metadata The metadata for the component. + * + * @return The instantiated tuplizer + * + * @throws HibernateException if the {@link java.lang.reflect.Constructor#newInstance} call fails. + */ + public ComponentTuplizer constructTuplizer(Class tuplizerClass, CompositeAttributeBinding metadata) { + Constructor constructor = getProperConstructor( tuplizerClass, COMPONENT_TUP_CTOR_SIG_NEW ); assert constructor != null : "Unable to locate proper constructor for tuplizer [" + tuplizerClass.getName() + "]"; try { return constructor.newInstance( metadata ); @@ -122,19 +170,41 @@ public class ComponentTuplizerFactory implements Serializable { return constructTuplizer( tuplizerClass, metadata ); } + /** + * Construct am instance of the default tuplizer for the given entity-mode. + * + * @param entityMode The entity mode for which to build a default tuplizer. + * @param metadata The metadata for the component. + * + * @return The instantiated tuplizer + * + * @throws HibernateException If no default tuplizer found for that entity-mode; may be re-thrown from + * {@link #constructTuplizer} too. + */ + public ComponentTuplizer constructDefaultTuplizer(EntityMode entityMode, CompositeAttributeBinding metadata) { + Class tuplizerClass = defaultImplClassByMode.get( entityMode ); + if ( tuplizerClass == null ) { + throw new HibernateException( "could not determine default tuplizer class to use [" + entityMode + "]" ); + } + + return constructTuplizer( tuplizerClass, metadata ); + } + private boolean isComponentTuplizerImplementor(Class tuplizerClass) { return ReflectHelper.implementsInterface( tuplizerClass, ComponentTuplizer.class ); } @SuppressWarnings({ "unchecked" }) - private boolean hasProperConstructor(Class tuplizerClass) { - return getProperConstructor( tuplizerClass ) != null; + private boolean hasProperConstructor(Class tuplizerClass, Class[] clazzConstructorSignature) { + return getProperConstructor( tuplizerClass, clazzConstructorSignature ) != null; } - private Constructor getProperConstructor(Class clazz) { + private Constructor getProperConstructor( + Class clazz, + Class[] clazzConstructorSignature) { Constructor constructor = null; try { - constructor = clazz.getDeclaredConstructor( COMPONENT_TUP_CTOR_SIG ); + constructor = clazz.getDeclaredConstructor( clazzConstructorSignature ); if ( ! ReflectHelper.isPublic( constructor ) ) { try { // found a constructor, but it was not publicly accessible so try to request accessibility diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/component/DynamicMapComponentTuplizer.java b/hibernate-core/src/main/java/org/hibernate/tuple/component/DynamicMapComponentTuplizer.java index c26b346e02..a9eb8aad4b 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/component/DynamicMapComponentTuplizer.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/component/DynamicMapComponentTuplizer.java @@ -27,12 +27,15 @@ import java.util.Map; import org.hibernate.mapping.Component; import org.hibernate.mapping.Property; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.CompositeAttributeBinding; import org.hibernate.property.Getter; import org.hibernate.property.PropertyAccessor; import org.hibernate.property.PropertyAccessorFactory; import org.hibernate.property.Setter; import org.hibernate.tuple.DynamicMapInstantiator; import org.hibernate.tuple.Instantiator; +import org.hibernate.tuple.PropertyFactory; /** * A {@link ComponentTuplizer} specific to the dynamic-map entity mode. @@ -66,4 +69,8 @@ public class DynamicMapComponentTuplizer extends AbstractComponentTuplizer { return buildPropertyAccessor(prop).getSetter( null, prop.getName() ); } + @Override + protected Instantiator buildInstantiator(CompositeAttributeBinding component) { + return new DynamicMapInstantiator(); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/component/PojoComponentTuplizer.java b/hibernate-core/src/main/java/org/hibernate/tuple/component/PojoComponentTuplizer.java index f36ac08939..e2387332ea 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/component/PojoComponentTuplizer.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/component/PojoComponentTuplizer.java @@ -35,6 +35,8 @@ import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.internal.util.ReflectHelper; import org.hibernate.mapping.Component; import org.hibernate.mapping.Property; +import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.CompositeAttributeBinding; import org.hibernate.property.BackrefPropertyAccessor; import org.hibernate.property.Getter; import org.hibernate.property.PropertyAccessor; @@ -42,6 +44,7 @@ import org.hibernate.property.PropertyAccessorFactory; import org.hibernate.property.Setter; import org.hibernate.tuple.Instantiator; import org.hibernate.tuple.PojoInstantiator; +import org.hibernate.tuple.PropertyFactory; /** * A {@link ComponentTuplizer} specific to the pojo entity mode. @@ -92,6 +95,44 @@ public class PojoComponentTuplizer extends AbstractComponentTuplizer { } } + public PojoComponentTuplizer(CompositeAttributeBinding component) { + super( component ); + + this.componentClass = component.getClassReference(); + + String[] getterNames = new String[propertySpan]; + String[] setterNames = new String[propertySpan]; + Class[] propTypes = new Class[propertySpan]; + for ( int i = 0; i < propertySpan; i++ ) { + getterNames[i] = getters[i].getMethodName(); + setterNames[i] = setters[i].getMethodName(); + propTypes[i] = getters[i].getReturnType(); + } + + final String parentPropertyName = + component.getParentReference() == null ? null : component.getParentReference().getName(); + if ( parentPropertyName == null ) { + parentSetter = null; + parentGetter = null; + } + else { + PropertyAccessor pa = PropertyAccessorFactory.getPropertyAccessor( null ); + parentSetter = pa.getSetter( componentClass, parentPropertyName ); + parentGetter = pa.getGetter( componentClass, parentPropertyName ); + } + + if ( hasCustomAccessors || !Environment.useReflectionOptimizer() ) { + optimizer = null; + } + else { + // TODO: here is why we need to make bytecode provider global :( + // TODO : again, fix this after HHH-1907 is complete + optimizer = Environment.getBytecodeProvider().getReflectionOptimizer( + componentClass, getterNames, setterNames, propTypes + ); + } + } + public Class getMappedClass() { return componentClass; } @@ -159,6 +200,18 @@ public class PojoComponentTuplizer extends AbstractComponentTuplizer { return prop.getSetter( component.getComponentClass() ); } + protected Instantiator buildInstantiator(CompositeAttributeBinding component) { + if ( component.getAttribute().isSynthetic() && ReflectHelper.isAbstractClass( component.getClassReference() ) ) { + return new ProxiedInstantiator( component ); + } + if ( optimizer == null ) { + return new PojoInstantiator( component, null ); + } + else { + return new PojoInstantiator( component, optimizer.getInstantiationOptimizer() ); + } + } + private static class ProxiedInstantiator implements Instantiator { private final Class proxiedClass; private final BasicProxyFactory factory; @@ -177,6 +230,20 @@ public class PojoComponentTuplizer extends AbstractComponentTuplizer { } } + public ProxiedInstantiator(CompositeAttributeBinding component) { + proxiedClass = component.getClassReference(); + if ( proxiedClass.isInterface() ) { + factory = Environment.getBytecodeProvider() + .getProxyFactoryFactory() + .buildBasicProxyFactory( null, new Class[] { proxiedClass } ); + } + else { + factory = Environment.getBytecodeProvider() + .getProxyFactoryFactory() + .buildBasicProxyFactory( proxiedClass, null ); + } + } + public Object instantiate(Serializable id) { throw new AssertionFailure( "ProxiedInstantiator can only be used to instantiate component" ); } diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/entity/DynamicMapEntityTuplizer.java b/hibernate-core/src/main/java/org/hibernate/tuple/entity/DynamicMapEntityTuplizer.java index d46022d16f..469e894c8b 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/entity/DynamicMapEntityTuplizer.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/entity/DynamicMapEntityTuplizer.java @@ -43,6 +43,7 @@ import org.hibernate.proxy.ProxyFactory; import org.hibernate.proxy.map.MapProxyFactory; import org.hibernate.tuple.DynamicMapInstantiator; import org.hibernate.tuple.Instantiator; +import org.hibernate.tuple.PropertyFactory; /** * An {@link EntityTuplizer} specific to the dynamic-map entity mode. @@ -128,21 +129,12 @@ public class DynamicMapEntityTuplizer extends AbstractEntityTuplizer { return pf; } - private PropertyAccessor buildPropertyAccessor(AttributeBinding mappedProperty) { - if ( mappedProperty.isBackRef() ) { - return PropertyAccessorFactory.getPropertyAccessor( null, mappedProperty.getPropertyAccessorName() ); - } - else { - return PropertyAccessorFactory.getDynamicMapPropertyAccessor(); - } - } - /** * {@inheritDoc} */ @Override protected Getter buildPropertyGetter(AttributeBinding mappedProperty) { - return buildPropertyAccessor( mappedProperty ).getGetter( null, mappedProperty.getAttribute().getName() ); + return PropertyFactory.getGetter( mappedProperty ); } /** @@ -150,7 +142,7 @@ public class DynamicMapEntityTuplizer extends AbstractEntityTuplizer { */ @Override protected Setter buildPropertySetter(AttributeBinding mappedProperty) { - return buildPropertyAccessor( mappedProperty ).getSetter( null, mappedProperty.getAttribute().getName() ); + return PropertyFactory.getSetter( mappedProperty ); } /** diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/entity/PojoEntityTuplizer.java b/hibernate-core/src/main/java/org/hibernate/tuple/entity/PojoEntityTuplizer.java index d7c49cf183..da1beef4d0 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/entity/PojoEntityTuplizer.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/entity/PojoEntityTuplizer.java @@ -36,7 +36,6 @@ import org.hibernate.EntityMode; import org.hibernate.EntityNameResolver; import org.hibernate.HibernateException; import org.hibernate.MappingException; -import org.hibernate.PropertyNotFoundException; import org.hibernate.bytecode.instrumentation.internal.FieldInterceptionHelper; import org.hibernate.bytecode.instrumentation.spi.FieldInterceptor; import org.hibernate.bytecode.spi.ReflectionOptimizer; @@ -52,13 +51,12 @@ import org.hibernate.mapping.Subclass; import org.hibernate.metamodel.spi.binding.AttributeBinding; import org.hibernate.metamodel.spi.binding.EntityBinding; import org.hibernate.property.Getter; -import org.hibernate.property.PropertyAccessor; -import org.hibernate.property.PropertyAccessorFactory; import org.hibernate.property.Setter; import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.ProxyFactory; import org.hibernate.tuple.Instantiator; import org.hibernate.tuple.PojoInstantiator; +import org.hibernate.tuple.PropertyFactory; import org.hibernate.type.CompositeType; /** @@ -295,11 +293,11 @@ public class PojoEntityTuplizer extends AbstractEntityTuplizer { } for ( AttributeBinding property : entityBinding.attributeBindings() ) { - Method method = getGetter( property ).getMethod(); + Method method = PropertyFactory.getGetter( property ).getMethod(); if ( method != null && Modifier.isFinal( method.getModifiers() ) ) { LOG.gettersOfLazyClassesCannotBeFinal(entityBinding.getEntity().getName(), property.getAttribute().getName()); } - method = getSetter( property ).getMethod(); + method = PropertyFactory.getSetter( property ).getMethod(); if ( method != null && Modifier.isFinal( method.getModifiers() ) ) { LOG.settersOfLazyClassesCannotBeFinal(entityBinding.getEntity().getName(), property.getAttribute().getName()); } @@ -448,7 +446,7 @@ public class PojoEntityTuplizer extends AbstractEntityTuplizer { */ @Override protected Getter buildPropertyGetter(AttributeBinding mappedProperty) { - return getGetter( mappedProperty ); + return PropertyFactory.getGetter( mappedProperty ); } /** @@ -456,26 +454,7 @@ public class PojoEntityTuplizer extends AbstractEntityTuplizer { */ @Override protected Setter buildPropertySetter(AttributeBinding mappedProperty) { - return getSetter( mappedProperty ); - } - - private Getter getGetter(AttributeBinding mappedProperty) throws PropertyNotFoundException, MappingException { - return getPropertyAccessor( mappedProperty ).getGetter( - mappedProperty.getContainer().getClassReference(), - mappedProperty.getAttribute().getName() - ); - } - - private Setter getSetter(AttributeBinding mappedProperty) throws PropertyNotFoundException, MappingException { - return getPropertyAccessor( mappedProperty ).getSetter( - mappedProperty.getContainer().getClassReference(), - mappedProperty.getAttribute().getName() - ); - } - - private PropertyAccessor getPropertyAccessor(AttributeBinding mappedProperty) throws MappingException { - // TODO: Fix this then backrefs are working in new metamodel - return PropertyAccessorFactory.getPropertyAccessor( mappedProperty, getEntityMode() ); + return PropertyFactory.getSetter( mappedProperty ); } /** diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/EmbeddableBindingTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/EmbeddableBindingTest.java index f9ad2a9aa5..de3d1d3a4b 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/EmbeddableBindingTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/EmbeddableBindingTest.java @@ -301,6 +301,15 @@ public class EmbeddableBindingTest extends BaseAnnotationBindingTestCase { private String test; @Parent private MainEntity parent; + + // require getter/setter for parent because of HHH-1614 + public MainEntity getParent() { + return parent; + } + + public void setParent(MainEntity parent) { + this.parent = parent; + } } @Entity @@ -331,13 +340,21 @@ public class EmbeddableBindingTest extends BaseAnnotationBindingTestCase { public interface Car { int getHorsePower(); + void setHorsePower(int horsePower); } @Embeddable public class CarImpl implements Car { + private int horsePower; + @Override public int getHorsePower() { - return 0; + return horsePower; + } + + @Override + public void setHorsePower(int horsePower) { + this.horsePower = horsePower; } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/bidir/onetomany/nonindexed/AbstractBidirectionalOneToManyTest.java b/hibernate-core/src/test/java/org/hibernate/test/bidir/onetomany/nonindexed/AbstractBidirectionalOneToManyTest.java new file mode 100644 index 0000000000..1eb8262c33 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/bidir/onetomany/nonindexed/AbstractBidirectionalOneToManyTest.java @@ -0,0 +1,45 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.bidir.onetomany.nonindexed; + +import org.junit.Test; + +import org.hibernate.cfg.Configuration; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; + +/** + * @author Gail Badner + */ +public class AbstractBidirectionalOneToManyTest extends BaseCoreFunctionalTestCase { + + @Override + public void configure(Configuration cfg) { + super.configure( cfg ); + cfg.setProperty( USE_NEW_METADATA_MAPPINGS, "true"); + } + + @Test + public void testDoNothing() { + } +} \ No newline at end of file diff --git a/hibernate-core/src/test/java/org/hibernate/test/bidir/onetomany/nonindexed/inverse/BidirectionalOneToManyInverseTest.java b/hibernate-core/src/test/java/org/hibernate/test/bidir/onetomany/nonindexed/BidirectionalOneToManyInverseTest.java similarity index 75% rename from hibernate-core/src/test/java/org/hibernate/test/bidir/onetomany/nonindexed/inverse/BidirectionalOneToManyInverseTest.java rename to hibernate-core/src/test/java/org/hibernate/test/bidir/onetomany/nonindexed/BidirectionalOneToManyInverseTest.java index 2fefb3b6a8..4b4ef8a841 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/bidir/onetomany/nonindexed/inverse/BidirectionalOneToManyInverseTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/bidir/onetomany/nonindexed/BidirectionalOneToManyInverseTest.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.test.bidir.onetomany.nonindexed.inverse; +package org.hibernate.test.bidir.onetomany.nonindexed; import org.junit.Test; @@ -31,20 +31,10 @@ import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; /** * @author Gail Badner */ -public class BidirectionalOneToManyInverseTest extends BaseCoreFunctionalTestCase { +public class BidirectionalOneToManyInverseTest extends AbstractBidirectionalOneToManyTest { @Override public String[] getMappings() { - return new String[] { "bidir/onetomany/nonindexed/inverse/ParentChild.hbm.xml" }; - } - - @Override - public void configure(Configuration cfg) { - super.configure( cfg ); - cfg.setProperty( USE_NEW_METADATA_MAPPINGS, "true"); - } - - @Test - public void testDoNothing() { + return new String[] { "bidir/onetomany/nonindexed/ParentChildInverseOneToMany.hbm.xml" }; } } \ No newline at end of file diff --git a/hibernate-core/src/test/java/org/hibernate/test/bidir/onetomany/nonindexed/BidirectionalOneToManyNonInverseTest.java b/hibernate-core/src/test/java/org/hibernate/test/bidir/onetomany/nonindexed/BidirectionalOneToManyNonInverseTest.java new file mode 100644 index 0000000000..44d9d58e09 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/bidir/onetomany/nonindexed/BidirectionalOneToManyNonInverseTest.java @@ -0,0 +1,35 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.bidir.onetomany.nonindexed; + +/** + * @author Gail Badner + */ +public class BidirectionalOneToManyNonInverseTest extends AbstractBidirectionalOneToManyTest { + + @Override + public String[] getMappings() { + return new String[] { "bidir/onetomany/nonindexed/ParentChildNonInverseOneToMany.hbm.xml" }; + } +} \ No newline at end of file diff --git a/hibernate-core/src/test/java/org/hibernate/test/bidir/onetomany/nonindexed/inverse/Child.java b/hibernate-core/src/test/java/org/hibernate/test/bidir/onetomany/nonindexed/Child.java similarity index 91% rename from hibernate-core/src/test/java/org/hibernate/test/bidir/onetomany/nonindexed/inverse/Child.java rename to hibernate-core/src/test/java/org/hibernate/test/bidir/onetomany/nonindexed/Child.java index 18da43503c..8272eff407 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/bidir/onetomany/nonindexed/inverse/Child.java +++ b/hibernate-core/src/test/java/org/hibernate/test/bidir/onetomany/nonindexed/Child.java @@ -1,5 +1,5 @@ //$Id: Child.java 5686 2005-02-12 07:27:32Z steveebersole $ -package org.hibernate.test.bidir.onetomany.nonindexed.inverse; +package org.hibernate.test.bidir.onetomany.nonindexed; diff --git a/hibernate-core/src/test/java/org/hibernate/test/bidir/onetomany/nonindexed/inverse/Parent.java b/hibernate-core/src/test/java/org/hibernate/test/bidir/onetomany/nonindexed/Parent.java similarity index 89% rename from hibernate-core/src/test/java/org/hibernate/test/bidir/onetomany/nonindexed/inverse/Parent.java rename to hibernate-core/src/test/java/org/hibernate/test/bidir/onetomany/nonindexed/Parent.java index b69de5f1c1..e85cc6404f 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/bidir/onetomany/nonindexed/inverse/Parent.java +++ b/hibernate-core/src/test/java/org/hibernate/test/bidir/onetomany/nonindexed/Parent.java @@ -1,5 +1,5 @@ //$Id: Parent.java 5686 2005-02-12 07:27:32Z steveebersole $ -package org.hibernate.test.bidir.onetomany.nonindexed.inverse; +package org.hibernate.test.bidir.onetomany.nonindexed; import java.util.HashSet; import java.util.Set; diff --git a/hibernate-core/src/test/java/org/hibernate/test/bidir/onetomany/nonindexed/inverse/ParentChild.hbm.xml b/hibernate-core/src/test/java/org/hibernate/test/bidir/onetomany/nonindexed/ParentChildInverseOneToMany.hbm.xml similarity index 96% rename from hibernate-core/src/test/java/org/hibernate/test/bidir/onetomany/nonindexed/inverse/ParentChild.hbm.xml rename to hibernate-core/src/test/java/org/hibernate/test/bidir/onetomany/nonindexed/ParentChildInverseOneToMany.hbm.xml index b8ad47f0e9..bbbd885e59 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/bidir/onetomany/nonindexed/inverse/ParentChild.hbm.xml +++ b/hibernate-core/src/test/java/org/hibernate/test/bidir/onetomany/nonindexed/ParentChildInverseOneToMany.hbm.xml @@ -1,5 +1,5 @@ - diff --git a/hibernate-core/src/test/java/org/hibernate/test/bidir/onetomany/nonindexed/ParentChildNonInverseOneToMany.hbm.xml b/hibernate-core/src/test/java/org/hibernate/test/bidir/onetomany/nonindexed/ParentChildNonInverseOneToMany.hbm.xml new file mode 100755 index 0000000000..4b2b2bbae9 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/bidir/onetomany/nonindexed/ParentChildNonInverseOneToMany.hbm.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + +