HHH-7052 : Bind PluralAttributeKeyBinding

This commit is contained in:
Gail Badner 2012-02-21 12:48:11 -08:00
parent 8afab9f255
commit f839cd22ef
3 changed files with 163 additions and 65 deletions

View File

@ -52,6 +52,7 @@
import org.hibernate.metamodel.spi.binding.CompositeAttributeBinding;
import org.hibernate.metamodel.spi.binding.EntityBinding;
import org.hibernate.metamodel.spi.binding.EntityDiscriminator;
import org.hibernate.metamodel.spi.binding.HibernateTypeDescriptor;
import org.hibernate.metamodel.spi.binding.IdGenerator;
import org.hibernate.metamodel.spi.binding.InheritanceType;
import org.hibernate.metamodel.spi.binding.ManyToOneAttributeBinding;
@ -95,6 +96,7 @@
import org.hibernate.metamodel.spi.source.MetadataImplementor;
import org.hibernate.metamodel.spi.source.Orderable;
import org.hibernate.metamodel.spi.source.PluralAttributeElementSource;
import org.hibernate.metamodel.spi.source.PluralAttributeKeySource;
import org.hibernate.metamodel.spi.source.PluralAttributeNature;
import org.hibernate.metamodel.spi.source.PluralAttributeSource;
import org.hibernate.metamodel.spi.source.PrimaryKeyJoinColumnSource;
@ -261,7 +263,9 @@ private EntityBinding doCreateEntityBinding(EntitySource entitySource, EntityBin
final EntityBinding entityBinding = createBasicEntityBinding( entitySource, superEntityBinding );
bindSecondaryTables( entitySource, entityBinding );
Deque<TableSpecification> tableStack = new ArrayDeque<TableSpecification>( );
tableStack.add( entityBinding.getPrimaryTable() );
bindAttributes( entitySource, entityBinding, tableStack );
bindTableUniqueConstraints( entitySource, entityBinding );
@ -614,7 +618,10 @@ else if ( attributeSource.isVirtualAttribute() ) {
final List<RelationalValueBinding> relationalValueBindings = createSimpleRelationalValues(
attributeSource,
attributeBindingContainer,
attribute
attribute,
attributeBindingContainer
.seekEntityBinding()
.getPrimaryTable()
);
final String propertyAccessorName = Helper.getPropertyAccessorName(
attributeSource.getPropertyAccessorName(),
@ -794,7 +801,10 @@ else if ( attributeSource.isVirtualAttribute() ) {
final List<RelationalValueBinding> relationalValueBindings = createSimpleRelationalValues(
attributeSource,
attributeBindingContainer,
attribute
attribute,
attributeBindingContainer
.seekEntityBinding()
.getPrimaryTable()
);
final String propertyAccessorName = Helper.getPropertyAccessorName(
attributeSource.getPropertyAccessorName(),
@ -955,6 +965,8 @@ private void doBasicPluralAttributeBinding(PluralAttributeSource source, Abstrac
binding.setCustomSqlDelete( source.getCustomSqlDelete() );
binding.setCustomSqlDeleteAll( source.getCustomSqlDeleteAll() );
binding.setWhere( source.getWhere() );
// doBasicAttributeBinding( source, binding );
}
@ -1020,8 +1032,6 @@ public String inferredTableName() {
if ( StringHelper.isNotEmpty( attributeSource.getCollectionTableCheck() ) ) {
pluralAttributeBinding.getCollectionTable().addCheckConstraint( attributeSource.getCollectionTableCheck() );
}
pluralAttributeBinding.setWhere( attributeSource.getWhere() );
}
private void bindCollectionKey(
@ -1029,56 +1039,91 @@ private void bindCollectionKey(
AbstractPluralAttributeBinding pluralAttributeBinding,
Deque<TableSpecification> tableStack) {
// TableSpecification targetTable = tableStack.peekLast();
pluralAttributeBinding.getPluralAttributeKeyBinding().prepareForeignKey(
attributeSource.getKeySource().getExplicitForeignKeyName(),
//tableStack.peekLast().getLogicalName()
null // todo : handle secondary table names
final PluralAttributeKeySource keySource = attributeSource.getKeySource();
String foreignKeyName = (
StringHelper.isNotEmpty( keySource.getExplicitForeignKeyName() ) ?
quoteIdentifier( keySource.getExplicitForeignKeyName() ) :
null // TODO: is null FK name allowd (is there a default?)
);
pluralAttributeBinding.getPluralAttributeKeyBinding().getForeignKey().setDeleteRule(
attributeSource.getKeySource().getOnDeleteAction()
pluralAttributeBinding.getPluralAttributeKeyBinding().prepareForeignKey(
foreignKeyName,
tableStack.peekLast()
);
final ForeignKey foreignKey = pluralAttributeBinding.getPluralAttributeKeyBinding().getForeignKey();
Iterator<RelationalValueBinding> targetValueBindings = null;
if ( attributeSource.getKeySource().getReferencedEntityAttributeName() != null ) {
final EntityBinding ownerEntityBinding = pluralAttributeBinding.getContainer().seekEntityBinding();
final AttributeBinding referencedAttributeBinding = ownerEntityBinding.locateAttributeBinding(
attributeSource.getKeySource().getReferencedEntityAttributeName()
foreignKey.setDeleteRule( keySource.getOnDeleteAction() );
if ( keySource.getReferencedEntityAttributeName() == null ) {
bindCollectionKeyTargetingPrimaryKey( attributeSource.getKeySource(), pluralAttributeBinding );
}
else {
bindCollectionKeyTargetingPropertyRef( attributeSource.getKeySource(), pluralAttributeBinding );
}
HibernateTypeDescriptor targetTypeDescriptor = pluralAttributeBinding.getHibernateTypeDescriptor();
}
private void bindCollectionKeyTargetingPrimaryKey(
PluralAttributeKeySource keySource,
AbstractPluralAttributeBinding pluralAttributeBinding) {
for ( RelationalValueSource valueSource : keySource.getValueSources() ) {
if ( ColumnSource.class.isInstance( valueSource ) ) {
final Column column = makeColumn(
ColumnSource.class.cast( valueSource ),
COLL_KEY_COLUMN_BINDING_DEFAULTS,
pluralAttributeBinding.getCollectionTable(),
pluralAttributeBinding.getAttribute().getName(),
true
);
pluralAttributeBinding.getPluralAttributeKeyBinding().getForeignKey().addColumn( column );
}
else {
// TODO: deal with formulas???
}
}
}
private void bindCollectionKeyTargetingPropertyRef(
PluralAttributeKeySource keySource,
AbstractPluralAttributeBinding pluralAttributeBinding) {
final EntityBinding ownerEntityBinding = pluralAttributeBinding.getContainer().seekEntityBinding();
final AttributeBinding referencedAttributeBinding = ownerEntityBinding.locateAttributeBinding(
keySource.getReferencedEntityAttributeName()
);
final ForeignKey foreignKey = pluralAttributeBinding.getPluralAttributeKeyBinding().getForeignKey();
if ( ! referencedAttributeBinding.getAttribute().isSingular() ) {
throw new MappingException(
String.format(
"Collection (%s) property-ref is a plural attribute (%s); must be singular.",
pluralAttributeBinding.getAttribute().getRole(),
referencedAttributeBinding
),
currentBindingContext.getOrigin()
);
if ( ! referencedAttributeBinding.getAttribute().isSingular() ) {
}
Iterator<RelationalValueBinding> targetValueBindings =
( (SingularAttributeBinding) referencedAttributeBinding ).getRelationalValueBindings().iterator();
for ( RelationalValueSource valueSource : keySource.getValueSources() ) {
if ( ! targetValueBindings.hasNext() ) {
throw new MappingException(
String.format(
"Collection (%s) property-ref is a plural attribute (%s); must be singular.",
pluralAttributeBinding.getAttribute().getRole(),
referencedAttributeBinding
"More collection key source columns than target columns for collection: %s",
pluralAttributeBinding.getAttribute().getRole()
),
currentBindingContext.getOrigin()
);
}
// targetValueBindings = ( (SingularAttributeBinding) referencedAttributeBinding ).getRelationalValueBindings().iterator();
}
for ( RelationalValueSource valueSource : attributeSource.getKeySource().getValueSources() ) {
Value targetValue = null;
if ( targetValueBindings != null ) {
if ( ! targetValueBindings.hasNext() ) {
throw new MappingException(
String.format(
"More collection key source columns than target columns for collection: %s",
pluralAttributeBinding.getAttribute().getRole()
),
currentBindingContext.getOrigin()
);
}
targetValue = targetValueBindings.next().getValue();
}
Value targetValue = targetValueBindings.next().getValue();
if ( ColumnSource.class.isInstance( valueSource ) ) {
final ColumnSource columnSource = ColumnSource.class.cast( valueSource );
final Column column = makeColumn(
columnSource,
COLL_KEY_COLUMN_BINDING_DEFAULTS,
final Column column = makeColumn(
columnSource,
COLL_KEY_COLUMN_BINDING_DEFAULTS,
pluralAttributeBinding.getCollectionTable(),
pluralAttributeBinding.getAttribute().getName(),
pluralAttributeBinding.getAttribute().getName(),
true
);
if ( targetValue != null && ! Column.class.isInstance( targetValue ) ) {
@ -1108,7 +1153,6 @@ private void bindCollectionKey(
);
}
}
private static final ColumnBindingDefaults COLL_KEY_COLUMN_BINDING_DEFAULTS = new ColumnBindingDefaults() {
@Override
public boolean areValuesIncludedInInsertByDefault() {
@ -1166,7 +1210,8 @@ private void bindBasicPluralElementRelationalValues(
createSimpleRelationalValues(
relationalValueSourceContainer,
elementBinding.getPluralAttributeBinding().getContainer(),
elementBinding.getPluralAttributeBinding().getAttribute()
elementBinding.getPluralAttributeBinding().getAttribute(),
elementBinding.getPluralAttributeBinding().getCollectionTable()
)
);
}
@ -1440,23 +1485,26 @@ private void bindTableUniqueConstraints(EntitySource entitySource, EntityBinding
private List<RelationalValueBinding> createSimpleRelationalValues(
RelationalValueSourceContainer relationalValueSourceContainer,
AttributeBindingContainer attributeBindingContainer,
Attribute attribute) {
Attribute attribute,
TableSpecification defaultTable) {
List<RelationalValueBinding> valueBindings = new ArrayList<RelationalValueBinding>();
if ( !relationalValueSourceContainer.relationalValueSources().isEmpty() ) {
for ( RelationalValueSource valueSource : relationalValueSourceContainer.relationalValueSources() ) {
final TableSpecification table = attributeBindingContainer
.seekEntityBinding()
.locateTable( valueSource.getContainingTableName() );
TableSpecification resolvedTable = defaultTable;
if ( valueSource.getContainingTableName() != null ) {
resolvedTable = attributeBindingContainer
.seekEntityBinding()
.locateTable( valueSource.getContainingTableName() );
}
if ( ColumnSource.class.isInstance( valueSource ) ) {
final ColumnSource columnSource = ColumnSource.class.cast( valueSource );
final Column column =
makeColumn(
columnSource,
relationalValueSourceContainer,
table,
relationalValueSourceContainer,
resolvedTable,
attribute.getName(),
true
);
@ -1474,7 +1522,7 @@ private List<RelationalValueBinding> createSimpleRelationalValues(
else {
valueBindings.add(
new RelationalValueBinding(
makeDerivedValue( ( (DerivedValueSource) valueSource ), table )
makeDerivedValue( ( (DerivedValueSource) valueSource ), resolvedTable )
)
);
}
@ -1485,18 +1533,15 @@ private List<RelationalValueBinding> createSimpleRelationalValues(
.getNamingStrategy()
.propertyToColumnName( attribute.getName() );
name = quoteIdentifier( name );
Column column = attributeBindingContainer
.seekEntityBinding()
.getPrimaryTable()
.locateOrCreateColumn( name );
Column column = defaultTable.locateOrCreateColumn( name );
column.setNullable( relationalValueSourceContainer.areValuesNullableByDefault() );
valueBindings.add( new RelationalValueBinding( column ) );
}
return valueBindings;
}
private String quoteIdentifier(String identifier) {
return currentBindingContext.isGloballyQuotedIdentifiers() ? StringHelper.quote( identifier ) : identifier;
private String quoteIdentifier(String string) {
return currentBindingContext.isGloballyQuotedIdentifiers() ? StringHelper.quote( string ) : string;
}
private Value makeRelationalValue(

View File

@ -40,8 +40,7 @@ public class PluralAttributeKeyBinding {
// may need notion of "boolean updatable"
// this knowledge can be implicitly resolved based on the typing information on the referenced owner attribute
private HibernateTypeDescriptor hibernateTypeDescriptor;
// in which case add this...
private final HibernateTypeDescriptor hibernateTypeDescriptor = new HibernateTypeDescriptor();
// SingularAttributeBinding referencedAttributeBinding;
// todo : this would be nice to have but we do not always know it, especially in HBM case.
@ -89,7 +88,7 @@ public HibernateTypeDescriptor getHibernateTypeDescriptor() {
return hibernateTypeDescriptor;
}
public void prepareForeignKey(String foreignKeyName, String targetTableName) {
public void prepareForeignKey(String foreignKeyName, TableSpecification targetTable) {
if ( foreignKey != null ) {
throw new AssertionFailure( "Foreign key already initialized" );
}
@ -105,10 +104,6 @@ public void prepareForeignKey(String foreignKeyName, String targetTableName) {
}
}
final TableSpecification targetTable = pluralAttributeBinding.getContainer()
.seekEntityBinding()
.locateTable( targetTableName );
foreignKey = collectionTable.createForeignKey( targetTable, foreignKeyName );
}

View File

@ -23,6 +23,8 @@
*/
package org.hibernate.metamodel.spi.binding;
import java.util.Iterator;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@ -30,13 +32,19 @@
import org.hibernate.metamodel.MetadataSourceProcessingOrder;
import org.hibernate.metamodel.MetadataSources;
import org.hibernate.metamodel.internal.MetadataImpl;
import org.hibernate.metamodel.spi.relational.Column;
import org.hibernate.metamodel.spi.relational.ForeignKey;
import org.hibernate.metamodel.spi.relational.Identifier;
import org.hibernate.service.ServiceRegistryBuilder;
import org.hibernate.service.internal.StandardServiceRegistryImpl;
import org.hibernate.testing.junit4.BaseUnitTestCase;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
/**
* @author Steve Ebersole
@ -77,14 +85,64 @@ private void doTest(MetadataSourceProcessingOrder processingOrder) {
assertNotNull( bagBinding );
assertSame( bagBinding, entityBinding.locateAttributeBinding( "theBag" ) );
assertNotNull( bagBinding.getCollectionTable() );
assertEquals( Identifier.toIdentifier( "`EntityWithBasicCollections_theBag`" ), bagBinding.getCollectionTable().getLogicalName() );
PluralAttributeKeyBinding bagKeyBinding = bagBinding.getPluralAttributeKeyBinding();
assertSame( bagBinding, bagKeyBinding.getPluralAttributeBinding() );
ForeignKey fkBag = bagKeyBinding.getForeignKey();
assertNotNull( fkBag );
assertSame( bagBinding.getCollectionTable(), fkBag.getSourceTable() );
assertEquals( 1, fkBag.getColumnSpan() );
Iterator<Column> fkBagColumnIterator = fkBag.getColumns().iterator();
Iterator<Column> fkBagSourceColumnIterator = fkBag.getSourceColumns().iterator();
assertNotNull( fkBagColumnIterator );
assertNotNull( fkBagSourceColumnIterator );
assertTrue( fkBagColumnIterator.hasNext() );
assertTrue( fkBagSourceColumnIterator.hasNext() );
assertEquals( Identifier.toIdentifier( "`owner_id`" ), fkBagColumnIterator.next().getColumnName() );
assertEquals( Identifier.toIdentifier( "`owner_id`" ), fkBagSourceColumnIterator.next().getColumnName() );
assertFalse( fkBagColumnIterator.hasNext() );
assertFalse( fkBagSourceColumnIterator.hasNext() );
assertSame( entityBinding.getPrimaryTable(), fkBag.getTargetTable() );
assertEquals( entityBinding.getPrimaryTable().getPrimaryKey().getColumns(), fkBag.getTargetColumns() );
assertSame( ForeignKey.ReferentialAction.NO_ACTION, fkBag.getDeleteRule() );
assertSame( ForeignKey.ReferentialAction.NO_ACTION, fkBag.getUpdateRule() );
// FK is null because no default FK name is generated until HHH-7092 is fixed
assertNull( fkBag.getName() );
assertFalse( bagKeyBinding.isInverse() );
assertEquals( PluralAttributeElementNature.BASIC, bagBinding.getPluralAttributeElementBinding().getPluralAttributeElementNature() );
assertEquals( String.class.getName(), ( (BasicPluralAttributeElementBinding) bagBinding.getPluralAttributeElementBinding() ).getHibernateTypeDescriptor().getJavaTypeName() );
assertEquals( String.class.getName(), bagBinding.getPluralAttributeElementBinding().getHibernateTypeDescriptor().getJavaTypeName() );
PluralAttributeBinding setBinding = metadata.getCollection( EntityWithBasicCollections.class.getName() + ".theSet" );
assertNotNull( setBinding );
assertSame( setBinding, entityBinding.locateAttributeBinding( "theSet" ) );
assertNotNull( setBinding.getCollectionTable() );
assertEquals( Identifier.toIdentifier( "`EntityWithBasicCollections_theSet`" ), setBinding.getCollectionTable().getLogicalName() );
PluralAttributeKeyBinding setKeyBinding = setBinding.getPluralAttributeKeyBinding();
assertSame( setBinding, setKeyBinding.getPluralAttributeBinding() );
ForeignKey fkSet = setKeyBinding.getForeignKey();
assertNotNull( fkSet );
assertSame( setBinding.getCollectionTable(), fkSet.getSourceTable() );
assertEquals( 1, fkSet.getColumnSpan() );
Iterator<Column> fkSetColumnIterator = fkSet.getColumns().iterator();
Iterator<Column> fkSetSourceColumnIterator = fkSet.getSourceColumns().iterator();
assertNotNull( fkSetColumnIterator );
assertNotNull( fkSetSourceColumnIterator );
assertTrue( fkSetColumnIterator.hasNext() );
assertTrue( fkSetSourceColumnIterator.hasNext() );
assertEquals( Identifier.toIdentifier( "`pid`" ), fkSetColumnIterator.next().getColumnName() );
assertEquals( Identifier.toIdentifier( "`pid`" ), fkSetSourceColumnIterator.next().getColumnName() );
assertFalse( fkSetColumnIterator.hasNext() );
assertFalse( fkSetSourceColumnIterator.hasNext() );
assertSame( entityBinding.getPrimaryTable(), fkSet.getTargetTable() );
assertEquals( entityBinding.getPrimaryTable().getPrimaryKey().getColumns(), fkSet.getTargetColumns() );
assertSame( ForeignKey.ReferentialAction.NO_ACTION, fkSet.getDeleteRule() );
assertSame( ForeignKey.ReferentialAction.NO_ACTION, fkSet.getUpdateRule() );
// FK is null because no default FK name is generated until HHH-7092 is fixed
assertNull( fkSet.getName() );
assertFalse( setKeyBinding.isInverse() );
assertEquals( PluralAttributeElementNature.BASIC, setBinding.getPluralAttributeElementBinding().getPluralAttributeElementNature() );
assertEquals( String.class.getName(), ( (BasicPluralAttributeElementBinding) setBinding.getPluralAttributeElementBinding() ).getHibernateTypeDescriptor().getJavaTypeName() );
assertEquals( String.class.getName(), setBinding.getPluralAttributeElementBinding().getHibernateTypeDescriptor().getJavaTypeName() );
}
}