HHH-8805 HHH-7916 Support @Index(NO_CONSTRAINT) and @NotFound(IGNORE)

This commit is contained in:
Brett Meyer 2014-03-17 19:28:40 -04:00
parent 8945e9e590
commit 4651a064fa
49 changed files with 327 additions and 175 deletions

View File

@ -23,6 +23,9 @@
*/ */
package org.hibernate.metamodel.internal.binder; package org.hibernate.metamodel.internal.binder;
import static org.hibernate.MultiTenancyStrategy.DISCRIMINATOR;
import static org.hibernate.engine.spi.SyntheticAttributeHelper.SYNTHETIC_COMPOSITE_ID_ATTRIBUTE_NAME;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Comparator; import java.util.Comparator;
@ -60,6 +63,7 @@ import org.hibernate.id.PersistentIdentifierGenerator;
import org.hibernate.id.enhanced.TableGenerator; import org.hibernate.id.enhanced.TableGenerator;
import org.hibernate.internal.FilterConfiguration; import org.hibernate.internal.FilterConfiguration;
import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.StringHelper;
import org.hibernate.metamodel.internal.binder.HibernateTypeHelper.ReflectedCollectionJavaTypes;
import org.hibernate.metamodel.internal.resolver.AssociationRelationalBindingResolver; import org.hibernate.metamodel.internal.resolver.AssociationRelationalBindingResolver;
import org.hibernate.metamodel.internal.resolver.MappedByAssociationRelationalBindingResolverImpl; import org.hibernate.metamodel.internal.resolver.MappedByAssociationRelationalBindingResolverImpl;
import org.hibernate.metamodel.internal.resolver.StandardAssociationRelationalBindingResolverImpl; import org.hibernate.metamodel.internal.resolver.StandardAssociationRelationalBindingResolverImpl;
@ -165,13 +169,8 @@ import org.hibernate.tuple.component.ComponentTuplizer;
import org.hibernate.tuple.entity.EntityTuplizer; import org.hibernate.tuple.entity.EntityTuplizer;
import org.hibernate.type.ForeignKeyDirection; import org.hibernate.type.ForeignKeyDirection;
import org.hibernate.type.Type; import org.hibernate.type.Type;
import org.jboss.jandex.DotName; import org.jboss.jandex.DotName;
import static org.hibernate.MultiTenancyStrategy.DISCRIMINATOR;
import static org.hibernate.engine.spi.SyntheticAttributeHelper.SYNTHETIC_COMPOSITE_ID_ATTRIBUTE_NAME;
import static org.hibernate.metamodel.internal.binder.HibernateTypeHelper.ReflectedCollectionJavaTypes;
/** /**
* The common binder shared between annotations and {@code hbm.xml} processing. * The common binder shared between annotations and {@code hbm.xml} processing.
* *
@ -753,7 +752,8 @@ public class Binder {
joinRelationalValueBindings, joinRelationalValueBindings,
foreignKeyHelper().determineForeignKeyTargetTable( entityBinding, secondaryTableSource ), foreignKeyHelper().determineForeignKeyTargetTable( entityBinding, secondaryTableSource ),
targetColumns, targetColumns,
secondaryTableSource.isCascadeDeleteEnabled() secondaryTableSource.isCascadeDeleteEnabled(),
secondaryTableSource.createForeignKeyConstraint()
); );
SecondaryTable secondaryTable = new SecondaryTable( table, foreignKey ); SecondaryTable secondaryTable = new SecondaryTable( table, foreignKey );
if ( secondaryTableSource.getFetchStyle()!=null ) { if ( secondaryTableSource.getFetchStyle()!=null ) {
@ -1002,7 +1002,8 @@ public class Binder {
subclassEntitySource subclassEntitySource
), ),
targetColumns, targetColumns,
subclassEntitySource.isCascadeDeleteEnabled() subclassEntitySource.isCascadeDeleteEnabled(),
subclassEntitySource.createForeignKeyConstraint()
); );
if ( subclassEntitySource.isCascadeDeleteEnabled() ) { if ( subclassEntitySource.isCascadeDeleteEnabled() ) {
@ -1461,7 +1462,8 @@ public class Binder {
extractColumnsFromRelationalValueBindings( ownerAssociationAttributeBinding.getRelationalValueBindings() ), extractColumnsFromRelationalValueBindings( ownerAssociationAttributeBinding.getRelationalValueBindings() ),
entityBinding.getPrimaryTable(), entityBinding.getPrimaryTable(),
targetColumns, targetColumns,
attributeSource.isCascadeDeleteEnabled() attributeSource.isCascadeDeleteEnabled(),
true
); );
if ( foreignKey == null ) { if ( foreignKey == null ) {
throw new AssertionFailure( "Foreign key not found; should have been defined by owner side of association." ); throw new AssertionFailure( "Foreign key not found; should have been defined by owner side of association." );
@ -1553,14 +1555,16 @@ public class Binder {
final List<RelationalValueBinding> sourceRelationalValueBindings, final List<RelationalValueBinding> sourceRelationalValueBindings,
final TableSpecification targetTable, final TableSpecification targetTable,
final List<Column> targetColumns, final List<Column> targetColumns,
boolean isCascadeDeleteEnabled) { boolean isCascadeDeleteEnabled,
boolean createConstraint) {
return foreignKeyHelper().locateOrCreateForeignKey( return foreignKeyHelper().locateOrCreateForeignKey(
foreignKeyName, foreignKeyName,
sourceTable, sourceTable,
extractColumnsFromRelationalValueBindings( sourceRelationalValueBindings ), extractColumnsFromRelationalValueBindings( sourceRelationalValueBindings ),
targetTable, targetTable,
targetColumns, targetColumns,
isCascadeDeleteEnabled isCascadeDeleteEnabled,
createConstraint
); );
} }
@ -1840,16 +1844,6 @@ public class Binder {
return attributeBinding; return attributeBinding;
} }
/**
* todo: if the not found exception is ignored, here we should create an unique key instead of FK
* this guard method should be removed after we implement this.
*/
private void throwExceptionIfNotFoundIgnored(boolean isNotFoundAnException) {
if ( !isNotFoundAnException ) {
throw new NotYetImplementedException( "association of ignored not found exception is not yet implemented" );
}
}
private ManyToOneAttributeBinding bindManyToOneAttribute( private ManyToOneAttributeBinding bindManyToOneAttribute(
final AttributeBindingContainer attributeBindingContainer, final AttributeBindingContainer attributeBindingContainer,
final ToOneAttributeSource attributeSource, final ToOneAttributeSource attributeSource,
@ -1857,7 +1851,6 @@ public class Binder {
if ( attribute == null ) { if ( attribute == null ) {
attribute = createSingularAttribute( attributeBindingContainer, attributeSource ); attribute = createSingularAttribute( attributeBindingContainer, attributeSource );
} }
throwExceptionIfNotFoundIgnored( attributeSource.isNotFoundAnException() );
final JavaTypeDescriptor referencedEntityTypeDescriptor = typeHelper().determineJavaType( final JavaTypeDescriptor referencedEntityTypeDescriptor = typeHelper().determineJavaType(
attributeSource, attributeSource,
@ -1885,7 +1878,7 @@ public class Binder {
propertyAccessorName( attributeSource ), propertyAccessorName( attributeSource ),
attributeSource.isIncludedInOptimisticLocking(), attributeSource.isIncludedInOptimisticLocking(),
attributeSource.isLazy(), attributeSource.isLazy(),
attributeSource.isNotFoundAnException(), attributeSource.isIgnoreNotFound(),
attributeSource.getNaturalIdMutability(), attributeSource.getNaturalIdMutability(),
createMetaAttributeContext( attributeBindingContainer, attributeSource ), createMetaAttributeContext( attributeBindingContainer, attributeSource ),
referencedEntityBinding, referencedEntityBinding,
@ -1936,7 +1929,7 @@ public class Binder {
uniqueKeyAttributeName, uniqueKeyAttributeName,
attributeSource.getFetchTiming() != FetchTiming.IMMEDIATE, attributeSource.getFetchTiming() != FetchTiming.IMMEDIATE,
attributeSource.isUnWrapProxy(), attributeSource.isUnWrapProxy(),
!attributeSource.isNotFoundAnException(), attributeSource.isIgnoreNotFound(),
attributeSource.isUnique() attributeSource.isUnique()
); );
typeHelper().bindHibernateTypeDescriptor( typeHelper().bindHibernateTypeDescriptor(
@ -2558,7 +2551,6 @@ public class Binder {
final OneToManyPluralAttributeElementSource elementSource, final OneToManyPluralAttributeElementSource elementSource,
final EntityBinding referencedEntityBinding, final EntityBinding referencedEntityBinding,
final JavaTypeDescriptor defaultElementTypeDescriptor) { final JavaTypeDescriptor defaultElementTypeDescriptor) {
throwExceptionIfNotFoundIgnored( elementSource.isNotFoundAnException() );
elementBinding.setElementEntityIdentifier( elementBinding.setElementEntityIdentifier(
referencedEntityBinding.getKeyRelationalValueBindings() referencedEntityBinding.getKeyRelationalValueBindings()
); );
@ -2569,7 +2561,7 @@ public class Binder {
null, null,
false, false,
false, false,
!elementSource.isNotFoundAnException(), //TODO: should be attributeBinding.isIgnoreNotFound(), elementSource.isIgnoreNotFound(),
false false
); );
final HibernateTypeDescriptor hibernateTypeDescriptor = elementBinding.getHibernateTypeDescriptor(); final HibernateTypeDescriptor hibernateTypeDescriptor = elementBinding.getHibernateTypeDescriptor();
@ -2597,7 +2589,6 @@ public class Binder {
final ManyToManyPluralAttributeElementSource elementSource, final ManyToManyPluralAttributeElementSource elementSource,
final EntityBinding referencedEntityBinding, final EntityBinding referencedEntityBinding,
final JavaTypeDescriptor defaultElementTypeDescriptor) { final JavaTypeDescriptor defaultElementTypeDescriptor) {
throwExceptionIfNotFoundIgnored( elementSource.isNotFoundAnException() );
final TableSpecification collectionTable = final TableSpecification collectionTable =
elementBinding.getPluralAttributeBinding().getPluralAttributeKeyBinding().getCollectionTable(); elementBinding.getPluralAttributeBinding().getPluralAttributeKeyBinding().getCollectionTable();
final AssociationRelationalBindingResolver resolver = getAssociationRelationalBindingResolver( final AssociationRelationalBindingResolver resolver = getAssociationRelationalBindingResolver(

View File

@ -0,0 +1,98 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* JBoss, Home of Professional Open Source
* Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors
* as indicated by the @authors tag. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* 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, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* 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,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package org.hibernate.metamodel.internal.binder;
import java.util.Map;
import javax.persistence.ConstraintMode;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames;
import org.hibernate.metamodel.source.internal.annotations.util.JandexHelper;
import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.DotName;
/**
* @author Brett Meyer
*/
public class ForeignKeyDelegate {
private String explicitForeignKeyName = null;
private String inverseForeignKeyName = null;
private boolean createForeignKeyConstraint = true;
// TODO: do we need inverseCreateForeignKeyConstraint?
public ForeignKeyDelegate() {
}
public ForeignKeyDelegate(Map<DotName, AnnotationInstance> annotations, ClassLoaderService cls) {
final AnnotationInstance joinColumnAnnotation = annotations.get( JPADotNames.JOIN_COLUMN );
final AnnotationInstance joinTable = annotations.get( JPADotNames.JOIN_TABLE );
final AnnotationInstance collectionTable = annotations.get( JPADotNames.COLLECTION_TABLE );
if ( joinColumnAnnotation != null ) {
resolveExplicitName( joinColumnAnnotation, cls );
resolveCreateForeignKeyConstraint( joinColumnAnnotation, cls );
}
if ( joinTable != null ) {
resolveExplicitName( joinTable, cls );
resolveInverseName( joinTable, cls );
resolveCreateForeignKeyConstraint( joinTable, cls );
}
if ( collectionTable != null ) {
resolveExplicitName( collectionTable, cls );
resolveCreateForeignKeyConstraint( collectionTable, cls );
}
}
private void resolveExplicitName(AnnotationInstance owningAnnotation, ClassLoaderService cls) {
AnnotationInstance jpaFkAnnotation = JandexHelper.getValue( owningAnnotation, "foreignKey", AnnotationInstance.class, cls );
explicitForeignKeyName = jpaFkAnnotation != null ? JandexHelper.getValue( jpaFkAnnotation, "name", String.class, cls ) : null;
}
private void resolveInverseName(AnnotationInstance owningAnnotation, ClassLoaderService cls) {
AnnotationInstance jpaFkAnnotation = JandexHelper.getValue( owningAnnotation, "inverseForeignKey", AnnotationInstance.class, cls );
inverseForeignKeyName = jpaFkAnnotation != null ? JandexHelper.getValue( jpaFkAnnotation, "name", String.class, cls ) : null;
}
private void resolveCreateForeignKeyConstraint(AnnotationInstance owningAnnotation, ClassLoaderService cls) {
AnnotationInstance jpaFkAnnotation = JandexHelper.getValue( owningAnnotation, "foreignKey", AnnotationInstance.class, cls );
if ( jpaFkAnnotation != null ) {
ConstraintMode mode = JandexHelper.getEnumValue( jpaFkAnnotation, "value", ConstraintMode.class, cls );
createForeignKeyConstraint = !mode.equals( ConstraintMode.NO_CONSTRAINT );
}
}
public String getExplicitForeignKeyName() {
return explicitForeignKeyName;
}
public String getInverseForeignKeyName() {
return inverseForeignKeyName;
}
public boolean createForeignKeyConstraint() {
return createForeignKeyConstraint;
}
}

View File

@ -155,7 +155,8 @@ public class ForeignKeyHelper {
final List<Column> sourceColumns, final List<Column> sourceColumns,
final TableSpecification targetTable, final TableSpecification targetTable,
final List<Column> targetColumns, final List<Column> targetColumns,
boolean isCascadeDeleteEnabled) { boolean isCascadeDeleteEnabled,
boolean createConstraint) {
final String foreignKeyName = helperContext.relationalIdentifierHelper().normalizeDatabaseIdentifier( final String foreignKeyName = helperContext.relationalIdentifierHelper().normalizeDatabaseIdentifier(
explicitForeignKeyName, new ForeignKeyNamingStrategyHelper( explicitForeignKeyName, new ForeignKeyNamingStrategyHelper(
sourceTable, sourceColumns, targetTable, targetColumns ) ); sourceTable, sourceColumns, targetTable, targetColumns ) );
@ -163,7 +164,7 @@ public class ForeignKeyHelper {
ForeignKey foreignKey = locateAndBindForeignKeyByName( foreignKeyName, sourceTable, sourceColumns, targetTable, targetColumns ); ForeignKey foreignKey = locateAndBindForeignKeyByName( foreignKeyName, sourceTable, sourceColumns, targetTable, targetColumns );
if ( foreignKey == null ) { if ( foreignKey == null ) {
// no foreign key found; create one // no foreign key found; create one
foreignKey = sourceTable.createForeignKey( targetTable, foreignKeyName ); foreignKey = sourceTable.createForeignKey( targetTable, foreignKeyName, createConstraint );
bindForeignKeyColumns( foreignKey, sourceTable, sourceColumns, targetTable, targetColumns ); bindForeignKeyColumns( foreignKey, sourceTable, sourceColumns, targetTable, targetColumns );
} }
if ( isCascadeDeleteEnabled ) { if ( isCascadeDeleteEnabled ) {

View File

@ -439,7 +439,7 @@ class HibernateTypeHelper {
elementSource.getReferencedEntityAttributeName(), elementSource.getReferencedEntityAttributeName(),
false, false,
false, false,
!elementSource.isNotFoundAnException(), elementSource.isIgnoreNotFound(),
false false
); );
final HibernateTypeDescriptor hibernateTypeDescriptor = elementBinding.getHibernateTypeDescriptor(); final HibernateTypeDescriptor hibernateTypeDescriptor = elementBinding.getHibernateTypeDescriptor();

View File

@ -104,7 +104,8 @@ public class MappedByAssociationRelationalBindingResolverImpl implements Associa
sourceColumns, sourceColumns,
targetTable, targetTable,
targetColumns, targetColumns,
attributeSource.isCascadeDeleteEnabled() attributeSource.isCascadeDeleteEnabled(),
attributeSource.createForeignKeyConstraint()
); );
} }

View File

@ -134,7 +134,8 @@ public class StandardAssociationRelationalBindingResolverImpl implements Associa
sourceColumns, sourceColumns,
targetTable, targetTable,
targetColumns, targetColumns,
attributeSource.isCascadeDeleteEnabled() attributeSource.isCascadeDeleteEnabled(),
attributeSource.createForeignKeyConstraint()
); );
} }
@ -392,7 +393,8 @@ public class StandardAssociationRelationalBindingResolverImpl implements Associa
extractColumnsFromRelationalValueBindings( sourceRelationalValueBindings ), extractColumnsFromRelationalValueBindings( sourceRelationalValueBindings ),
targetTable, targetTable,
targetColumns, targetColumns,
foreignKeyContributingSource.isCascadeDeleteEnabled() foreignKeyContributingSource.isCascadeDeleteEnabled(),
foreignKeyContributingSource.createForeignKeyConstraint()
); );
} }

View File

@ -112,8 +112,8 @@ public abstract class AbstractSingularAssociationAttributeSource
} }
@Override @Override
public boolean isNotFoundAnException() { public boolean isIgnoreNotFound() {
return !getPersistentAttribute().getShouldIgnoreNotFound(); return getPersistentAttribute().isIgnoreNotFound();
} }
@Override @Override

