From f5e83567c53bf1ba12cdd32670a76a4156c37984 Mon Sep 17 00:00:00 2001 From: Gail Badner Date: Thu, 3 Jan 2013 19:44:46 -0800 Subject: [PATCH] HHH-7523 : Add support for key-many-to-one in composite IDs --- .../hibernate/metamodel/internal/Binder.java | 91 +++++--- .../hbm/AbstractToOneAttributeSourceImpl.java | 12 +- .../hbm/IdentifierKeyManyToOneSourceImpl.java | 44 ++++ .../source/hbm/KeyAttributeSourceImpl.java | 2 +- .../source/hbm/KeyManyToOneSourceImpl.java | 197 ++++++++++++++++++ .../hbm/ManyToOneAttributeSourceImpl.java | 5 + .../hbm/OneToOneAttributeSourceImpl.java | 5 + .../source/hbm/RootEntitySourceImpl.java | 27 +-- .../AbstractAttributeBindingContainer.java | 6 +- ...actCompositeAttributeBindingContainer.java | 6 +- .../binding/AttributeBindingContainer.java | 7 +- .../binding/CompositeAttributeBinding.java | 6 +- .../spi/binding/EntityIdentifier.java | 9 - .../spi/binding/OneToOneAttributeBinding.java | 6 +- ...edIdentityIdClassParentIdClassDepTest.java | 11 + .../IdentifierPropertyReferencesTest.java | 1 - .../test/immutable/ImmutableTest.java | 3 +- .../component/EagerKeyManyToOneTest.java | 1 - .../bidir/component/LazyKeyManyToOneTest.java | 1 - .../bidir/embedded/KeyManyToOneTest.java | 2 +- .../DiscrimSubclassOneToOneTest.java | 1 - .../junit4/BaseCoreFunctionalTestCase.java | 2 +- 22 files changed, 367 insertions(+), 78 deletions(-) create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/IdentifierKeyManyToOneSourceImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/KeyManyToOneSourceImpl.java 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 9b78e91f2c..99ab7e02b4 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 @@ -27,6 +27,7 @@ import static org.hibernate.engine.spi.SyntheticAttributeHelper.SYNTHETIC_COMPOS import java.lang.reflect.Modifier; import java.util.ArrayList; +import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; @@ -92,6 +93,7 @@ import org.hibernate.metamodel.spi.binding.SetBinding; import org.hibernate.metamodel.spi.binding.SingularAssociationAttributeBinding; import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; import org.hibernate.metamodel.spi.binding.SingularAttributeBinding.NaturalIdMutability; +import org.hibernate.metamodel.spi.binding.SingularNonAssociationAttributeBinding; import org.hibernate.metamodel.spi.domain.Aggregate; import org.hibernate.metamodel.spi.domain.Attribute; import org.hibernate.metamodel.spi.domain.Entity; @@ -775,11 +777,6 @@ public class Binder { for ( SingularAttributeSource attributeSource : identifierSource.getAttributeSourcesMakingUpIdentifier() ) { SingularAttributeBinding singularAttributeBinding = bindIdentifierAttribute( rootEntityBinding, attributeSource ); - if ( singularAttributeBinding.isAssociation() ) { - throw new NotYetImplementedException( - "composite IDs containing an association attribute is not implemented yet." - ); - } idAttributeBindings.add( singularAttributeBinding ); } @@ -1128,13 +1125,12 @@ public class Binder { public EntityType resolveEntityType( EntityBinding referencedEntityBinding, SingularAttributeBinding referencedAttributeBinding) { - final boolean isRefToPk = - referencedEntityBinding - .getHierarchyDetails().getEntityIdentifier().isIdentifierAttributeBinding( - referencedAttributeBinding - ); + final SingularNonAssociationAttributeBinding idAttributeBinding = + referencedEntityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(); final String uniqueKeyAttributeName = - isRefToPk ? null : getRelativePathFromEntityName( referencedAttributeBinding ); + idAttributeBinding == referencedAttributeBinding ? + null : + getRelativePathFromEntityName( referencedAttributeBinding ); return metadata.getTypeResolver().getTypeFactory().manyToOne( referencedEntityBinding.getEntity().getName(), uniqueKeyAttributeName, @@ -1183,6 +1179,34 @@ public class Binder { EntityBinding referencedEntityBinding, SingularAttributeBinding referencedAttributeBinding ) { + /** + * this is not correct, here, if no @JoinColumn defined, we simply create the FK column only with column calucated + * but what we should do is get all the column info from the referenced column(s), including nullable, size etc. + */ + final TableSpecification table = locateDefaultTableSpecificationForAttribute( + attributeBindingContainer, + attributeSource + ); + final List relationalValueBindings; + if ( ! attributeSource.relationalValueSources().isEmpty() ) { + relationalValueBindings = + bindValues( + attributeBindingContainer, + attributeSource, + actualAttribute, + table, + attributeSource.getDefaultNamingStrategies( + attributeBindingContainer.seekEntityBinding().getEntity().getName(), + table.getLogicalName().getText(), + referencedAttributeBinding + ), + false + ); + } + else { + relationalValueBindings = Collections.emptyList(); + } + // todo : currently a chicken-egg problem here between creating the attribute binding and binding its FK values... return attributeBindingContainer.makeOneToOneAttributeBinding( actualAttribute, @@ -1193,7 +1217,8 @@ public class Binder { createMetaAttributeContext( attributeBindingContainer, attributeSource ), referencedEntityBinding, referencedAttributeBinding, - attributeSource.getForeignKeyDirection() == ForeignKeyDirection.FROM_PARENT + attributeSource.getForeignKeyDirection() == ForeignKeyDirection.FROM_PARENT, + relationalValueBindings ); } @@ -1201,22 +1226,34 @@ public class Binder { public EntityType resolveEntityType( EntityBinding referencedEntityBinding, SingularAttributeBinding referencedAttributeBinding) { - final boolean isRefToPk = - referencedEntityBinding - .getHierarchyDetails().getEntityIdentifier().isIdentifierAttributeBinding( - referencedAttributeBinding - ); + final SingularNonAssociationAttributeBinding idAttributeBinding = + referencedEntityBinding.getHierarchyDetails().getEntityIdentifier().getAttributeBinding(); final String uniqueKeyAttributeName = - isRefToPk ? null : getRelativePathFromEntityName( referencedAttributeBinding ); - return metadata.getTypeResolver().getTypeFactory().oneToOne( - referencedEntityBinding.getEntity().getName(), - attributeSource.getForeignKeyDirection(), - uniqueKeyAttributeName, - attributeSource.getFetchTiming() != FetchTiming.IMMEDIATE, - attributeSource.isUnWrapProxy(), - attributeBindingContainer.seekEntityBinding().getEntityName(), - actualAttribute.getName() - ); + idAttributeBinding == referencedAttributeBinding ? + null : + getRelativePathFromEntityName( referencedAttributeBinding ); + if ( attributeSource.relationalValueSources().isEmpty() ) { + return metadata.getTypeResolver().getTypeFactory().oneToOne( + referencedEntityBinding.getEntity().getName(), + attributeSource.getForeignKeyDirection(), + uniqueKeyAttributeName, + attributeSource.getFetchTiming() != FetchTiming.IMMEDIATE, + attributeSource.isUnWrapProxy(), + attributeBindingContainer.seekEntityBinding().getEntityName(), + actualAttribute.getName() + ); + } + else { + return metadata.getTypeResolver().getTypeFactory().specialOneToOne( + referencedEntityBinding.getEntity().getName(), + attributeSource.getForeignKeyDirection(), + uniqueKeyAttributeName, + attributeSource.getFetchTiming() != FetchTiming.IMMEDIATE, + attributeSource.isUnWrapProxy(), + attributeBindingContainer.seekEntityBinding().getEntityName(), + actualAttribute.getName() + ); + } } }; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/AbstractToOneAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/AbstractToOneAttributeSourceImpl.java index 91928691fb..506fdc48cb 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/AbstractToOneAttributeSourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/AbstractToOneAttributeSourceImpl.java @@ -37,6 +37,7 @@ import org.hibernate.metamodel.spi.relational.Value; import org.hibernate.metamodel.spi.source.ExplicitHibernateTypeSource; import org.hibernate.metamodel.spi.source.MappingException; import org.hibernate.metamodel.spi.source.ToOneAttributeSource; +import org.hibernate.type.ForeignKeyDirection; /** * @author Gail Badner @@ -84,6 +85,7 @@ public abstract class AbstractToOneAttributeSourceImpl extends AbstractHbmSource return getFetchTiming() != FetchTiming.IMMEDIATE; } + protected abstract boolean requiresImmediateFetch(); protected abstract String getFetchSelectionString(); protected abstract String getLazySelectionString(); protected abstract String getOuterJoinSelectionString(); @@ -99,7 +101,10 @@ public abstract class AbstractToOneAttributeSourceImpl extends AbstractHbmSource final String lazySelection = getLazySelectionString(); if ( lazySelection == null ) { - if ( "join".equals( getFetchSelectionString() ) || "true".equals( getOuterJoinSelectionString() ) ) { + if ( requiresImmediateFetch() ) { + return FetchTiming.IMMEDIATE; + } + else if ( "join".equals( getFetchSelectionString() ) || "true".equals( getOuterJoinSelectionString() ) ) { return FetchTiming.IMMEDIATE; } else if ( "false".equals( getOuterJoinSelectionString() ) ) { @@ -136,7 +141,10 @@ public abstract class AbstractToOneAttributeSourceImpl extends AbstractHbmSource // todo : handle batch fetches? if ( getFetchSelectionString() == null ) { - if ( getOuterJoinSelectionString() == null ) { + if ( requiresImmediateFetch() ) { + return FetchStyle.JOIN; + } + else if ( getOuterJoinSelectionString() == null ) { return FetchStyle.SELECT; } else { diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/IdentifierKeyManyToOneSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/IdentifierKeyManyToOneSourceImpl.java new file mode 100644 index 0000000000..2a942ebb50 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/IdentifierKeyManyToOneSourceImpl.java @@ -0,0 +1,44 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, 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.source.hbm; + +import org.hibernate.jaxb.spi.hbm.JaxbKeyManyToOneElement; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; + +/** + * @author Gail Badner + */ +public class IdentifierKeyManyToOneSourceImpl extends KeyManyToOneSourceImpl { + + public IdentifierKeyManyToOneSourceImpl( + MappingDocument mappingDocument, + final JaxbKeyManyToOneElement keyManyToOneElement) { + super( mappingDocument, keyManyToOneElement, SingularAttributeBinding.NaturalIdMutability.NOT_NATURAL_ID ); + } + + @Override + public boolean areValuesIncludedInUpdateByDefault() { + return true; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/KeyAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/KeyAttributeSourceImpl.java index cefc1224b8..15e77b070e 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/KeyAttributeSourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/KeyAttributeSourceImpl.java @@ -163,7 +163,7 @@ class KeyAttributeSourceImpl @Override public String getContainingTableName() { - return null; //To change body of implemented methods use File | Settings | File Templates. + return null; } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/KeyManyToOneSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/KeyManyToOneSourceImpl.java new file mode 100644 index 0000000000..e07c8f0815 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/KeyManyToOneSourceImpl.java @@ -0,0 +1,197 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2013, 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.source.hbm; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.hibernate.engine.spi.CascadeStyle; +import org.hibernate.engine.spi.CascadeStyles; +import org.hibernate.internal.util.collections.CollectionHelper; +import org.hibernate.jaxb.spi.hbm.JaxbColumnElement; +import org.hibernate.jaxb.spi.hbm.JaxbKeyManyToOneElement; +import org.hibernate.mapping.PropertyGeneration; +import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; +import org.hibernate.metamodel.spi.source.ExplicitHibernateTypeSource; +import org.hibernate.metamodel.spi.source.MetaAttributeSource; +import org.hibernate.metamodel.spi.source.RelationalValueSource; +import org.hibernate.metamodel.spi.source.SingularAttributeSource; +import org.hibernate.type.ForeignKeyDirection; + +/** + * Implementation for {@code } mappings + * + * @author Gail Badner + */ +class KeyManyToOneSourceImpl + extends AbstractToOneAttributeSourceImpl + implements SingularAttributeSource { + private final JaxbKeyManyToOneElement keyManyToOneElement; + private final List valueSources; + + public KeyManyToOneSourceImpl( + MappingDocument mappingDocument, + final JaxbKeyManyToOneElement keyManyToOneElement, + final SingularAttributeBinding.NaturalIdMutability naturalIdMutability) { + super( mappingDocument, naturalIdMutability, null ); + this.keyManyToOneElement = keyManyToOneElement; + this.valueSources = Helper.buildValueSources( + sourceMappingDocument(), + new Helper.ValueSourcesAdapter() { + @Override + public String getColumnAttribute() { + return keyManyToOneElement.getColumnAttribute(); + } + + @Override + public String getFormulaAttribute() { + return null; + } + + @Override + public List getColumn() { + return keyManyToOneElement.getColumn(); + } + + @Override + public List getFormula() { + return CollectionHelper.createEmptyList( String.class ); + } + + @Override + public String getContainingTableName() { + return null; + } + + @Override + public boolean isIncludedInInsertByDefault() { + return true; + } + + @Override + public boolean isIncludedInUpdateByDefault() { + return false; + } + } + ); + } + + @Override + public String getName() { + return keyManyToOneElement.getName(); + } + + @Override + public String getPropertyAccessorName() { + return keyManyToOneElement.getAccess(); + } + + @Override + public boolean isIncludedInOptimisticLocking() { + return false; + } + + @Override + public Nature getNature() { + return Nature.MANY_TO_ONE; + } + + @Override + public boolean isVirtualAttribute() { + return false; + } + + @Override + protected boolean requiresImmediateFetch() { + return false; + } + + @Override + protected String getFetchSelectionString() { + return null; + } + + @Override + protected String getLazySelectionString() { + return keyManyToOneElement.getLazy() != null ? + keyManyToOneElement.getLazy().value() : + null; + } + + @Override + protected String getOuterJoinSelectionString() { + return null; + } + + @Override + public boolean areValuesIncludedInInsertByDefault() { + return true; + } + + @Override + public boolean areValuesIncludedInUpdateByDefault() { + return true; + } + + @Override + public boolean areValuesNullableByDefault() { + return false; + } + + @Override + public String getContainingTableName() { + return null; + } + + @Override + public List relationalValueSources() { + return valueSources; + } + + @Override + public Iterable getMetaAttributeSources() { + return keyManyToOneElement.getMeta(); + } + + @Override + public String getReferencedEntityName() { + return keyManyToOneElement.getEntityName(); + } + + @Override + public ForeignKeyDirection getForeignKeyDirection() { + return ForeignKeyDirection.TO_PARENT; + } + + @Override + public Iterable getCascadeStyles() { + return Collections.singleton( CascadeStyles.NONE ); + } + + @Override + public String getExplicitForeignKeyName() { + return keyManyToOneElement.getForeignKey(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ManyToOneAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ManyToOneAttributeSourceImpl.java index 1b620d26bd..945c387dad 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ManyToOneAttributeSourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ManyToOneAttributeSourceImpl.java @@ -112,6 +112,11 @@ class ManyToOneAttributeSourceImpl extends AbstractToOneAttributeSourceImpl { return Helper.interpretCascadeStyles( manyToOneElement.getCascade(), bindingContext() ); } + @Override + protected boolean requiresImmediateFetch() { + return false; + } + @Override protected String getFetchSelectionString() { return manyToOneElement.getFetch() != null ? diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/OneToOneAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/OneToOneAttributeSourceImpl.java index e63492a43c..9d45fcef94 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/OneToOneAttributeSourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/OneToOneAttributeSourceImpl.java @@ -145,6 +145,11 @@ class OneToOneAttributeSourceImpl extends AbstractToOneAttributeSourceImpl { return false; } + @Override + protected boolean requiresImmediateFetch() { + return !oneToOneElement.isConstrained(); + } + @Override public boolean areValuesIncludedInInsertByDefault() { return true; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/RootEntitySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/RootEntitySourceImpl.java index f6ae3e67db..9e37edb0c7 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/RootEntitySourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/RootEntitySourceImpl.java @@ -29,7 +29,6 @@ import java.util.List; import org.hibernate.AssertionFailure; import org.hibernate.EntityMode; import org.hibernate.TruthValue; -import org.hibernate.cfg.NotYetImplementedException; import org.hibernate.engine.OptimisticLockStyle; import org.hibernate.id.EntityIdentifierNature; import org.hibernate.internal.util.StringHelper; @@ -41,6 +40,7 @@ import org.hibernate.jaxb.spi.hbm.JaxbKeyManyToOneElement; import org.hibernate.jaxb.spi.hbm.JaxbKeyPropertyElement; import org.hibernate.jaxb.spi.hbm.JaxbMultiTenancyElement; import org.hibernate.jaxb.spi.hbm.JaxbNaturalIdElement; +import org.hibernate.jaxb.spi.hbm.JaxbPolymorphismAttribute; import org.hibernate.mapping.PropertyGeneration; import org.hibernate.metamodel.spi.binding.Caching; import org.hibernate.metamodel.spi.binding.IdGenerator; @@ -63,6 +63,7 @@ import org.hibernate.metamodel.spi.source.VersionAttributeSource; /** * @author Steve Ebersole + * @author Gail Badner */ public class RootEntitySourceImpl extends AbstractEntitySourceImpl implements RootEntitySource { private final TableSpecificationSource primaryTable; @@ -160,7 +161,7 @@ public class RootEntitySourceImpl extends AbstractEntitySourceImpl implements Ro @Override public boolean isExplicitPolymorphism() { - return "explicit".equals( entityElement().getPolymorphism() ); + return JaxbPolymorphismAttribute.EXPLICIT == entityElement().getPolymorphism(); } @Override @@ -444,14 +445,11 @@ public class RootEntitySourceImpl extends AbstractEntitySourceImpl implements Ro @Override protected List buildAttributeSources() { List attributeSources = new ArrayList(); -// for ( Object attributeElement : compositeIdElement().getKeyPropertyOrKeyManyToOne() ) { -// attributeSources.add( buildAttributeSource( attributeElement ) ); -// } for ( JaxbKeyPropertyElement keyProperty : compositeIdElement().getKeyProperty()){ attributeSources.add( new IdentifierKeyAttributeSourceImpl( sourceMappingDocument(), keyProperty ) ); } - for (JaxbKeyManyToOneElement element : compositeIdElement().getKeyManyToOne()){ - throw new NotYetImplementedException( "key-many-to-one is not supported yet" ); + for (JaxbKeyManyToOneElement keyManyToOne : compositeIdElement().getKeyManyToOne()){ + attributeSources.add( new IdentifierKeyManyToOneSourceImpl( sourceMappingDocument(), keyManyToOne ) ); } return attributeSources; } @@ -525,20 +523,11 @@ public class RootEntitySourceImpl extends AbstractEntitySourceImpl implements Ro public List getAttributeSourcesMakingUpIdentifier() { final List attributeSources = new ArrayList(); final JaxbCompositeIdElement compositeId = entityElement().getCompositeId(); - for(final JaxbKeyPropertyElement keyProperty: compositeId.getKeyProperty()) { + for ( final JaxbKeyPropertyElement keyProperty: compositeId.getKeyProperty() ) { attributeSources.add( new IdentifierKeyAttributeSourceImpl( sourceMappingDocument(), keyProperty ) ); } - for(final JaxbKeyManyToOneElement keyProperty : compositeId.getKeyManyToOne()){ -// final AttributeSource attributeSource = buildAttributeSource( -// keyProperty, -// null, -// SingularAttributeBinding.NaturalIdMutability.NOT_NATURAL_ID -// ); -// if ( ! attributeSource.isSingular() ) { -// throw new HibernateException( "Only singular attributes are supported for composite identifiers" ); -// } -// attributeSources.add( (SingularAttributeSource) attributeSource ); - //todo : implement + for ( final JaxbKeyManyToOneElement keyManyToOne : compositeId.getKeyManyToOne() ){ + attributeSources.add( new IdentifierKeyManyToOneSourceImpl( sourceMappingDocument(), keyManyToOne ) ); } return attributeSources; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractAttributeBindingContainer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractAttributeBindingContainer.java index 69c8d66bb7..c66b39dc65 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractAttributeBindingContainer.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractAttributeBindingContainer.java @@ -154,7 +154,8 @@ public abstract class AbstractAttributeBindingContainer implements AttributeBind MetaAttributeContext metaAttributeContext, EntityBinding referencedEntityBinding, SingularAttributeBinding referencedAttributeBinding, - boolean isConstrained) { + boolean isConstrained, + List valueBindings) { final OneToOneAttributeBinding binding = new OneToOneAttributeBinding( this, attribute, @@ -165,7 +166,8 @@ public abstract class AbstractAttributeBindingContainer implements AttributeBind metaAttributeContext, referencedEntityBinding, referencedAttributeBinding, - isConstrained + isConstrained, + valueBindings ); registerAttributeBinding( binding ); return binding; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractCompositeAttributeBindingContainer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractCompositeAttributeBindingContainer.java index f0c317ef1b..7befd81c66 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractCompositeAttributeBindingContainer.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractCompositeAttributeBindingContainer.java @@ -151,7 +151,8 @@ public abstract class AbstractCompositeAttributeBindingContainer MetaAttributeContext metaAttributeContext, EntityBinding referencedEntityBinding, SingularAttributeBinding referencedAttributeBinding, - boolean isConstrained) { + boolean isConstrained, + List valueBindings) { if ( !isModifiable() ) { throw new UnsupportedOperationException( "Attribute bindings are read-only and cannot be modified." ); } @@ -164,7 +165,8 @@ public abstract class AbstractCompositeAttributeBindingContainer metaAttributeContext, referencedEntityBinding, referencedAttributeBinding, - isConstrained + isConstrained, + valueBindings ); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AttributeBindingContainer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AttributeBindingContainer.java index e765de96f2..4f76c64fd2 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AttributeBindingContainer.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AttributeBindingContainer.java @@ -164,9 +164,7 @@ public interface AttributeBindingContainer { MetaAttributeContext metaAttributeContext); /** - * Factory method for many-to-one attribute bindings. - * - * + * Factory method for one-to-one attribute bindings. * * @param attribute The attribute for which to make a binding. * @param propertyAccessorName @@ -187,7 +185,8 @@ public interface AttributeBindingContainer { MetaAttributeContext metaAttributeContext, EntityBinding referencedEntityBinding, SingularAttributeBinding referencedAttributeBinding, - boolean isConstrained); + boolean isConstrained, + List valueBindings); /** 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 2d0ef2c3b3..b75c31fa63 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 @@ -404,7 +404,8 @@ public class CompositeAttributeBinding MetaAttributeContext metaAttributeContext, EntityBinding referencedEntityBinding, SingularAttributeBinding referencedAttributeBinding, - boolean isConstrained) { + boolean isConstrained, + List valueBindings) { return compositeAttributeBindingContainer.makeOneToOneAttributeBinding( attribute, propertyAccessorName, @@ -414,7 +415,8 @@ public class CompositeAttributeBinding metaAttributeContext, referencedEntityBinding, referencedAttributeBinding, - isConstrained + isConstrained, + valueBindings ); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityIdentifier.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityIdentifier.java index e2d2f1dffc..f0a4637d89 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityIdentifier.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityIdentifier.java @@ -394,15 +394,6 @@ public class EntityIdentifier { ) ); } - if ( attributeBinding.isAssociation() ) { - throw new MappingException( - String.format( - "The composite ID for [%s] contains an attribute [%s} that is an association.", - entityBinding.getEntity().getName(), - attributeBinding.getAttribute().getName() - ) - ); - } } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/OneToOneAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/OneToOneAttributeBinding.java index f7f3e23489..68a5eae42d 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/OneToOneAttributeBinding.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/OneToOneAttributeBinding.java @@ -49,7 +49,8 @@ public class OneToOneAttributeBinding MetaAttributeContext metaAttributeContext, EntityBinding referencedEntityBinding, SingularAttributeBinding referencedAttributeBinding, - boolean isConstrained) { + boolean isConstrained, + List valueBindings) { super( container, attribute, @@ -59,9 +60,8 @@ public class OneToOneAttributeBinding naturalIdMutability, metaAttributeContext, referencedEntityBinding, - CollectionHelper.createEmptyList( RelationalValueBinding.class ), + valueBindings, referencedAttributeBinding - ); this.isConstrained = isConstrained; } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e2/a/DerivedIdentityIdClassParentIdClassDepTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e2/a/DerivedIdentityIdClassParentIdClassDepTest.java index c0c066f8ee..a8006fc879 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e2/a/DerivedIdentityIdClassParentIdClassDepTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/derivedidentities/e2/a/DerivedIdentityIdClassParentIdClassDepTest.java @@ -1,8 +1,13 @@ package org.hibernate.test.annotations.derivedidentities.e2.a; +import java.util.List; + import org.junit.Test; import org.hibernate.Session; +import org.hibernate.metamodel.spi.relational.Column; +import org.hibernate.metamodel.spi.relational.PrimaryKey; +import org.hibernate.metamodel.spi.relational.TableSpecification; import org.hibernate.test.util.SchemaUtil; import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; @@ -23,6 +28,12 @@ public class DerivedIdentityIdClassParentIdClassDepTest extends BaseCoreFunction assertTrue( SchemaUtil.isColumnPresent( "Dependent", "name", metadata() ) ); assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "firstName", metadata() ) ); assertTrue( ! SchemaUtil.isColumnPresent( "Dependent", "lastName", metadata() ) ); + final TableSpecification dependentTable = SchemaUtil.getTable( "Dependent", metadata() ); + final List dependentPkColumns = dependentTable.getPrimaryKey().getColumns(); + assertEquals( 3, dependentPkColumns.size() ); + assertTrue( dependentPkColumns.contains( dependentTable.locateColumn( "name" ) ) ); + assertTrue( dependentPkColumns.contains( dependentTable.locateColumn( "FK1" ) ) ); + assertTrue( dependentPkColumns.contains( dependentTable.locateColumn( "FK2" ) ) ); Employee e = new Employee(); e.firstName = "Emmanuel"; e.lastName = "Bernard"; diff --git a/hibernate-core/src/test/java/org/hibernate/test/idprops/IdentifierPropertyReferencesTest.java b/hibernate-core/src/test/java/org/hibernate/test/idprops/IdentifierPropertyReferencesTest.java index f003468dd3..31baf5ba7c 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/idprops/IdentifierPropertyReferencesTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/idprops/IdentifierPropertyReferencesTest.java @@ -38,7 +38,6 @@ import static org.junit.Assert.assertEquals; /** * @author Steve Ebersole */ -@FailureExpectedWithNewMetamodel public class IdentifierPropertyReferencesTest extends BaseCoreFunctionalTestCase { @Override public String[] getMappings() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/immutable/ImmutableTest.java b/hibernate-core/src/test/java/org/hibernate/test/immutable/ImmutableTest.java index e1395a55a3..2498f9be99 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/immutable/ImmutableTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/immutable/ImmutableTest.java @@ -52,7 +52,6 @@ import static org.junit.Assert.fail; /** * @author Gavin King */ -@FailureExpectedWithNewMetamodel public class ImmutableTest extends BaseCoreFunctionalTestCase { private static class TextAsMaterializedClobType extends AbstractSingleColumnStandardBasicType { public final static TextAsMaterializedClobType INSTANCE = new TextAsMaterializedClobType(); @@ -853,6 +852,7 @@ public class ImmutableTest extends BaseCoreFunctionalTestCase { } @Test + @FailureExpectedWithNewMetamodel public void testImmutableCollectionWithUpdate() { clearCounts(); @@ -1074,6 +1074,7 @@ public class ImmutableTest extends BaseCoreFunctionalTestCase { } @Test + @FailureExpectedWithNewMetamodel public void testImmutableCollectionWithMerge() { clearCounts(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/keymanytoone/bidir/component/EagerKeyManyToOneTest.java b/hibernate-core/src/test/java/org/hibernate/test/keymanytoone/bidir/component/EagerKeyManyToOneTest.java index f3d2eeec0f..a050a1912b 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/keymanytoone/bidir/component/EagerKeyManyToOneTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/keymanytoone/bidir/component/EagerKeyManyToOneTest.java @@ -50,7 +50,6 @@ import static org.junit.Assert.fail; * @author Steve Ebersole */ @SuppressWarnings( {"unchecked"}) -@FailureExpectedWithNewMetamodel public class EagerKeyManyToOneTest extends BaseCoreFunctionalTestCase { @Override public String[] getMappings() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/keymanytoone/bidir/component/LazyKeyManyToOneTest.java b/hibernate-core/src/test/java/org/hibernate/test/keymanytoone/bidir/component/LazyKeyManyToOneTest.java index c0bbdd78e2..182a71e463 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/keymanytoone/bidir/component/LazyKeyManyToOneTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/keymanytoone/bidir/component/LazyKeyManyToOneTest.java @@ -37,7 +37,6 @@ import static org.junit.Assert.assertEquals; /** * @author Steve Ebersole */ -@FailureExpectedWithNewMetamodel public class LazyKeyManyToOneTest extends BaseCoreFunctionalTestCase { @Override public String[] getMappings() { diff --git a/hibernate-core/src/test/java/org/hibernate/test/keymanytoone/bidir/embedded/KeyManyToOneTest.java b/hibernate-core/src/test/java/org/hibernate/test/keymanytoone/bidir/embedded/KeyManyToOneTest.java index 2a5be5753b..612a6586c7 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/keymanytoone/bidir/embedded/KeyManyToOneTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/keymanytoone/bidir/embedded/KeyManyToOneTest.java @@ -38,7 +38,6 @@ import org.junit.Test; /** * @author Steve Ebersole */ -@FailureExpectedWithNewMetamodel public class KeyManyToOneTest extends BaseCoreFunctionalTestCase { @Override public String[] getMappings() { @@ -52,6 +51,7 @@ public class KeyManyToOneTest extends BaseCoreFunctionalTestCase { } @Test + @FailureExpectedWithNewMetamodel public void testCriteriaRestrictionOnKeyManyToOne() { Session s = openSession(); s.beginTransaction(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/onetoone/singletable/DiscrimSubclassOneToOneTest.java b/hibernate-core/src/test/java/org/hibernate/test/onetoone/singletable/DiscrimSubclassOneToOneTest.java index 4da2e93642..7d028a7420 100755 --- a/hibernate-core/src/test/java/org/hibernate/test/onetoone/singletable/DiscrimSubclassOneToOneTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/onetoone/singletable/DiscrimSubclassOneToOneTest.java @@ -42,7 +42,6 @@ import static org.junit.Assert.assertNull; /** * @author Gavin King */ -@FailureExpectedWithNewMetamodel public class DiscrimSubclassOneToOneTest extends BaseCoreFunctionalTestCase { @Override public String[] getMappings() { diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/junit4/BaseCoreFunctionalTestCase.java b/hibernate-testing/src/main/java/org/hibernate/testing/junit4/BaseCoreFunctionalTestCase.java index ddbcd9c009..55090e3946 100644 --- a/hibernate-testing/src/main/java/org/hibernate/testing/junit4/BaseCoreFunctionalTestCase.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/junit4/BaseCoreFunctionalTestCase.java @@ -336,7 +336,7 @@ public abstract class BaseCoreFunctionalTestCase extends BaseUnitTestCase { } } } - if ( !hasLob && !entityBinding.getHierarchyDetails().isExplicitPolymorphism() && overrideCacheStrategy() ) { + if ( !hasLob && entityBinding.getSuperEntityBinding() == null && overrideCacheStrategy() ) { Caching caching = entityBinding.getHierarchyDetails().getCaching(); if ( caching == null ) { caching = new Caching();