View File

@ -51,8 +51,8 @@ public abstract class AbstractPluralAssociationElementSourceImpl
} }
@Override @Override
public boolean isNotFoundAnException() { public boolean isIgnoreNotFound() {
return !pluralAssociationAttribute().getShouldIgnoreNotFound(); return pluralAssociationAttribute().isIgnoreNotFound();
} }
public AttributeSource getAttributeSource() { public AttributeSource getAttributeSource() {

View File

@ -73,8 +73,8 @@ public abstract class AbstractToOneAttributeSourceImpl extends SingularAttribute
} }
@Override @Override
public boolean isNotFoundAnException() { public boolean isIgnoreNotFound() {
return !associationAttribute.getShouldIgnoreNotFound(); return associationAttribute.isIgnoreNotFound();
} }
@Override @Override

View File

@ -81,6 +81,11 @@ public class JoinedSubclassEntitySourceImpl extends SubclassEntitySourceImpl imp
return getEntityClass().getExplicitForeignKeyName(); return getEntityClass().getExplicitForeignKeyName();
} }
@Override
public boolean createForeignKeyConstraint() {
return getEntityClass().createForeignKeyConstraint();
}
@Override @Override
public JoinColumnResolutionDelegate getForeignKeyTargetColumnResolutionDelegate() { public JoinColumnResolutionDelegate getForeignKeyTargetColumnResolutionDelegate() {
return fkColumnResolutionDelegate; return fkColumnResolutionDelegate;

View File

@ -22,7 +22,13 @@ public class ManyToManyMappedByPluralAttributeElementSourceImpl
@Override @Override
public String getExplicitForeignKeyName() { public String getExplicitForeignKeyName() {
throw new UnsupportedOperationException( "Not supported for attributes with mappedBy specified." ); } throw new UnsupportedOperationException( "Not supported for attributes with mappedBy specified." );
}
@Override
public boolean createForeignKeyConstraint() {
throw new UnsupportedOperationException( "Not supported for attributes with mappedBy specified." );
}
@Override @Override
public boolean isCascadeDeleteEnabled() { public boolean isCascadeDeleteEnabled() {

View File

@ -70,6 +70,11 @@ public class ManyToManyPluralAttributeElementSourceImpl
return pluralAssociationAttribute().getInverseForeignKeyName(); return pluralAssociationAttribute().getInverseForeignKeyName();
} }
@Override
public boolean createForeignKeyConstraint() {
return pluralAssociationAttribute().createForeignKeyConstraint();
}
@Override @Override
public boolean isCascadeDeleteEnabled() { public boolean isCascadeDeleteEnabled() {
return false; return false;

View File

@ -73,6 +73,11 @@ public class PluralAttributeKeySourceImpl implements PluralAttributeKeySource {
return attribute.getExplicitForeignKeyName(); return attribute.getExplicitForeignKeyName();
} }
@Override
public boolean createForeignKeyConstraint() {
return attribute.createForeignKeyConstraint();
}
@Override @Override
public JoinColumnResolutionDelegate getForeignKeyTargetColumnResolutionDelegate() { public JoinColumnResolutionDelegate getForeignKeyTargetColumnResolutionDelegate() {
if ( attribute.getMappedByAttributeName() != null ) { if ( attribute.getMappedByAttributeName() != null ) {

View File

@ -125,6 +125,12 @@ public class SecondaryTableSourceImpl implements SecondaryTableSource {
return null; return null;
} }
@Override
public boolean createForeignKeyConstraint() {
// not supported from annotations, unless docs for @ForeignKey are wrong...
return true;
}
@Override @Override
public JoinColumnResolutionDelegate getForeignKeyTargetColumnResolutionDelegate() { public JoinColumnResolutionDelegate getForeignKeyTargetColumnResolutionDelegate() {
return fkColumnResolutionDelegate; return fkColumnResolutionDelegate;

View File

@ -33,6 +33,7 @@ import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.cfg.NamingStrategy; import org.hibernate.cfg.NamingStrategy;
import org.hibernate.cfg.NotYetImplementedException; import org.hibernate.cfg.NotYetImplementedException;
import org.hibernate.metamodel.internal.binder.Binder; import org.hibernate.metamodel.internal.binder.Binder;
import org.hibernate.metamodel.internal.binder.ForeignKeyDelegate;
import org.hibernate.metamodel.source.internal.annotations.attribute.AbstractPersistentAttribute; import org.hibernate.metamodel.source.internal.annotations.attribute.AbstractPersistentAttribute;
import org.hibernate.metamodel.source.internal.annotations.attribute.AssociationOverride; import org.hibernate.metamodel.source.internal.annotations.attribute.AssociationOverride;
import org.hibernate.metamodel.source.internal.annotations.attribute.Column; import org.hibernate.metamodel.source.internal.annotations.attribute.Column;
@ -49,7 +50,6 @@ import org.hibernate.metamodel.spi.binding.AttributeBinding;
import org.hibernate.metamodel.spi.binding.CompositeAttributeBinding; import org.hibernate.metamodel.spi.binding.CompositeAttributeBinding;
import org.hibernate.metamodel.spi.relational.TableSpecification; import org.hibernate.metamodel.spi.relational.TableSpecification;
import org.hibernate.metamodel.spi.relational.Value; import org.hibernate.metamodel.spi.relational.Value;
import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.AnnotationInstance;
/** /**
@ -59,10 +59,9 @@ import org.jboss.jandex.AnnotationInstance;
public class ToOneAttributeSourceImpl extends AbstractToOneAttributeSourceImpl implements ToOneAttributeSource { public class ToOneAttributeSourceImpl extends AbstractToOneAttributeSourceImpl implements ToOneAttributeSource {
private final List<RelationalValueSource> relationalValueSources; private final List<RelationalValueSource> relationalValueSources;
private final String containingTableName; private final String containingTableName;
private final String explicitForeignKeyName;
private final EntityBindingContext bindingContext; private final EntityBindingContext bindingContext;
private final ClassLoaderService cls; private final ClassLoaderService cls;
private final ForeignKeyDelegate foreignKeyDelegate;
public ToOneAttributeSourceImpl( public ToOneAttributeSourceImpl(
SingularAssociationAttribute associationAttribute, SingularAssociationAttribute associationAttribute,
@ -85,7 +84,8 @@ public class ToOneAttributeSourceImpl extends AbstractToOneAttributeSourceImpl i
// Need to initialize logicalJoinTableName before determining nature. // Need to initialize logicalJoinTableName before determining nature.
this.containingTableName = resolveContainingTableName( associationAttribute, relationalValueSources ); this.containingTableName = resolveContainingTableName( associationAttribute, relationalValueSources );
setNature( determineNatureIfPossible( associationAttribute ) ); setNature( determineNatureIfPossible( associationAttribute ) );
this.explicitForeignKeyName = resolveForeignKeyName( associationAttribute ); this.foreignKeyDelegate = new ForeignKeyDelegate(
associationAttribute().getBackingMember().getAnnotations(), cls);
} }
private Nature determineNatureIfPossible( private Nature determineNatureIfPossible(
@ -118,27 +118,6 @@ public class ToOneAttributeSourceImpl extends AbstractToOneAttributeSourceImpl i
} }
} }
private String resolveForeignKeyName(SingularAssociationAttribute attribute) {
final AnnotationInstance joinColumnAnnotation = attribute.getBackingMember()
.getAnnotations()
.get( JPADotNames.JOIN_COLUMN );
if ( joinColumnAnnotation == null ) {
return null;
}
final AnnotationInstance jpaFkAnnotation = JandexHelper.getValue(
joinColumnAnnotation,
"foreignKey",
AnnotationInstance.class,
cls
);
if ( jpaFkAnnotation == null ) {
return null;
}
return JandexHelper.getValue( jpaFkAnnotation, "name", String.class, cls );
}
@Override @Override
public void resolveToOneAttributeSource(AttributeSourceResolutionContext context) { public void resolveToOneAttributeSource(AttributeSourceResolutionContext context) {
if ( getNature() != null ) { if ( getNature() != null ) {
@ -289,7 +268,12 @@ public class ToOneAttributeSourceImpl extends AbstractToOneAttributeSourceImpl i
@Override @Override
public String getExplicitForeignKeyName() { public String getExplicitForeignKeyName() {
return explicitForeignKeyName; return foreignKeyDelegate.getExplicitForeignKeyName();
}
@Override
public boolean createForeignKeyConstraint() {
return foreignKeyDelegate.createForeignKeyConstraint();
} }
@Override @Override

View File

@ -120,6 +120,11 @@ public class ToOneMappedByAttributeSourceImpl
throw new UnsupportedOperationException( "Not supported for a \"mappedBy\" association." ); throw new UnsupportedOperationException( "Not supported for a \"mappedBy\" association." );
} }
@Override
public boolean createForeignKeyConstraint() {
throw new UnsupportedOperationException( "Not supported for a \"mappedBy\" association." );
}
@Override @Override
public boolean isCascadeDeleteEnabled() { public boolean isCascadeDeleteEnabled() {
return false; return false;

View File

@ -37,6 +37,6 @@ public interface AssociationAttribute {
public boolean isOrphanRemoval(); public boolean isOrphanRemoval();
public boolean isOptional(); public boolean isOptional();
public boolean getShouldIgnoreNotFound(); public boolean isIgnoreNotFound();
public boolean isUnWrapProxy(); public boolean isUnWrapProxy();
} }

View File

@ -31,6 +31,7 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.SortedMap; import java.util.SortedMap;
import java.util.SortedSet; import java.util.SortedSet;
import javax.persistence.AccessType; import javax.persistence.AccessType;
import javax.persistence.CascadeType; import javax.persistence.CascadeType;
@ -44,6 +45,7 @@ import org.hibernate.engine.FetchStyle;
import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.mapping.PropertyGeneration; import org.hibernate.mapping.PropertyGeneration;
import org.hibernate.metamodel.internal.binder.ForeignKeyDelegate;
import org.hibernate.metamodel.reflite.spi.ArrayDescriptor; import org.hibernate.metamodel.reflite.spi.ArrayDescriptor;
import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor;
import org.hibernate.metamodel.reflite.spi.MemberDescriptor; import org.hibernate.metamodel.reflite.spi.MemberDescriptor;
@ -64,7 +66,6 @@ import org.hibernate.metamodel.source.spi.PluralAttributeSource;
import org.hibernate.metamodel.spi.binding.Caching; import org.hibernate.metamodel.spi.binding.Caching;
import org.hibernate.metamodel.spi.binding.CustomSQL; import org.hibernate.metamodel.spi.binding.CustomSQL;
import org.hibernate.metamodel.spi.binding.IdentifierGeneratorDefinition; import org.hibernate.metamodel.spi.binding.IdentifierGeneratorDefinition;
import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.AnnotationValue; import org.jboss.jandex.AnnotationValue;
import org.jboss.jandex.DotName; import org.jboss.jandex.DotName;
@ -117,8 +118,7 @@ public class PluralAttribute
// information about the FK // information about the FK
private final OnDeleteAction onDeleteAction; private final OnDeleteAction onDeleteAction;
private String inverseForeignKeyName; private final ForeignKeyDelegate foreignKeyDelegate;
private String explicitForeignKeyName;
private final AttributeTypeResolver collectionTypeResolver; private final AttributeTypeResolver collectionTypeResolver;
@ -131,6 +131,8 @@ public class PluralAttribute
private final AnnotationInstance joinTableAnnotation; private final AnnotationInstance joinTableAnnotation;
private ArrayList<Column> joinColumnValues = new ArrayList<Column>(); private ArrayList<Column> joinColumnValues = new ArrayList<Column>();
private ArrayList<Column> inverseJoinColumnValues = new ArrayList<Column>(); private ArrayList<Column> inverseJoinColumnValues = new ArrayList<Column>();
private final ClassLoaderService classLoaderService;
public PluralAttribute( public PluralAttribute(
ManagedTypeMetadata container, ManagedTypeMetadata container,
@ -153,6 +155,8 @@ public class PluralAttribute
accessType, accessType,
accessorStrategy accessorStrategy
); );
this.classLoaderService = getContext().getServiceRegistry().getService( ClassLoaderService.class );
// just to get the error the test expects // just to get the error the test expects
// todo : I'd really rather see this driven from the class-level, not the attribute-level // todo : I'd really rather see this driven from the class-level, not the attribute-level
@ -204,24 +208,7 @@ public class PluralAttribute
this.whereClause = determineWereClause( backingMember ); this.whereClause = determineWereClause( backingMember );
this.orderBy = determineOrderBy( backingMember ); this.orderBy = determineOrderBy( backingMember );
final AnnotationInstance joinTable = backingMember.getAnnotations().get( JPADotNames.JOIN_TABLE ); this.foreignKeyDelegate = new ForeignKeyDelegate( backingMember.getAnnotations(), classLoaderService );
final AnnotationInstance collectionTable = backingMember.getAnnotations().get( JPADotNames.COLLECTION_TABLE );
if ( joinTable != null ) {
AnnotationInstance jpaFkAnnotation = JandexHelper.extractAnnotationValue( joinTable, "foreignKey" );
this.explicitForeignKeyName = jpaFkAnnotation != null
? jpaFkAnnotation.value( "name" ).asString()
: null;
jpaFkAnnotation = JandexHelper.extractAnnotationValue( joinTable, "inverseForeignKey" );
this.inverseForeignKeyName = jpaFkAnnotation != null
? jpaFkAnnotation.value( "name" ).asString()
: null;
}
if ( collectionTable != null) {
final AnnotationInstance jpaFkAnnotation = JandexHelper.extractAnnotationValue( collectionTable, "foreignKey" );
explicitForeignKeyName = jpaFkAnnotation != null
? jpaFkAnnotation.value( "name" ).asString()
: null;
}
this.caching = determineCachingSettings( backingMember ); this.caching = determineCachingSettings( backingMember );
@ -331,7 +318,7 @@ public class PluralAttribute
collectionId, collectionId,
"columns", "columns",
AnnotationInstance[].class, AnnotationInstance[].class,
getContext().getServiceRegistry().getService( ClassLoaderService.class ) classLoaderService
); );
final List<Column> idColumns = CollectionHelper.arrayList( columnAnnotations.length ); final List<Column> idColumns = CollectionHelper.arrayList( columnAnnotations.length );
for ( AnnotationInstance columnAnnotation : columnAnnotations ) { for ( AnnotationInstance columnAnnotation : columnAnnotations ) {
@ -346,7 +333,7 @@ public class PluralAttribute
type, type,
"parameters", "parameters",
AnnotationInstance[].class, AnnotationInstance[].class,
getContext().getServiceRegistry().getService( ClassLoaderService.class ) classLoaderService
); );
if ( paramAnnotations == null || paramAnnotations.length == 0 ) { if ( paramAnnotations == null || paramAnnotations.length == 0 ) {
return Collections.emptyMap(); return Collections.emptyMap();
@ -658,7 +645,7 @@ public class PluralAttribute
} }
@Override @Override
public boolean getShouldIgnoreNotFound() { public boolean isIgnoreNotFound() {
return ignoreNotFound; return ignoreNotFound;
} }
@ -702,11 +689,14 @@ public class PluralAttribute
} }
public String getInverseForeignKeyName() { public String getInverseForeignKeyName() {
return inverseForeignKeyName; return foreignKeyDelegate.getInverseForeignKeyName();
} }
public String getExplicitForeignKeyName(){ public String getExplicitForeignKeyName(){
return explicitForeignKeyName; return foreignKeyDelegate.getExplicitForeignKeyName();
} }
public boolean createForeignKeyConstraint(){
return foreignKeyDelegate.createForeignKeyConstraint();
}
public Caching getCaching() { public Caching getCaching() {
return caching; return caching;

View File

@ -25,6 +25,7 @@ package org.hibernate.metamodel.source.internal.annotations.attribute;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Set; import java.util.Set;
import javax.persistence.AccessType; import javax.persistence.AccessType;
import javax.persistence.CascadeType; import javax.persistence.CascadeType;
@ -40,7 +41,6 @@ import org.hibernate.metamodel.source.internal.annotations.util.HibernateDotName
import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames; import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames;
import org.hibernate.metamodel.source.spi.AttributePath; import org.hibernate.metamodel.source.spi.AttributePath;
import org.hibernate.metamodel.source.spi.AttributeRole; import org.hibernate.metamodel.source.spi.AttributeRole;
import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.AnnotationInstance;
/** /**
@ -190,7 +190,7 @@ public class SingularAssociationAttribute
} }
@Override @Override
public boolean getShouldIgnoreNotFound() { public boolean isIgnoreNotFound() {
return ignoreNotFound; return ignoreNotFound;
} }

View File

@ -23,13 +23,17 @@
*/ */
package org.hibernate.metamodel.source.internal.annotations.entity; package org.hibernate.metamodel.source.internal.annotations.entity;
import static org.hibernate.metamodel.source.internal.annotations.util.JPADotNames.ENTITY;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.persistence.AccessType; import javax.persistence.AccessType;
import org.hibernate.annotations.OnDeleteAction; import org.hibernate.annotations.OnDeleteAction;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.StringHelper;
import org.hibernate.metamodel.internal.binder.ForeignKeyDelegate;
import org.hibernate.metamodel.reflite.spi.ClassDescriptor; import org.hibernate.metamodel.reflite.spi.ClassDescriptor;
import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor; import org.hibernate.metamodel.reflite.spi.JavaTypeDescriptor;
import org.hibernate.metamodel.source.internal.annotations.AnnotationBindingContext; import org.hibernate.metamodel.source.internal.annotations.AnnotationBindingContext;
@ -39,13 +43,10 @@ import org.hibernate.metamodel.source.internal.annotations.util.HibernateDotName
import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames; import org.hibernate.metamodel.source.internal.annotations.util.JPADotNames;
import org.hibernate.metamodel.source.internal.annotations.util.JandexHelper; import org.hibernate.metamodel.source.internal.annotations.util.JandexHelper;
import org.hibernate.metamodel.spi.binding.CustomSQL; import org.hibernate.metamodel.spi.binding.CustomSQL;
import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.AnnotationValue; import org.jboss.jandex.AnnotationValue;
import org.jboss.jandex.ClassInfo; import org.jboss.jandex.ClassInfo;
import static org.hibernate.metamodel.source.internal.annotations.util.JPADotNames.ENTITY;
/** /**
* Representation of metadata (configured via annotations or orm.xml) attached * Representation of metadata (configured via annotations or orm.xml) attached
* to an Entity. * to an Entity.
@ -68,13 +69,11 @@ public class EntityTypeMetadata extends IdentifiableTypeMetadata {
private final String discriminatorMatchValue; private final String discriminatorMatchValue;
private final boolean isLazy; private final boolean isLazy;
private final String proxy; private final String proxy;
private final ForeignKeyDelegate foreignKeyDelegate;
private final ClassLoaderService classLoaderService;
// todo : ??? // todo : ???
private final String inverseForeignKeyName;
private final String explicitForeignKeyName;
private final OnDeleteAction onDeleteAction; private final OnDeleteAction onDeleteAction;
private final List<PrimaryKeyJoinColumn> joinedSubclassPrimaryKeyJoinColumnSources; private final List<PrimaryKeyJoinColumn> joinedSubclassPrimaryKeyJoinColumnSources;
@ -87,6 +86,8 @@ public class EntityTypeMetadata extends IdentifiableTypeMetadata {
AccessType defaultAccessType, AccessType defaultAccessType,
AnnotationBindingContext bindingContext) { AnnotationBindingContext bindingContext) {
super( javaTypeDescriptor, defaultAccessType, true, bindingContext ); super( javaTypeDescriptor, defaultAccessType, true, bindingContext );
this.classLoaderService = bindingContext.getServiceRegistry().getService( ClassLoaderService.class );
this.explicitEntityName = determineExplicitEntityName(); this.explicitEntityName = determineExplicitEntityName();
this.customLoaderQueryName = determineCustomLoader(); this.customLoaderQueryName = determineCustomLoader();
@ -119,7 +120,7 @@ public class EntityTypeMetadata extends IdentifiableTypeMetadata {
dynamicInsertAnnotation, dynamicInsertAnnotation,
"value", "value",
Boolean.class, Boolean.class,
getLocalBindingContext().getServiceRegistry().getService( ClassLoaderService.class ) classLoaderService
); );
} }
else { else {
@ -136,7 +137,7 @@ public class EntityTypeMetadata extends IdentifiableTypeMetadata {
dynamicUpdateAnnotation, dynamicUpdateAnnotation,
"value", "value",
Boolean.class, Boolean.class,
getLocalBindingContext().getServiceRegistry().getService( ClassLoaderService.class ) classLoaderService
); );
} }
else { else {
@ -154,7 +155,7 @@ public class EntityTypeMetadata extends IdentifiableTypeMetadata {
selectBeforeUpdateAnnotation, selectBeforeUpdateAnnotation,
"value", "value",
Boolean.class, Boolean.class,
getLocalBindingContext().getServiceRegistry().getService( ClassLoaderService.class ) classLoaderService
); );
} }
else { else {
@ -205,14 +206,14 @@ public class EntityTypeMetadata extends IdentifiableTypeMetadata {
else { else {
this.discriminatorMatchValue = null; this.discriminatorMatchValue = null;
} }
// TODO: bind JPA @ForeignKey?
foreignKeyDelegate = new ForeignKeyDelegate();
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// todo : which (if any) of these to keep? // todo : which (if any) of these to keep?
this.joinedSubclassPrimaryKeyJoinColumnSources = determinePrimaryKeyJoinColumns(); this.joinedSubclassPrimaryKeyJoinColumnSources = determinePrimaryKeyJoinColumns();
// TODO: bind JPA @ForeignKey?
this.explicitForeignKeyName = null;
this.inverseForeignKeyName = null;
this.onDeleteAction = determineOnDeleteAction(); this.onDeleteAction = determineOnDeleteAction();
} }
@ -226,7 +227,8 @@ public class EntityTypeMetadata extends IdentifiableTypeMetadata {
AccessType defaultAccessType, AccessType defaultAccessType,
AnnotationBindingContext bindingContext) { AnnotationBindingContext bindingContext) {
super( javaTypeDescriptor, superType, defaultAccessType, bindingContext ); super( javaTypeDescriptor, superType, defaultAccessType, bindingContext );
this.classLoaderService = bindingContext.getServiceRegistry().getService( ClassLoaderService.class );
this.explicitEntityName = determineExplicitEntityName(); this.explicitEntityName = determineExplicitEntityName();
this.customLoaderQueryName = determineCustomLoader(); this.customLoaderQueryName = determineCustomLoader();
@ -259,7 +261,7 @@ public class EntityTypeMetadata extends IdentifiableTypeMetadata {
dynamicInsertAnnotation, dynamicInsertAnnotation,
"value", "value",
Boolean.class, Boolean.class,
getLocalBindingContext().getServiceRegistry().getService( ClassLoaderService.class ) classLoaderService
); );
} }
else { else {
@ -276,7 +278,7 @@ public class EntityTypeMetadata extends IdentifiableTypeMetadata {
dynamicUpdateAnnotation, dynamicUpdateAnnotation,
"value", "value",
Boolean.class, Boolean.class,
getLocalBindingContext().getServiceRegistry().getService( ClassLoaderService.class ) classLoaderService
); );
} }
else { else {
@ -294,7 +296,7 @@ public class EntityTypeMetadata extends IdentifiableTypeMetadata {
selectBeforeUpdateAnnotation, selectBeforeUpdateAnnotation,
"value", "value",
Boolean.class, Boolean.class,
getLocalBindingContext().getServiceRegistry().getService( ClassLoaderService.class ) classLoaderService
); );
} }
else { else {
@ -345,14 +347,14 @@ public class EntityTypeMetadata extends IdentifiableTypeMetadata {
else { else {
this.discriminatorMatchValue = null; this.discriminatorMatchValue = null;
} }
// TODO: bind JPA @ForeignKey?
foreignKeyDelegate = new ForeignKeyDelegate();
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// todo : which (if any) of these to keep? // todo : which (if any) of these to keep?
this.joinedSubclassPrimaryKeyJoinColumnSources = determinePrimaryKeyJoinColumns(); this.joinedSubclassPrimaryKeyJoinColumnSources = determinePrimaryKeyJoinColumns();
// TODO: bind JPA @ForeignKey?
this.explicitForeignKeyName = null;
this.inverseForeignKeyName = null;
this.onDeleteAction = determineOnDeleteAction(); this.onDeleteAction = determineOnDeleteAction();
} }
@ -422,7 +424,7 @@ public class EntityTypeMetadata extends IdentifiableTypeMetadata {
onDeleteAnnotation, onDeleteAnnotation,
"action", "action",
OnDeleteAction.class, OnDeleteAction.class,
getLocalBindingContext().getServiceRegistry().getService( ClassLoaderService.class ) classLoaderService
); );
} }
return null; return null;
@ -499,11 +501,14 @@ public class EntityTypeMetadata extends IdentifiableTypeMetadata {
public String getInverseForeignKeyName() { public String getInverseForeignKeyName() {
return inverseForeignKeyName; return foreignKeyDelegate.getInverseForeignKeyName();
} }
public String getExplicitForeignKeyName(){ public String getExplicitForeignKeyName(){
return explicitForeignKeyName; return foreignKeyDelegate.getExplicitForeignKeyName();
} }
public boolean createForeignKeyConstraint(){
return foreignKeyDelegate.createForeignKeyConstraint();
}
public OnDeleteAction getOnDeleteAction() { public OnDeleteAction getOnDeleteAction() {
return onDeleteAction; return onDeleteAction;

View File

@ -88,8 +88,8 @@ public abstract class AbstractToOneAttributeSourceImpl extends AbstractHbmSource
} }
@Override @Override
public boolean isNotFoundAnException() { public boolean isIgnoreNotFound() {
return true; return false;
} }
@Override @Override
@ -262,5 +262,11 @@ public abstract class AbstractToOneAttributeSourceImpl extends AbstractHbmSource
return context.resolveTableForAttribute( propertyRef ); return context.resolveTableForAttribute( propertyRef );
} }
} }
@Override
public boolean createForeignKeyConstraint() {
// TODO: Can HBM do something like JPA's @ForeignKey(NO_CONSTRAINT)?
return true;
}
} }

View File

@ -93,6 +93,12 @@ public class JoinedSubclassEntitySourceImpl extends SubclassEntitySourceImpl imp
public String getExplicitForeignKeyName() { public String getExplicitForeignKeyName() {
return key.getForeignKey(); return key.getForeignKey();
} }
@Override
public boolean createForeignKeyConstraint() {
// TODO: Can HBM do something like JPA's @ForeignKey(NO_CONSTRAINT)?
return true;
}
@Override @Override
public JoinColumnResolutionDelegate getForeignKeyTargetColumnResolutionDelegate() { public JoinColumnResolutionDelegate getForeignKeyTargetColumnResolutionDelegate() {
@ -116,7 +122,6 @@ public class JoinedSubclassEntitySourceImpl extends SubclassEntitySourceImpl imp
}; };
} }
@Override @Override
public List<ColumnSource> getPrimaryKeyColumnSources() { public List<ColumnSource> getPrimaryKeyColumnSources() {
return primaryKeyJoinColumnSources; return primaryKeyJoinColumnSources;

View File

@ -140,8 +140,8 @@ public class ManyToManyPluralAttributeElementSourceImpl
} }
@Override @Override
public boolean isNotFoundAnException() { public boolean isIgnoreNotFound() {
return manyToManyElement.getNotFound() == null || !"ignore".equals( manyToManyElement.getNotFound().value() ); return manyToManyElement.getNotFound() != null && "ignore".equalsIgnoreCase( manyToManyElement.getNotFound().value() );
} }
@Override @Override
@ -257,5 +257,11 @@ public class ManyToManyPluralAttributeElementSourceImpl
return context.resolveTableForAttribute( manyToManyElement.getPropertyRef() ); return context.resolveTableForAttribute( manyToManyElement.getPropertyRef() );
} }
} }
@Override
public boolean createForeignKeyConstraint() {
// TODO: Can HBM do something like JPA's @ForeignKey(NO_CONSTRAINT)?
return true;
}
} }

View File

@ -105,8 +105,8 @@ class ManyToOneAttributeSourceImpl extends AbstractToOneAttributeSourceImpl {
} }
@Override @Override
public boolean isNotFoundAnException() { public boolean isIgnoreNotFound() {
return manyToOneElement.getNotFound() == null || !"ignore".equals( manyToOneElement.getNotFound().value() ); return manyToOneElement.getNotFound() != null && "ignore".equalsIgnoreCase( manyToOneElement.getNotFound().value() );
} }
@Override @Override

View File

@ -63,9 +63,8 @@ public class OneToManyPluralAttributeElementSourceImpl
} }
@Override @Override
public boolean isNotFoundAnException() { public boolean isIgnoreNotFound() {
return oneToManyElement.getNotFound() == null return oneToManyElement.getNotFound() != null && "ignore".equalsIgnoreCase( oneToManyElement.getNotFound().value() );
|| ! "ignore".equals( oneToManyElement.getNotFound().value() );
} }
@Override @Override

View File

@ -85,6 +85,12 @@ public class PluralAttributeKeySourceImpl
public String getExplicitForeignKeyName() { public String getExplicitForeignKeyName() {
return keyElement.getForeignKey(); return keyElement.getForeignKey();
} }
@Override
public boolean createForeignKeyConstraint() {
// TODO: Can HBM do something like JPA's @ForeignKey(NO_CONSTRAINT)?
return true;
}
@Override @Override
public JoinColumnResolutionDelegate getForeignKeyTargetColumnResolutionDelegate() { public JoinColumnResolutionDelegate getForeignKeyTargetColumnResolutionDelegate() {

View File

@ -140,6 +140,12 @@ class SecondaryTableSourceImpl extends AbstractHbmSourceNode implements Secondar
public String getExplicitForeignKeyName() { public String getExplicitForeignKeyName() {
return joinElement.getKey().getForeignKey(); return joinElement.getKey().getForeignKey();
} }
@Override
public boolean createForeignKeyConstraint() {
// TODO: Can HBM do something like JPA's @ForeignKey(NO_CONSTRAINT)?
return true;
}
@Override @Override
public JoinColumnResolutionDelegate getForeignKeyTargetColumnResolutionDelegate() { public JoinColumnResolutionDelegate getForeignKeyTargetColumnResolutionDelegate() {

View File

@ -39,7 +39,7 @@ public interface AssociationSource extends CascadeStyleSource {
*/ */
public String getReferencedEntityName(); public String getReferencedEntityName();
public boolean isNotFoundAnException(); public boolean isIgnoreNotFound();
/** /**
* Returns the attribute source that is owned by this {@link AssociationSource}, * Returns the attribute source that is owned by this {@link AssociationSource},

View File

@ -41,6 +41,13 @@ public interface ForeignKeyContributingSource {
* @return The user supplied foreign key name. * @return The user supplied foreign key name.
*/ */
public String getExplicitForeignKeyName(); public String getExplicitForeignKeyName();
/**
* Primarily exists to support JPA's @ForeignKey(NO_CONSTRAINT).
*
* @return True if the FK constraint should be created, false if not.
*/
public boolean createForeignKeyConstraint();
/** /**
* Is "cascade delete" enabled for the foreign key? In other words, if a record in the parent (referenced) * Is "cascade delete" enabled for the foreign key? In other words, if a record in the parent (referenced)

View File

@ -34,7 +34,7 @@ public interface ManyToManyPluralAttributeElementSource
public String getReferencedEntityAttributeName(); public String getReferencedEntityAttributeName();
public boolean isNotFoundAnException(); public boolean isIgnoreNotFound();
public String getExplicitForeignKeyName(); public String getExplicitForeignKeyName();

View File

@ -29,5 +29,5 @@ package org.hibernate.metamodel.source.spi;
public interface OneToManyPluralAttributeElementSource extends PluralAttributeElementSource, AssociationSource { public interface OneToManyPluralAttributeElementSource extends PluralAttributeElementSource, AssociationSource {
public String getReferencedEntityName(); public String getReferencedEntityName();
public boolean isNotFoundAnException(); public boolean isIgnoreNotFound();
} }

View File

@ -181,7 +181,7 @@ public abstract class AbstractAttributeBindingContainer implements AttributeBind
String propertyAccessorName, String propertyAccessorName,
boolean includedInOptimisticLocking, boolean includedInOptimisticLocking,
boolean lazy, boolean lazy,
boolean isNotFoundAnException, boolean isIgnoreNotFound,
SingularAttributeBinding.NaturalIdMutability naturalIdMutability, SingularAttributeBinding.NaturalIdMutability naturalIdMutability,
MetaAttributeContext metaAttributeContext, MetaAttributeContext metaAttributeContext,
EntityBinding referencedEntityBinding, EntityBinding referencedEntityBinding,
@ -192,7 +192,7 @@ public abstract class AbstractAttributeBindingContainer implements AttributeBind
propertyAccessorName, propertyAccessorName,
includedInOptimisticLocking, includedInOptimisticLocking,
lazy, lazy,
isNotFoundAnException, isIgnoreNotFound,
naturalIdMutability, naturalIdMutability,
metaAttributeContext, metaAttributeContext,
referencedEntityBinding, referencedEntityBinding,

View File

@ -186,7 +186,7 @@ public abstract class AbstractCompositeAttributeBindingContainer
String propertyAccessorName, String propertyAccessorName,
boolean includedInOptimisticLocking, boolean includedInOptimisticLocking,
boolean lazy, boolean lazy,
boolean isNotFoundAnException, boolean isIgnoreNotFound,
SingularAttributeBinding.NaturalIdMutability naturalIdMutability, SingularAttributeBinding.NaturalIdMutability naturalIdMutability,
MetaAttributeContext metaAttributeContext, MetaAttributeContext metaAttributeContext,
EntityBinding referencedEntityBinding, EntityBinding referencedEntityBinding,
@ -199,7 +199,7 @@ public abstract class AbstractCompositeAttributeBindingContainer
propertyAccessorName, propertyAccessorName,
includedInOptimisticLocking, includedInOptimisticLocking,
lazy, lazy,
isNotFoundAnException, isIgnoreNotFound,
naturalIdMutability, naturalIdMutability,
metaAttributeContext, metaAttributeContext,
referencedEntityBinding, referencedEntityBinding,

View File

@ -48,7 +48,7 @@ public abstract class AbstractSingularAssociationAttributeBinding extends Abstra
private FetchTiming fetchTiming; private FetchTiming fetchTiming;
private FetchStyle fetchStyle; private FetchStyle fetchStyle;
private boolean isUnWrapProxy; private boolean isUnWrapProxy;
private final boolean isNotFoundAnException; private final boolean isIgnoreNotFound;
public AbstractSingularAssociationAttributeBinding( public AbstractSingularAssociationAttributeBinding(
AttributeBindingContainer container, AttributeBindingContainer container,
@ -56,7 +56,7 @@ public abstract class AbstractSingularAssociationAttributeBinding extends Abstra
String propertyAccessorName, String propertyAccessorName,
boolean includedInOptimisticLocking, boolean includedInOptimisticLocking,
boolean isLazy, boolean isLazy,
boolean isNotFoundAnException, boolean isIgnoreNotFound,
NaturalIdMutability naturalIdMutability, NaturalIdMutability naturalIdMutability,
MetaAttributeContext metaAttributeContext, MetaAttributeContext metaAttributeContext,
EntityBinding referencedEntityBinding, EntityBinding referencedEntityBinding,
@ -78,12 +78,12 @@ public abstract class AbstractSingularAssociationAttributeBinding extends Abstra
} }
this.referencedEntityBinding = referencedEntityBinding; this.referencedEntityBinding = referencedEntityBinding;
this.referencedAttributeBinding = referencedAttributeBinding; this.referencedAttributeBinding = referencedAttributeBinding;
this.isNotFoundAnException = isNotFoundAnException; this.isIgnoreNotFound = isIgnoreNotFound;
} }
@Override @Override
public boolean isNotFoundAnException() { public boolean isIgnoreNotFound() {
return isNotFoundAnException; return isIgnoreNotFound;
} }
@Override @Override

View File

@ -207,7 +207,7 @@ public interface AttributeBindingContainer {
String propertyAccessorName, String propertyAccessorName,
boolean includedInOptimisticLocking, boolean includedInOptimisticLocking,
boolean lazy, boolean lazy,
boolean isNotFoundAnException, boolean isIgnoreNotFound,
SingularAttributeBinding.NaturalIdMutability naturalIdMutability, SingularAttributeBinding.NaturalIdMutability naturalIdMutability,
MetaAttributeContext metaAttributeContext, MetaAttributeContext metaAttributeContext,
EntityBinding referencedEntityBinding, EntityBinding referencedEntityBinding,

View File

@ -438,7 +438,7 @@ public class CompositeAttributeBinding
String propertyAccessorName, String propertyAccessorName,
boolean includedInOptimisticLocking, boolean includedInOptimisticLocking,
boolean lazy, boolean lazy,
boolean isNotFoundAnException, boolean isIgnoreNotFound,
NaturalIdMutability naturalIdMutability, NaturalIdMutability naturalIdMutability,
MetaAttributeContext metaAttributeContext, MetaAttributeContext metaAttributeContext,
EntityBinding referencedEntityBinding, EntityBinding referencedEntityBinding,
@ -448,7 +448,7 @@ public class CompositeAttributeBinding
propertyAccessorName, propertyAccessorName,
includedInOptimisticLocking, includedInOptimisticLocking,
lazy, lazy,
isNotFoundAnException, isIgnoreNotFound,
naturalIdMutability, naturalIdMutability,
metaAttributeContext, metaAttributeContext,
referencedEntityBinding, referencedEntityBinding,

View File

@ -41,7 +41,7 @@ public class ManyToOneAttributeBinding
String propertyAccessorName, String propertyAccessorName,
boolean includedInOptimisticLocking, boolean includedInOptimisticLocking,
boolean lazy, boolean lazy,
boolean isNotFoundAnException, boolean isIgnoreNotFound,
NaturalIdMutability naturalIdMutability, NaturalIdMutability naturalIdMutability,
MetaAttributeContext metaAttributeContext, MetaAttributeContext metaAttributeContext,
EntityBinding referencedEntityBinding, EntityBinding referencedEntityBinding,
@ -52,7 +52,7 @@ public class ManyToOneAttributeBinding
propertyAccessorName, propertyAccessorName,
includedInOptimisticLocking, includedInOptimisticLocking,
lazy, lazy,
isNotFoundAnException, isIgnoreNotFound,
naturalIdMutability, naturalIdMutability,
metaAttributeContext, metaAttributeContext,
referencedEntityBinding, referencedEntityBinding,

View File

@ -52,7 +52,7 @@ public class OneToOneAttributeBinding
propertyAccessorName, propertyAccessorName,
includedInOptimisticLocking, includedInOptimisticLocking,
lazy, lazy,
true, //always true false,
naturalIdMutability, naturalIdMutability,
metaAttributeContext, metaAttributeContext,
referencedEntityBinding, referencedEntityBinding,

View File

@ -45,7 +45,7 @@ public interface SingularAssociationAttributeBinding extends SingularAttributeBi
public SingularAttributeBinding getReferencedAttributeBinding(); public SingularAttributeBinding getReferencedAttributeBinding();
public boolean isNotFoundAnException(); public boolean isIgnoreNotFound();
public TableSpecification getTable(); public TableSpecification getTable();

View File

@ -166,8 +166,8 @@ public abstract class AbstractTableSpecification implements TableSpecification {
} }
@Override @Override
public ForeignKey createForeignKey(TableSpecification targetTable, String name) { public ForeignKey createForeignKey(TableSpecification targetTable, String name, boolean createConstraint) {
ForeignKey fk = new ForeignKey( this, targetTable, name ); ForeignKey fk = new ForeignKey( this, targetTable, name, createConstraint );
foreignKeys.add( fk ); foreignKeys.add( fk );
return fk; return fk;
} }

View File

@ -100,7 +100,7 @@ public class DenormalizedTable extends Table {
} }
private void copyFK(ForeignKey fk, String fkName) { private void copyFK(ForeignKey fk, String fkName) {
ForeignKey copiedFK = createForeignKey( fk.getTargetTable(), fkName ); ForeignKey copiedFK = createForeignKey( fk.getTargetTable(), fkName, fk.createConstraint() );
copiedFK.setDeleteRule( fk.getDeleteRule() ); copiedFK.setDeleteRule( fk.getDeleteRule() );
copiedFK.setUpdateRule( fk.getUpdateRule() ); copiedFK.setUpdateRule( fk.getUpdateRule() );
Iterable<ForeignKey.ColumnMapping> columnMappings = fk.getColumnMappings(); Iterable<ForeignKey.ColumnMapping> columnMappings = fk.getColumnMappings();

View File

@ -52,17 +52,21 @@ public class ForeignKey extends AbstractConstraint {
private ReferentialAction deleteRule = ReferentialAction.NO_ACTION; private ReferentialAction deleteRule = ReferentialAction.NO_ACTION;
private ReferentialAction updateRule = ReferentialAction.NO_ACTION; private ReferentialAction updateRule = ReferentialAction.NO_ACTION;
private boolean createConstraint;
protected ForeignKey(TableSpecification sourceTable, TableSpecification targetTable, String name) { protected ForeignKey(TableSpecification sourceTable, TableSpecification targetTable, String name,
boolean createConstraint) {
super( sourceTable, name ); super( sourceTable, name );
if ( targetTable == null ) { if ( targetTable == null ) {
throw new IllegalArgumentException( "targetTable must be non-null." ); throw new IllegalArgumentException( "targetTable must be non-null." );
} }
this.targetTable = targetTable; this.targetTable = targetTable;
this.createConstraint = createConstraint;
} }
protected ForeignKey(TableSpecification sourceTable, TableSpecification targetTable) { protected ForeignKey(TableSpecification sourceTable, TableSpecification targetTable) {
this( sourceTable, targetTable, null ); this( sourceTable, targetTable, null, true );
} }
public TableSpecification getSourceTable() { public TableSpecification getSourceTable() {
@ -216,4 +220,8 @@ public class ForeignKey extends AbstractConstraint {
public String getExportIdentifier() { public String getExportIdentifier() {
return getSourceTable().getLoggableValueQualifier() + ".FK-" + getName(); return getSourceTable().getLoggableValueQualifier() + ".FK-" + getName();
} }
public boolean createConstraint() {
return createConstraint;
}
} }

View File

@ -129,10 +129,11 @@ public interface TableSpecification extends ValueContainer, Loggable {
* *
* @param targetTable The table that is the target of the foreign key * @param targetTable The table that is the target of the foreign key
* @param name The (optional) name of the foreign key * @param name The (optional) name of the foreign key
* @param createConstraint
* *
* @return The foreign key reference. * @return The foreign key reference.
*/ */
public ForeignKey createForeignKey(TableSpecification targetTable, String name); public ForeignKey createForeignKey(TableSpecification targetTable, String name, boolean createConstraint);
public Iterable<Index> getIndexes(); public Iterable<Index> getIndexes();

View File

@ -44,6 +44,10 @@ public class StandardForeignKeyExporter implements Exporter<ForeignKey> {
if ( ! dialect.hasAlterTable() ) { if ( ! dialect.hasAlterTable() ) {
return NO_COMMANDS; return NO_COMMANDS;
} }
if ( ! foreignKey.createConstraint() ) {
return NO_COMMANDS;
}
final int numberOfColumns = foreignKey.getColumnSpan(); final int numberOfColumns = foreignKey.getColumnSpan();
final String[] columnNames = new String[ numberOfColumns ]; final String[] columnNames = new String[ numberOfColumns ];
@ -95,6 +99,10 @@ public class StandardForeignKeyExporter implements Exporter<ForeignKey> {
if ( ! dialect.hasAlterTable() ) { if ( ! dialect.hasAlterTable() ) {
return NO_COMMANDS; return NO_COMMANDS;
} }
if ( ! foreignKey.createConstraint() ) {
return NO_COMMANDS;
}
final String sourceTableName = jdbcEnvironment.getQualifiedObjectNameSupport().formatName( final String sourceTableName = jdbcEnvironment.getQualifiedObjectNameSupport().formatName(
( (Table) foreignKey.getSourceTable() ).getTableName() ( (Table) foreignKey.getSourceTable() ).getTableName()

View File

@ -110,7 +110,7 @@ public class TableManipulationTests extends BaseUnitTestCase {
Column pageBookId = page.locateOrCreateColumn( "BOOK_ID" ); Column pageBookId = page.locateOrCreateColumn( "BOOK_ID" );
pageId.setJdbcDataType( INTEGER ); pageId.setJdbcDataType( INTEGER );
pageId.setSize( Size.precision( 18, 0 ) ); pageId.setSize( Size.precision( 18, 0 ) );
ForeignKey pageBookFk = page.createForeignKey( book, "PAGE_BOOK_FK" ); ForeignKey pageBookFk = page.createForeignKey( book, "PAGE_BOOK_FK", true );
pageBookFk.addColumn( pageBookId ); pageBookFk.addColumn( pageBookId );
assertEquals( page, pageBookFk.getSourceTable() ); assertEquals( page, pageBookFk.getSourceTable() );

View File

@ -1,6 +1,8 @@
//$Id$ //$Id$
package org.hibernate.test.annotations.notfound; package org.hibernate.test.annotations.notfound;
import javax.persistence.ConstraintMode;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.ForeignKey;
import javax.persistence.GeneratedValue; import javax.persistence.GeneratedValue;
import javax.persistence.Id; import javax.persistence.Id;
import javax.persistence.JoinColumn; import javax.persistence.JoinColumn;
@ -37,7 +39,8 @@ public class Coin {
} }
@ManyToOne @ManyToOne
@JoinColumn(name = "currency", referencedColumnName = "name") @JoinColumn(name = "currency", referencedColumnName = "name",
foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
@NotFound(action = NotFoundAction.IGNORE) @NotFound(action = NotFoundAction.IGNORE)
public Currency getCurrency() { public Currency getCurrency() {
return currency; return currency;

View File

@ -23,19 +23,16 @@
*/ */
package org.hibernate.test.annotations.notfound; package org.hibernate.test.annotations.notfound;
import org.junit.Test; import static org.junit.Assert.assertNull;
import org.hibernate.Session; import org.hibernate.Session;
import org.hibernate.Transaction; import org.hibernate.Transaction;
import org.hibernate.testing.FailureExpectedWithNewMetamodel;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Test;
import static org.junit.Assert.assertNull;
/** /**
* @author Emmanuel Bernard * @author Emmanuel Bernard
*/ */
@FailureExpectedWithNewMetamodel(jiraKey = "HHH-7916")
public class NotFoundTest extends BaseCoreFunctionalTestCase { public class NotFoundTest extends BaseCoreFunctionalTestCase {
@Test @Test
public void testManyToOne() throws Exception { public void testManyToOne() throws Exception {

View File

@ -22,9 +22,13 @@
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*/ */
package org.hibernate.test.collection.original; package org.hibernate.test.collection.original;
import java.sql.SQLException; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import org.junit.Test; import java.sql.SQLException;
import org.hibernate.Hibernate; import org.hibernate.Hibernate;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
@ -33,17 +37,11 @@ import org.hibernate.Transaction;
import org.hibernate.testing.FailureExpectedWithNewMetamodel; import org.hibernate.testing.FailureExpectedWithNewMetamodel;
import org.hibernate.testing.TestForIssue; import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
/** /**
* @author Gavin King * @author Gavin King
*/ */
@FailureExpectedWithNewMetamodel(jiraKey = "HHH-7916")
public class CollectionTest extends BaseCoreFunctionalTestCase { public class CollectionTest extends BaseCoreFunctionalTestCase {
@Override @Override
public String[] getMappings() { public String[] getMappings() {
@ -51,6 +49,7 @@ public class CollectionTest extends BaseCoreFunctionalTestCase {
} }
@Test @Test
@FailureExpectedWithNewMetamodel
public void testExtraLazy() throws HibernateException, SQLException { public void testExtraLazy() throws HibernateException, SQLException {
Session s = openSession(); Session s = openSession();
Transaction t = s.beginTransaction(); Transaction t = s.beginTransaction();

View File

@ -23,24 +23,21 @@
*/ */
package org.hibernate.test.unconstrained; package org.hibernate.test.unconstrained;
import org.junit.Test; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import org.hibernate.FetchMode; import org.hibernate.FetchMode;
import org.hibernate.Hibernate; import org.hibernate.Hibernate;
import org.hibernate.Session; import org.hibernate.Session;
import org.hibernate.Transaction; import org.hibernate.Transaction;
import org.hibernate.criterion.Restrictions; import org.hibernate.criterion.Restrictions;
import org.hibernate.testing.FailureExpectedWithNewMetamodel;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Test;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
/** /**
* @author Gavin King * @author Gavin King
*/ */
@FailureExpectedWithNewMetamodel(jiraKey = "HHH-7916")
public class UnconstrainedTest extends BaseCoreFunctionalTestCase { public class UnconstrainedTest extends BaseCoreFunctionalTestCase {
@Override @Override
public String[] getMappings() { public String[] getMappings() {