diff --git a/changelog.txt b/changelog.txt index 85dcaf14cd..d06803c81c 100644 --- a/changelog.txt +++ b/changelog.txt @@ -172,7 +172,7 @@ https://hibernate.onjira.com/browse/HHH/fixforversion/11550 * [HHH-6749] - FooBarTest.testLimit() fails on MS SQL Server due to dialect interpretation of max row * [HHH-6750] - ASTParserLoadingTest.testAggregation() fails on MS SQL Server performing avg, presumably due to forcing result to match column type * [HHH-6751] - Test failure due to inconsistent scale returned for BigDecimal properties - * [HHH-6755] - SQL Server/Sybase dialects don't have type mapping for binary datatype + * [HHH-6755] - SQL Server/Sybase dialects don't have type mapping for binary jdbcDataType * [HHH-6756] - Test failures due to Oracle LONG limitatations * [HHH-6757] - QueryCacheTest.testCaseInsensitiveComparison() fails for case-insensitive DBs * [HHH-6758] - Test failure due to Oracle restrictions on Blob comparison and missing equals() and hashcode() diff --git a/documentation/src/main/docbook/devguide/en-US/Data_Categorizations.xml b/documentation/src/main/docbook/devguide/en-US/Data_Categorizations.xml index c14ee41415..bfad2e40a1 100644 --- a/documentation/src/main/docbook/devguide/en-US/Data_Categorizations.xml +++ b/documentation/src/main/docbook/devguide/en-US/Data_Categorizations.xml @@ -15,7 +15,7 @@ Usage of the word <wordasword>type</wordasword> - A Hibernate type is neither a Java type nor a SQL datatype. It provides information about + A Hibernate type is neither a Java type nor a SQL jdbcDataType. It provides information about both of these. diff --git a/documentation/src/main/docbook/devguide/en-US/Database_Access.xml b/documentation/src/main/docbook/devguide/en-US/Database_Access.xml index 9b54a8d8bd..4aaa971167 100644 --- a/documentation/src/main/docbook/devguide/en-US/Database_Access.xml +++ b/documentation/src/main/docbook/devguide/en-US/Database_Access.xml @@ -552,7 +552,7 @@ Set the <option>sql-type</option> attribure. Use the attribute to override the default mapping of a Hibernate type to SQL - datatype. + jdbcDataType. diff --git a/documentation/src/main/docbook/manual/en-US/content/toolset_guide.xml b/documentation/src/main/docbook/manual/en-US/content/toolset_guide.xml index b8d28b2469..d524be604e 100644 --- a/documentation/src/main/docbook/manual/en-US/content/toolset_guide.xml +++ b/documentation/src/main/docbook/manual/en-US/content/toolset_guide.xml @@ -176,7 +176,7 @@ The sql-type attribute allows the user to override the default - mapping of a Hibernate type to SQL datatype. + mapping of a Hibernate type to SQL jdbcDataType. diff --git a/documentation/src/main/docbook/manual/en-US/content/type.xml b/documentation/src/main/docbook/manual/en-US/content/type.xml index fd05981fbe..c18f2b561a 100644 --- a/documentation/src/main/docbook/manual/en-US/content/type.xml +++ b/documentation/src/main/docbook/manual/en-US/content/type.xml @@ -39,7 +39,7 @@ - A Hibernate type is neither a Java type nor a SQL datatype; it provides a information about both. + A Hibernate type is neither a Java type nor a SQL jdbcDataType; it provides a information about both. When you encounter the term type in regards to Hibernate be aware that usage might diff --git a/documentation/src/main/docbook/quickstart/en-US/content/tutorial_native.xml b/documentation/src/main/docbook/quickstart/en-US/content/tutorial_native.xml index b0714781d6..ca9bee6901 100644 --- a/documentation/src/main/docbook/quickstart/en-US/content/tutorial_native.xml +++ b/documentation/src/main/docbook/quickstart/en-US/content/tutorial_native.xml @@ -202,8 +202,8 @@ In some cases this automatic detection might not chose the default you expect or need, as seen with the date property. Hibernate cannot know if the property, which is of type - java.util.Date, should map to a SQL DATE, - TIME, or TIMESTAMP datatype. + java.util.Date, should map to a SQL DATE, + TIME, or TIMESTAMP jdbcDataType. Full date and time information is preserved by mapping the property to a timestamp converter, which identifies an instance of the class org.hibernate.type.TimestampType. @@ -334,4 +334,4 @@ session.close();]]> - \ No newline at end of file + diff --git a/hibernate-core/src/main/java/org/hibernate/cache/internal/CacheDataDescriptionImpl.java b/hibernate-core/src/main/java/org/hibernate/cache/internal/CacheDataDescriptionImpl.java index 9371d587bc..8b0e6d57b5 100644 --- a/hibernate-core/src/main/java/org/hibernate/cache/internal/CacheDataDescriptionImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/cache/internal/CacheDataDescriptionImpl.java @@ -95,6 +95,7 @@ public class CacheDataDescriptionImpl implements CacheDataDescription { if ( model.isVersioned() ) { versionComparator = ( ( VersionType ) model.getHierarchyDetails() + .getEntityVersion() .getVersioningAttributeBinding() .getHibernateTypeDescriptor() .getResolvedTypeMapping() diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/Cache71Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/Cache71Dialect.java index c9d0f45790..371388e21f 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/Cache71Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/Cache71Dialect.java @@ -226,7 +226,7 @@ public class Cache71Dialect extends Dialect { protected final void commonRegistration() { // Note: For object <-> SQL datatype mappings see: - // Configuration Manager | Advanced | SQL | System DDL Datatype Mappings + // Configuration Manager | Advanced | SQL | System DDL JdbcDataType Mappings // // TBD registerColumnType(Types.BINARY, "binary($1)"); // changed 08-11-2005, jsl diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/Binder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/Binder.java index bafdbef53a..f7a102d5ca 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/Binder.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/Binder.java @@ -28,12 +28,14 @@ import java.beans.PropertyDescriptor; import java.lang.reflect.ParameterizedType; import java.util.ArrayDeque; import java.util.ArrayList; +import java.util.Comparator; import java.util.Deque; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Properties; + import org.hibernate.AssertionFailure; import org.hibernate.EntityMode; import org.hibernate.TruthValue; @@ -48,6 +50,7 @@ import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.beans.BeanInfoHelper; import org.hibernate.metamodel.internal.source.hbm.Helper; import org.hibernate.metamodel.spi.binding.AbstractPluralAttributeBinding; +import org.hibernate.metamodel.spi.binding.AbstractPluralAttributeElementBinding; import org.hibernate.metamodel.spi.binding.AttributeBinding; import org.hibernate.metamodel.spi.binding.AttributeBindingContainer; import org.hibernate.metamodel.spi.binding.BasicAttributeBinding; @@ -61,7 +64,7 @@ import org.hibernate.metamodel.spi.binding.InheritanceType; import org.hibernate.metamodel.spi.binding.ManyToOneAttributeBinding; import org.hibernate.metamodel.spi.binding.MetaAttribute; import org.hibernate.metamodel.spi.binding.PluralAttributeElementNature; -import org.hibernate.metamodel.spi.binding.SimpleValueBinding; +import org.hibernate.metamodel.spi.binding.RelationalValueBinding; import org.hibernate.metamodel.spi.binding.SingularAssociationAttributeBinding; import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; import org.hibernate.metamodel.spi.binding.TypeDefinition; @@ -70,16 +73,15 @@ import org.hibernate.metamodel.spi.domain.Component; import org.hibernate.metamodel.spi.domain.Entity; import org.hibernate.metamodel.spi.domain.PluralAttribute; import org.hibernate.metamodel.spi.domain.SingularAttribute; +import org.hibernate.metamodel.spi.relational.AbstractValue; import org.hibernate.metamodel.spi.relational.Column; -import org.hibernate.metamodel.spi.relational.Datatype; import org.hibernate.metamodel.spi.relational.DerivedValue; import org.hibernate.metamodel.spi.relational.ForeignKey; import org.hibernate.metamodel.spi.relational.Identifier; +import org.hibernate.metamodel.spi.relational.JdbcDataType; import org.hibernate.metamodel.spi.relational.Schema; -import org.hibernate.metamodel.spi.relational.SimpleValue; import org.hibernate.metamodel.spi.relational.Table; import org.hibernate.metamodel.spi.relational.TableSpecification; -import org.hibernate.metamodel.spi.relational.Tuple; import org.hibernate.metamodel.spi.relational.UniqueKey; import org.hibernate.metamodel.spi.relational.Value; import org.hibernate.metamodel.spi.source.AttributeSource; @@ -115,11 +117,13 @@ import org.hibernate.metamodel.spi.source.SubclassEntitySource; import org.hibernate.metamodel.spi.source.TableSource; import org.hibernate.metamodel.spi.source.ToOneAttributeSource; import org.hibernate.metamodel.spi.source.UniqueConstraintSource; +import org.hibernate.metamodel.spi.source.VersionAttributeSource; import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.service.config.spi.ConfigurationService; import org.hibernate.tuple.entity.EntityTuplizer; import org.hibernate.type.Type; +import org.hibernate.type.TypeFactory; /** * The common binder shared between annotations and {@code hbm.xml} processing. @@ -409,8 +413,9 @@ public class Binder { private void bindSimpleIdentifier( SimpleIdentifierSource identifierSource, EntityBinding entityBinding) { - final BasicAttributeBinding idAttributeBinding = doBasicSingularAttributeBindingCreation( - identifierSource.getIdentifierAttributeSource(), entityBinding + final BasicAttributeBinding idAttributeBinding = bindBasicAttribute( + identifierSource.getIdentifierAttributeSource(), + entityBinding ); entityBinding.getHierarchyDetails().getEntityIdentifier().setValueBinding( idAttributeBinding ); @@ -424,34 +429,35 @@ public class Binder { .getEntityIdentifier() .setIdGenerator( generator ); - final Value relationalValue = idAttributeBinding.getValue(); + final List relationalValueBindings = idAttributeBinding.getRelationalValueBindings(); - if ( SimpleValue.class.isInstance( relationalValue ) ) { - if ( !Column.class.isInstance( relationalValue ) ) { + if ( relationalValueBindings.size() == 1 ) { + final Value value = relationalValueBindings.get( 0 ).getValue(); + if ( !Column.class.isInstance( value ) ) { // this should never ever happen.. throw new AssertionFailure( "Simple-id was not a column." ); } - entityBinding.getPrimaryTable().getPrimaryKey().addColumn( Column.class.cast( relationalValue ) ); + entityBinding.getPrimaryTable().getPrimaryKey().addColumn( Column.class.cast( value ) ); } else { - for ( SimpleValue subValue : ( (Tuple) relationalValue ).values() ) { - if ( Column.class.isInstance( subValue ) ) { - entityBinding.getPrimaryTable().getPrimaryKey().addColumn( Column.class.cast( subValue ) ); + for ( RelationalValueBinding valueBinding : relationalValueBindings ) { + final Value value = valueBinding.getValue(); + if ( Column.class.isInstance( value ) ) { + entityBinding.getPrimaryTable().getPrimaryKey().addColumn( Column.class.cast( value ) ); } } } } private void bindVersion(EntityBinding entityBinding, RootEntitySource entitySource) { - final SingularAttributeSource versioningAttributeSource = entitySource.getVersioningAttributeSource(); + final VersionAttributeSource versioningAttributeSource = entitySource.getVersioningAttributeSource(); if ( versioningAttributeSource == null ) { return; } - BasicAttributeBinding attributeBinding = doBasicSingularAttributeBindingCreation( - versioningAttributeSource, entityBinding - ); - entityBinding.getHierarchyDetails().setVersioningAttributeBinding( attributeBinding ); + BasicAttributeBinding attributeBinding = bindBasicAttribute( versioningAttributeSource, entityBinding ); + entityBinding.getHierarchyDetails().getEntityVersion().setVersioningAttributeBinding( attributeBinding ); + entityBinding.getHierarchyDetails().getEntityVersion().setUnsavedValue( versioningAttributeSource.getUnsavedValue() ); } public static final ColumnBindingDefaults DISCRIMINATOR_COLUMN_BINDING_DEFAULTS = new ColumnBindingDefaults() { @@ -477,13 +483,16 @@ public class Binder { return; } - EntityDiscriminator discriminator = new EntityDiscriminator(); - SimpleValue relationalValue = makeSimpleValue( + Value relationalValue = makeRelationalValue( entityBinding, discriminatorSource.getDiscriminatorRelationalValueSource(), DISCRIMINATOR_COLUMN_BINDING_DEFAULTS ); - discriminator.setBoundValue( relationalValue ); + EntityDiscriminator discriminator = new EntityDiscriminator( + relationalValue, + discriminatorSource.isInserted(), + discriminatorSource.isForced() + ); discriminator.getExplicitHibernateTypeDescriptor().setExplicitTypeName( discriminatorSource.getExplicitHibernateTypeName() != null @@ -491,12 +500,13 @@ public class Binder { : "string" ); - discriminator.setInserted( discriminatorSource.isInserted() ); - discriminator.setForced( discriminatorSource.isForced() ); - entityBinding.getHierarchyDetails().setEntityDiscriminator( discriminator ); entityBinding.setDiscriminatorMatchValue( entitySource.getDiscriminatorMatchValue() ); - resolveTypeInformation(discriminator.getExplicitHibernateTypeDescriptor(), relationalValue); + + Type resolvedType = determineHibernateTypeFromDescriptor( discriminator.getExplicitHibernateTypeDescriptor() ); + if ( resolvedType != null ) { + pushHibernateTypeInformationDownIfNeeded( resolvedType, relationalValue ); + } } private void bindDiscriminatorValue(SubclassEntitySource entitySource, EntityBinding entityBinding) { @@ -517,13 +527,7 @@ public class Binder { for ( AttributeSource attributeSource : attributeSourceContainer.attributeSources() ) { if ( attributeSource.isSingular() ) { - final SingularAttributeSource singularAttributeSource = (SingularAttributeSource) attributeSource; - if ( singularAttributeSource.getNature() == SingularAttributeNature.COMPONENT ) { - bindComponent( (ComponentAttributeSource) singularAttributeSource, attributeBindingContainer, tableStack ); - } - else { - doBasicSingularAttributeBindingCreation( singularAttributeSource, attributeBindingContainer ); - } + bindSingularAttribute( (SingularAttributeSource) attributeSource, attributeBindingContainer, tableStack ); } else { bindPersistentCollection( (PluralAttributeSource) attributeSource, attributeBindingContainer, tableStack ); @@ -531,14 +535,253 @@ public class Binder { } } - private void bindComponent( + private void bindSingularAttribute( + SingularAttributeSource attributeSource, + AttributeBindingContainer attributeBindingContainer, + Deque tableStack) { + if ( attributeSource.getNature() == SingularAttributeNature.BASIC ) { + bindBasicAttribute( attributeSource, attributeBindingContainer ); + } + else if ( attributeSource.getNature() == SingularAttributeNature.COMPONENT ) { + bindComponentAttribute( (ComponentAttributeSource) attributeSource, attributeBindingContainer, tableStack ); + } + else if ( attributeSource.getNature() == SingularAttributeNature.ANY ) { + throw new NotYetImplementedException( "Handling of ANY mappings not yet implemented" ); + } + else { + bindToOneAttribute( (ToOneAttributeSource) attributeSource, attributeBindingContainer ); + } + } + + private SingularAttributeBinding bindToOneAttribute( + ToOneAttributeSource attributeSource, + AttributeBindingContainer attributeBindingContainer) { + final SingularAttribute existingAttribute = attributeBindingContainer.getAttributeContainer() + .locateSingularAttribute( attributeSource.getName() ); + final SingularAttribute attribute; + if ( existingAttribute != null ) { + attribute = existingAttribute; + } + else if ( attributeSource.isVirtualAttribute() ) { + attribute = attributeBindingContainer.getAttributeContainer().createVirtualSingularAttribute( + attributeSource.getName() + ); + } + else { + attribute = attributeBindingContainer.getAttributeContainer() + .createSingularAttribute( attributeSource.getName() ); + } + + final List relationalValueBindings = createSimpleRelationalValues( + attributeSource, + attributeBindingContainer, + attribute + ); + final String propertyAccessorName = Helper.getPropertyAccessorName( + attributeSource.getPropertyAccessorName(), + false, + currentBindingContext.getMappingDefaults().getPropertyAccessorName() + ); + final MetaAttributeContext metaAttributeContext = buildMetaAttributeContext( + attributeSource.metaAttributes(), + attributeBindingContainer.getMetaAttributeContext() + ); + + final SingularAssociationAttributeBinding attributeBinding; + if ( attributeSource.getNature() == SingularAttributeNature.ONE_TO_ONE ) { + throw new NotYetImplementedException( "Handling of one-to-one mappings not yet implemented" ); + } + else if ( attributeSource.getNature() == SingularAttributeNature.MANY_TO_ONE ) { + attributeBinding = attributeBindingContainer.makeManyToOneAttributeBinding( + attribute, + propertyAccessorName, + attributeSource.isIncludedInOptimisticLocking(), + attributeSource.isLazy(), + metaAttributeContext, + attributeSource.getReferencedEntityName(), + attributeSource.getReferencedEntityAttributeName(), + relationalValueBindings + ); + final String referencedEntityName = attributeSource.getReferencedEntityName(); + EntityBinding referencedEntityBinding = getEntityBinding( referencedEntityName ); + if ( referencedEntityBinding == null ) { + EntitySource source = sourcesByName.get( referencedEntityName ); + createEntityBinding( source, referencedEntityBinding ); + } + AttributeBinding referencedAttrBinding = attributeSource.getReferencedEntityAttributeName() != null + ? referencedEntityBinding.locateAttributeBinding( attributeSource.getReferencedEntityAttributeName() ) + : referencedEntityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding(); + attributeBinding.resolveReference( referencedAttrBinding ); + referencedAttrBinding.addEntityReferencingAttributeBinding( attributeBinding ); + + resolveTypeInformation( attributeSource.getTypeInformation(), attributeBinding ); + resolveToOneInformation( + attributeSource, + (ManyToOneAttributeBinding) attributeBinding + ); + } + else { + throw new NotYetImplementedException(); + } + + return attributeBinding; + } + + private ForeignKey resolveForeignKey( + ToOneAttributeSource attributeSource, + AttributeBindingContainer attributeBindingContainer) { + final String explicitForeignKeyName = attributeSource.getForeignKeyName(); + + // foreign key columns should all come from the same table... + final TableSpecification sourceTable = attributeBindingContainer.seekEntityBinding().locateTable( + attributeSource.relationalValueSources().get( 0 ).getContainingTableName() + ); + + ForeignKey foreignKey = sourceTable.locateForeignKey( explicitForeignKeyName ); + if ( foreignKey != null ) { + // todo : maybe validate columns? + return foreignKey; + } + + final List sourceColumns = new ArrayList(); + for ( RelationalValueSource relationalValueSource : attributeSource.relationalValueSources() ) { + sourceColumns.add( locateOrMakeValue( sourceTable, relationalValueSource, attributeSource ) ); + } + + // todo : pretty sure this is one of the places where the "chasing" approach implemented by john breaks down + // even assuming the best case that the target entity and its attributes are fully resolved, + // what about the self-referential (Employee<->Manager) case? + final EntityBinding referencedEntityBinding = metadata.getEntityBinding( attributeSource.getReferencedEntityName() ); + if ( referencedEntityBinding == null ) { + throw new MappingException( + "Unable to locate reference entity binding for association : " + attributeSource, + currentBindingContext.getOrigin() + ); + } + + // todo : try to look up the reverse FK based on the tables/columns... + + final TableSpecification targetTable; + final List targetColumns = new ArrayList(); + if ( StringHelper.isEmpty( attributeSource.getReferencedEntityAttributeName() ) ) { + List valueBindings = referencedEntityBinding.getHierarchyDetails() + .getEntityIdentifier() + .getValueBinding() + .getRelationalValueBindings(); + targetTable = valueBindings.get( 0 ).getValue().getTable(); + for ( RelationalValueBinding binding : valueBindings ) { + targetColumns.add( binding.getValue() ); + } + } + else { + // todo : this is very different for JPA which uses @JoinColumn and hbm which uses property-ref + // we need a scheme that works for both. + // the processing here uses hbm/property-ref approach + // + // the referenced property could conceivably be either a component or a basic + final SingularAttributeBinding referencedAttributeBinding = (SingularAttributeBinding) referencedEntityBinding.locateAttributeBinding( + attributeSource.getReferencedEntityAttributeName() + ); + if ( ComponentAttributeBinding.class.isInstance( referencedAttributeBinding ) ) { + collectValues( (ComponentAttributeBinding) referencedAttributeBinding, targetColumns ); + } + else { + for ( RelationalValueBinding valueBinding :( (BasicAttributeBinding) referencedAttributeBinding ).getRelationalValueBindings() ) { + targetColumns.add( valueBinding.getValue() ); + } + } + targetTable = targetColumns.get( 0 ).getTable(); + } + + if ( sourceColumns.size() != targetColumns.size() ) { + throw new MappingException( + "Encountered mismatch in number of columns in foreign key", + currentBindingContext.getOrigin() + ); + } + foreignKey = sourceTable.createForeignKey( targetTable, explicitForeignKeyName ); + for ( int i = 0; i < sourceColumns.size(); i++ ) { + // todo : handle special case of formulas in key mappings... + foreignKey.addColumnMapping( (Column) sourceColumns.get(i), (Column) targetColumns.get(i) ); + } + + return foreignKey; + } + + private void collectValues(ComponentAttributeBinding componentAttributeBinding, List targetColumns) { + for ( AttributeBinding attributeBinding : componentAttributeBinding.attributeBindings() ) { + if ( BasicAttributeBinding.class.isInstance( attributeBinding ) ) { + for ( RelationalValueBinding valueBinding :( (BasicAttributeBinding) attributeBinding ).getRelationalValueBindings() ) { + targetColumns.add( valueBinding.getValue() ); + } + } + else if ( ManyToOneAttributeBinding.class.isInstance( attributeBinding ) ) { + for ( RelationalValueBinding valueBinding :( (BasicAttributeBinding) attributeBinding ).getRelationalValueBindings() ) { + targetColumns.add( valueBinding.getValue() ); + } + } + else if ( ComponentAttributeBinding.class.isInstance( attributeBinding ) ) { + collectValues( (ComponentAttributeBinding) attributeBinding, targetColumns ); + } + } + } + + private BasicAttributeBinding bindBasicAttribute( + SingularAttributeSource attributeSource, + AttributeBindingContainer attributeBindingContainer) { + final SingularAttribute existingAttribute = attributeBindingContainer.getAttributeContainer() + .locateSingularAttribute( attributeSource.getName() ); + final SingularAttribute attribute; + if ( existingAttribute != null ) { + attribute = existingAttribute; + } + else if ( attributeSource.isVirtualAttribute() ) { + attribute = attributeBindingContainer.getAttributeContainer().createVirtualSingularAttribute( + attributeSource.getName() + ); + } + else { + attribute = attributeBindingContainer.getAttributeContainer() + .createSingularAttribute( attributeSource.getName() ); + } + + final List relationalValueBindings = createSimpleRelationalValues( + attributeSource, + attributeBindingContainer, + attribute + ); + final String propertyAccessorName = Helper.getPropertyAccessorName( + attributeSource.getPropertyAccessorName(), + false, + currentBindingContext.getMappingDefaults().getPropertyAccessorName() + ); + final MetaAttributeContext metaAttributeContext = buildMetaAttributeContext( + attributeSource.metaAttributes(), + attributeBindingContainer.getMetaAttributeContext() + ); + + final BasicAttributeBinding attributeBinding = attributeBindingContainer.makeBasicAttributeBinding( + attribute, + relationalValueBindings, + propertyAccessorName, + attributeSource.isIncludedInOptimisticLocking(), + attributeSource.isLazy(), + metaAttributeContext, + attributeSource.getGeneration() + ); + resolveTypeInformation( attributeSource.getTypeInformation(), attributeBinding ); + return attributeBinding; + } + + private void bindComponentAttribute( ComponentAttributeSource attributeSource, AttributeBindingContainer container, Deque tableStack) { final String attributeName = attributeSource.getName(); SingularAttribute attribute = container.getAttributeContainer().locateComponentAttribute( attributeName ); + final Component component; if ( attribute == null ) { - final Component component = new Component( + component = new Component( attributeSource.getPath(), attributeSource.getClassName(), attributeSource.getClassReference(), @@ -546,17 +789,35 @@ public class Binder { ); attribute = container.getAttributeContainer().createComponentAttribute( attributeName, component ); } - ComponentAttributeBinding componentAttributeBinding = container.makeComponentAttributeBinding( attribute ); - - if ( StringHelper.isNotEmpty( attributeSource.getParentReferenceAttributeName() ) ) { - final SingularAttribute parentReferenceAttribute = - componentAttributeBinding.getComponent() - .createSingularAttribute( attributeSource.getParentReferenceAttributeName() ); - componentAttributeBinding.setParentReference( parentReferenceAttribute ); + else { + component = (Component) attribute.getSingularAttributeType(); } - componentAttributeBinding.setMetaAttributeContext( - buildMetaAttributeContext( attributeSource.metaAttributes(), container.getMetaAttributeContext() ) + final String propertyAccessorName = Helper.getPropertyAccessorName( + attributeSource.getPropertyAccessorName(), + false, + currentBindingContext.getMappingDefaults().getPropertyAccessorName() + ); + final MetaAttributeContext metaAttributeContext = buildMetaAttributeContext( + attributeSource.metaAttributes(), + container.getMetaAttributeContext() + ); + + final SingularAttribute parentReferenceAttribute; + if ( StringHelper.isNotEmpty( attributeSource.getParentReferenceAttributeName() ) ) { + parentReferenceAttribute = component.createSingularAttribute( attributeSource.getParentReferenceAttributeName() ); + } + else { + parentReferenceAttribute = null; + } + + ComponentAttributeBinding componentAttributeBinding = container.makeComponentAttributeBinding( + attribute, + parentReferenceAttribute, + propertyAccessorName, + attributeSource.isIncludedInOptimisticLocking(), + attributeSource.isLazy(), + metaAttributeContext ); bindAttributes( attributeSource, componentAttributeBinding, tableStack ); @@ -570,22 +831,41 @@ public class Binder { .locatePluralAttribute( attributeSource.getName() ); final AbstractPluralAttributeBinding pluralAttributeBinding; + final String propertyAccessorName = Helper.getPropertyAccessorName( + attributeSource.getPropertyAccessorName(), + false, + currentBindingContext.getMappingDefaults().getPropertyAccessorName() + ); + final MetaAttributeContext metaAttributeContext = buildMetaAttributeContext( + attributeSource.metaAttributes(), + attributeBindingContainer.getMetaAttributeContext() + ); if ( attributeSource.getPluralAttributeNature() == PluralAttributeNature.BAG ) { final PluralAttribute attribute = existingAttribute != null ? existingAttribute : attributeBindingContainer.getAttributeContainer().createBag( attributeSource.getName() ); pluralAttributeBinding = attributeBindingContainer.makeBagAttributeBinding( attribute, - convert( attributeSource.getElementSource().getNature() ) + convert( attributeSource.getElementSource().getNature() ), + propertyAccessorName, + attributeSource.isIncludedInOptimisticLocking(), + false, + metaAttributeContext ); } else if ( attributeSource.getPluralAttributeNature() == PluralAttributeNature.SET ) { final PluralAttribute attribute = existingAttribute != null ? existingAttribute : attributeBindingContainer.getAttributeContainer().createSet( attributeSource.getName() ); + final Comparator comparator = null; pluralAttributeBinding = attributeBindingContainer.makeSetAttributeBinding( attribute, - convert( attributeSource.getElementSource().getNature() ) + convert( attributeSource.getElementSource().getNature() ), + propertyAccessorName, + attributeSource.isIncludedInOptimisticLocking(), + false, + metaAttributeContext, + comparator ); } else { @@ -618,31 +898,18 @@ public class Binder { binding.getHibernateTypeDescriptor().getTypeParameters().putAll( source.getTypeInformation().getParameters() ); if ( StringHelper.isNotEmpty( source.getCustomPersisterClassName() ) ) { - binding.setCollectionPersisterClass( + binding.setExplicitPersisterClass( currentBindingContext.locateClassByName( source.getCustomPersisterClassName() ) ); } - if ( source.getCustomPersisterClassName() != null ) { - binding.setCollectionPersisterClass( - metadata.locateClassByName( source.getCustomPersisterClassName() ) - ); - } - binding.setCustomLoaderName( source.getCustomLoaderName() ); binding.setCustomSqlInsert( source.getCustomSqlInsert() ); binding.setCustomSqlUpdate( source.getCustomSqlUpdate() ); binding.setCustomSqlDelete( source.getCustomSqlDelete() ); binding.setCustomSqlDeleteAll( source.getCustomSqlDeleteAll() ); - binding.setMetaAttributeContext( - buildMetaAttributeContext( - source.metaAttributes(), - binding.getContainer().getMetaAttributeContext() - ) - ); - - doBasicAttributeBinding( source, binding ); +// doBasicAttributeBinding( source, binding ); } // private CollectionLaziness interpretLaziness(String laziness) { @@ -741,12 +1008,12 @@ public class Binder { ); final ForeignKey foreignKey = pluralAttributeBinding.getPluralAttributeKeyBinding().getForeignKey(); - Iterator targetValueBindings = null; + Iterator targetValueBindings = null; if ( attributeSource.getKeySource().getReferencedEntityAttributeName() != null ) { final EntityBinding ownerEntityBinding = pluralAttributeBinding.getContainer().seekEntityBinding(); - final AttributeBinding referencedAttributeBinding = - ownerEntityBinding - .locateAttributeBinding( attributeSource.getKeySource().getReferencedEntityAttributeName() ); + final AttributeBinding referencedAttributeBinding = ownerEntityBinding.locateAttributeBinding( + attributeSource.getKeySource().getReferencedEntityAttributeName() + ); if ( ! referencedAttributeBinding.getAttribute().isSingular() ) { throw new MappingException( String.format( @@ -757,10 +1024,10 @@ public class Binder { currentBindingContext.getOrigin() ); } - targetValueBindings = ( ( SingularAttributeBinding) referencedAttributeBinding ).getSimpleValueBindings().iterator(); +// targetValueBindings = ( (SingularAttributeBinding) referencedAttributeBinding ).getRelationalValueBindings().iterator(); } for ( RelationalValueSource valueSource : attributeSource.getKeySource().getValueSources() ) { - SimpleValue targetValue = null; + Value targetValue = null; if ( targetValueBindings != null ) { if ( ! targetValueBindings.hasNext() ) { throw new MappingException( @@ -771,7 +1038,7 @@ public class Binder { currentBindingContext.getOrigin() ); } - targetValue = targetValueBindings.next().getSimpleValue(); + targetValue = targetValueBindings.next().getValue(); } if ( ColumnSource.class.isInstance( valueSource ) ) { final ColumnSource columnSource = ColumnSource.class.cast( valueSource ); @@ -856,7 +1123,7 @@ public class Binder { private void bindBasicPluralElementRelationalValues( RelationalValueSourceContainer relationalValueSourceContainer, BasicPluralAttributeElementBinding elementBinding) { - elementBinding.setSimpleValueBindings( + elementBinding.setRelationalValueBindings( createSimpleRelationalValues( relationalValueSourceContainer, elementBinding.getPluralAttributeBinding().getContainer(), @@ -898,85 +1165,11 @@ public class Binder { } } - private void doBasicAttributeBinding(AttributeSource attributeSource, AttributeBinding attributeBinding) { - attributeBinding.setPropertyAccessorName( attributeSource.getPropertyAccessorName() ); - attributeBinding.setIncludedInOptimisticLocking( attributeSource.isIncludedInOptimisticLocking() ); - } - private PluralAttributeElementNature convert(org.hibernate.metamodel.spi.source.PluralAttributeElementNature pluralAttributeElementNature) { return PluralAttributeElementNature.valueOf( pluralAttributeElementNature.name() ); } - private BasicAttributeBinding doBasicSingularAttributeBindingCreation( - SingularAttributeSource attributeSource, - AttributeBindingContainer attributeBindingContainer) { - final SingularAttribute existingAttribute = attributeBindingContainer.getAttributeContainer() - .locateSingularAttribute( attributeSource.getName() ); - final SingularAttribute attribute; - if ( existingAttribute != null ) { - attribute = existingAttribute; - } - else if ( attributeSource.isVirtualAttribute() ) { - attribute = attributeBindingContainer.getAttributeContainer().createVirtualSingularAttribute( - attributeSource.getName() - ); - } - else { - attribute = attributeBindingContainer.getAttributeContainer() - .createSingularAttribute( attributeSource.getName() ); - } - - final BasicAttributeBinding attributeBinding; - if ( attributeSource.getNature() == SingularAttributeNature.BASIC ) - attributeBinding = attributeBindingContainer.makeBasicAttributeBinding( attribute ); - else if ( attributeSource.getNature() == SingularAttributeNature.MANY_TO_ONE ) - attributeBinding = attributeBindingContainer.makeManyToOneAttributeBinding( attribute ); - else throw new NotYetImplementedException(); - - attributeBinding.setGeneration( attributeSource.getGeneration() ); - attributeBinding.setLazy( attributeSource.isLazy() ); - attributeBinding.setIncludedInOptimisticLocking( attributeSource.isIncludedInOptimisticLocking() ); - - attributeBinding.setPropertyAccessorName( - Helper.getPropertyAccessorName( - attributeSource.getPropertyAccessorName(), - false, - currentBindingContext.getMappingDefaults().getPropertyAccessorName() - ) - ); - - bindRelationalValues( attributeSource, attributeBinding ); - - resolveTypeInformation( attributeSource.getTypeInformation(), attributeBinding ); - if ( attributeSource.getNature() == SingularAttributeNature.MANY_TO_ONE ) - resolveToOneInformation( ( ToOneAttributeSource ) attributeSource, ( ManyToOneAttributeBinding ) attributeBinding ); - - if ( attributeBinding instanceof SingularAssociationAttributeBinding ) { - SingularAssociationAttributeBinding assocAttrBinding = ( SingularAssociationAttributeBinding ) attributeBinding; - String referencedEntityName = assocAttrBinding.getReferencedEntityName(); - EntityBinding referencedEntityBinding = getEntityBinding( referencedEntityName ); - if (referencedEntityBinding == null) { - EntitySource source = sourcesByName.get(referencedEntityName); - createEntityBinding(source, referencedEntityBinding); - } - AttributeBinding referencedAttrBinding = assocAttrBinding.isPropertyReference() ? - referencedEntityBinding.locateAttributeBinding( assocAttrBinding.getReferencedAttributeName() ) : - referencedEntityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding(); - assocAttrBinding.resolveReference( referencedAttrBinding ); - referencedAttrBinding.addEntityReferencingAttributeBinding( assocAttrBinding ); - } - - attributeBinding.setMetaAttributeContext( - buildMetaAttributeContext( - attributeSource.metaAttributes(), - attributeBindingContainer.getMetaAttributeContext() - ) - ); - - return attributeBinding; - } - - private EntityBinding getEntityBinding( String entityName ) { + private EntityBinding getEntityBinding(String entityName) { // Check if binding has already been created EntityBinding binding = metadata.getEntityBinding( entityName ); if ( binding == null ) { @@ -994,7 +1187,9 @@ public class Binder { return binding; } - private void resolveTypeInformation(ExplicitHibernateTypeSource typeSource, BasicAttributeBinding attributeBinding) { + private final Properties EMPTY_PROPERTIES = new Properties(); + + private void resolveTypeInformation(ExplicitHibernateTypeSource typeSource, SingularAttributeBinding attributeBinding) { final Class attributeJavaType = determineJavaType( attributeBinding.getAttribute() ); if ( attributeJavaType != null ) { attributeBinding.getAttribute() @@ -1002,7 +1197,265 @@ public class Binder { } resolveTypeInformation( typeSource, attributeBinding.getHibernateTypeDescriptor(), attributeJavaType ); - resolveTypeInformation( attributeBinding.getHibernateTypeDescriptor(), (SimpleValue)attributeBinding.getValue() ); + resolveSingularAttributeTypeInformation( attributeBinding ); + } + + // perform any needed type resolutions for SingularAttributeBinding + private void resolveSingularAttributeTypeInformation(SingularAttributeBinding attributeBinding) { + if ( attributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping() != null ) { + return; + } + + // we can determine the Hibernate Type if either: + // 1) the user explicitly named a Type in a HibernateTypeDescriptor + // 2) we know the java type of the attribute + Type resolvedType = determineHibernateTypeFromDescriptor( attributeBinding.getHibernateTypeDescriptor() ); + if ( resolvedType == null ) { + if ( ! attributeBinding.getAttribute().isSingular() ) { + throw new AssertionFailure( "SingularAttributeBinding object has a plural attribute: " + attributeBinding.getAttribute().getName() ); + } + final SingularAttribute singularAttribute = attributeBinding.getAttribute(); + if ( singularAttribute.getSingularAttributeType() != null ) { + resolvedType = getHeuristicType( + singularAttribute.getSingularAttributeType().getClassName(), + EMPTY_PROPERTIES + ); + } + } + + if ( resolvedType != null ) { + pushHibernateTypeInformationDownIfNeeded( attributeBinding, resolvedType ); + } + } + + private Type determineHibernateTypeFromDescriptor(HibernateTypeDescriptor hibernateTypeDescriptor) { + if ( hibernateTypeDescriptor.getResolvedTypeMapping() != null ) { + return hibernateTypeDescriptor.getResolvedTypeMapping(); + } + String typeName = determineTypeName( hibernateTypeDescriptor ); + Properties typeParameters = getTypeParameters( hibernateTypeDescriptor ); + return getHeuristicType( typeName, typeParameters ); + } + + private static String determineTypeName(HibernateTypeDescriptor hibernateTypeDescriptor) { + return hibernateTypeDescriptor.getExplicitTypeName() != null + ? hibernateTypeDescriptor.getExplicitTypeName() + : hibernateTypeDescriptor.getJavaTypeName(); + } + + private static Properties getTypeParameters(HibernateTypeDescriptor hibernateTypeDescriptor) { + Properties typeParameters = new Properties( ); + if ( hibernateTypeDescriptor.getTypeParameters() != null ) { + typeParameters.putAll( hibernateTypeDescriptor.getTypeParameters() ); + } + return typeParameters; + } + + private void resolvePluralAttributeTypeInformation(AbstractPluralAttributeBinding attributeBinding) { + if ( attributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping() != null ) { + return; + } + Type resolvedType; + // do NOT look at java type... + //String typeName = determineTypeName( attributeBinding.getHibernateTypeDescriptor() ); + String typeName = attributeBinding.getHibernateTypeDescriptor().getExplicitTypeName(); + if ( typeName != null ) { + resolvedType = + metadata.getTypeResolver() + .getTypeFactory() + .customCollection( + typeName, + getTypeParameters( attributeBinding.getHibernateTypeDescriptor() ), + attributeBinding.getAttribute().getName(), + attributeBinding.getReferencedPropertyName(), + attributeBinding.getPluralAttributeElementBinding().getPluralAttributeElementNature() == + PluralAttributeElementNature.COMPOSITE + ); + } + else { + resolvedType = determineDefaultCollectionInformation( attributeBinding ); + } + if ( resolvedType != null ) { +// todo : what exactly is getting pushed down here? and to what/where? +// pushHibernateTypeInformationDownIfNeeded( +// attributeBinding.getHibernateTypeDescriptor(), +// null, +// resolvedType +// ); + } + resolveCollectionElementTypeInformation( attributeBinding.getPluralAttributeElementBinding() ); + } + + private Type determineDefaultCollectionInformation(AbstractPluralAttributeBinding attributeBinding) { + final TypeFactory typeFactory = metadata.getTypeResolver().getTypeFactory(); + switch ( attributeBinding.getAttribute().getNature() ) { + case SET: { + return typeFactory.set( + attributeBinding.getAttribute().getName(), + attributeBinding.getReferencedPropertyName(), + attributeBinding.getPluralAttributeElementBinding().getPluralAttributeElementNature() == PluralAttributeElementNature.COMPOSITE + ); + } + case BAG: { + return typeFactory.bag( + attributeBinding.getAttribute().getName(), + attributeBinding.getReferencedPropertyName(), + attributeBinding.getPluralAttributeElementBinding() + .getPluralAttributeElementNature() == PluralAttributeElementNature.COMPOSITE + ); + } + default: { + throw new UnsupportedOperationException( + "Collection type not supported yet:" + attributeBinding.getAttribute().getNature() + ); + } + } + } + + private void resolveCollectionElementTypeInformation(AbstractPluralAttributeElementBinding pluralAttributeElementBinding) { + switch ( pluralAttributeElementBinding.getPluralAttributeElementNature() ) { + case BASIC: { + resolveBasicCollectionElement( BasicPluralAttributeElementBinding.class.cast( + pluralAttributeElementBinding + ) ); + break; + } + case COMPOSITE: + case ONE_TO_MANY: + case MANY_TO_MANY: + case MANY_TO_ANY: { + throw new UnsupportedOperationException( "Collection element nature not supported yet: " + pluralAttributeElementBinding + .getPluralAttributeElementNature() ); + } + default: { + throw new AssertionFailure( "Unknown collection element nature : " + pluralAttributeElementBinding.getPluralAttributeElementNature() ); + } + } + } + + private void resolveBasicCollectionElement(BasicPluralAttributeElementBinding basicCollectionElement) { + Type resolvedHibernateType = determineHibernateTypeFromDescriptor( basicCollectionElement.getHibernateTypeDescriptor() ); + if ( resolvedHibernateType != null ) { + pushHibernateTypeInformationDownIfNeeded( + basicCollectionElement.getHibernateTypeDescriptor(), + basicCollectionElement.getRelationalValueBindings(), + resolvedHibernateType + ); + } + } + + private Type getHeuristicType(String typeName, Properties typeParameters) { + if ( typeName != null ) { + try { + return metadata.getTypeResolver().heuristicType( typeName, typeParameters ); + } + catch (Exception ignore) { + } + } + + return null; + } + + private void pushHibernateTypeInformationDownIfNeeded( + SingularAttributeBinding attributeBinding, + Type resolvedHibernateType) { + final HibernateTypeDescriptor hibernateTypeDescriptor = attributeBinding.getHibernateTypeDescriptor(); + + + // sql type information ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + if ( BasicAttributeBinding.class.isInstance( attributeBinding ) ) { + pushHibernateTypeInformationDownIfNeeded( + hibernateTypeDescriptor, + (BasicAttributeBinding) attributeBinding, + resolvedHibernateType + ); + } + else if ( ComponentAttributeBinding.class.isInstance( attributeBinding ) ) { + pushHibernateTypeInformationDownIfNeeded( + hibernateTypeDescriptor, + (ComponentAttributeBinding) attributeBinding + ); + } + } + + private void pushHibernateTypeInformationDownIfNeeded( + HibernateTypeDescriptor hibernateTypeDescriptor, + ComponentAttributeBinding attributeBinding) { + final SingularAttribute singularAttribute = SingularAttribute.class.cast( attributeBinding.getAttribute() ); + if ( ! singularAttribute.isTypeResolved() && hibernateTypeDescriptor.getJavaTypeName() != null ) { + singularAttribute.resolveType( metadata.makeJavaType( hibernateTypeDescriptor.getJavaTypeName() ) ); + } + + for ( AttributeBinding subAttributeBinding : attributeBinding.attributeBindings() ) { + if ( SingularAttributeBinding.class.isInstance( subAttributeBinding ) ) { + resolveSingularAttributeTypeInformation( + SingularAttributeBinding.class.cast( subAttributeBinding ) + ); + } + else if ( AbstractPluralAttributeBinding.class.isInstance( subAttributeBinding ) ) { + resolvePluralAttributeTypeInformation( + AbstractPluralAttributeBinding.class.cast( subAttributeBinding ) + ); + } + else { + throw new AssertionFailure( "Unknown type of AttributeBinding: " + attributeBinding.getClass().getName() ); + } + } + } + + private void pushHibernateTypeInformationDownIfNeeded( + HibernateTypeDescriptor hibernateTypeDescriptor, + BasicAttributeBinding attributeBinding, + Type resolvedHibernateType) { + final SingularAttribute singularAttribute = SingularAttribute.class.cast( attributeBinding.getAttribute() ); + if ( ! singularAttribute.isTypeResolved() && hibernateTypeDescriptor.getJavaTypeName() != null ) { + singularAttribute.resolveType( metadata.makeJavaType( hibernateTypeDescriptor.getJavaTypeName() ) ); + } + pushHibernateTypeInformationDownIfNeeded( + hibernateTypeDescriptor, + attributeBinding.getRelationalValueBindings(), + resolvedHibernateType + ); + } + + private void pushHibernateTypeInformationDownIfNeeded( + HibernateTypeDescriptor hibernateTypeDescriptor, + List relationalValueBindings, + Type resolvedHibernateType) { + if ( resolvedHibernateType == null ) { + return; + } + if ( hibernateTypeDescriptor.getResolvedTypeMapping() == null ) { + hibernateTypeDescriptor.setResolvedTypeMapping( resolvedHibernateType ); + } + + // java type information ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + if ( hibernateTypeDescriptor.getJavaTypeName() == null ) { + hibernateTypeDescriptor.setJavaTypeName( resolvedHibernateType.getReturnedClass().getName() ); + } + + // todo : this can be made a lot smarter, but for now this will suffice. currently we only handle single value bindings + + if ( relationalValueBindings.size() > 1 ) { + return; + } + final Value value = relationalValueBindings.get( 0 ).getValue(); + pushHibernateTypeInformationDownIfNeeded( resolvedHibernateType, value ); + } + + private void pushHibernateTypeInformationDownIfNeeded(Type resolvedHibernateType, Value value) { + if ( value.getJdbcDataType() == null ) { + if ( AbstractValue.class.isInstance( value ) ) { + ( (AbstractValue) value ).setJdbcDataType( + new JdbcDataType( + resolvedHibernateType.sqlTypes( metadata )[0], + resolvedHibernateType.getName(), + resolvedHibernateType.getReturnedClass() + ) + ); + } + } } private void resolveTypeInformation( @@ -1045,29 +1498,6 @@ public class Binder { } } - private void resolveTypeInformation( HibernateTypeDescriptor descriptor, - SimpleValue value ) { - Type resolvedType = descriptor.getResolvedTypeMapping(); - if ( resolvedType == null ) { - final String name = descriptor.getExplicitTypeName() == null ? descriptor.getJavaTypeName() : descriptor.getExplicitTypeName(); - if (name != null) { - resolvedType = metadata.getTypeResolver().heuristicType( name, convertTypeParametersToProperties( descriptor ) ); - descriptor.setResolvedTypeMapping( resolvedType ); - } - if (resolvedType == null) return; - } - if ( descriptor.getJavaTypeName() == null ) descriptor.setJavaTypeName( resolvedType.getReturnedClass().getName() ); - if ( value.getDatatype() == null ) - value.setDatatype( new Datatype( resolvedType.sqlTypes( metadata )[0], resolvedType.getName(), - resolvedType.getReturnedClass() ) ); - } - - private Properties convertTypeParametersToProperties( HibernateTypeDescriptor descriptor ) { - Properties props = new Properties( ); - if ( descriptor.getTypeParameters() != null ) props.putAll( descriptor.getTypeParameters() ); - return props; - } - /** * @param attribute the domain attribute * @@ -1209,24 +1639,12 @@ public class Binder { } } - private void bindRelationalValues( - RelationalValueSourceContainer relationalValueSourceContainer, - SingularAttributeBinding attributeBinding) { - attributeBinding.setSimpleValueBindings( - createSimpleRelationalValues( - relationalValueSourceContainer, - attributeBinding.getContainer(), - attributeBinding.getAttribute() - ) - ); - } - - private List createSimpleRelationalValues( + private List createSimpleRelationalValues( RelationalValueSourceContainer relationalValueSourceContainer, AttributeBindingContainer attributeBindingContainer, Attribute attribute) { - List valueBindings = new ArrayList(); + List valueBindings = new ArrayList(); if ( !relationalValueSourceContainer.relationalValueSources().isEmpty() ) { for ( RelationalValueSource valueSource : relationalValueSourceContainer.relationalValueSources() ) { @@ -1238,7 +1656,7 @@ public class Binder { final ColumnSource columnSource = ColumnSource.class.cast( valueSource ); final Column column = makeColumn( (ColumnSource) valueSource, relationalValueSourceContainer, table ); valueBindings.add( - new SimpleValueBinding( + new RelationalValueBinding( column, decode( columnSource.isIncludedInInsert(), relationalValueSourceContainer.areValuesIncludedInInsertByDefault() ), decode( @@ -1250,7 +1668,7 @@ public class Binder { } else { valueBindings.add( - new SimpleValueBinding( + new RelationalValueBinding( makeDerivedValue( ( (DerivedValueSource) valueSource ), table ) ) ); @@ -1267,7 +1685,7 @@ public class Binder { .getPrimaryTable() .locateOrCreateColumn( name ); column.setNullable( relationalValueSourceContainer.areValuesNullableByDefault() ); - valueBindings.add( new SimpleValueBinding( column ) ); + valueBindings.add( new RelationalValueBinding( column ) ); } return valueBindings; } @@ -1276,7 +1694,22 @@ public class Binder { return currentBindingContext.isGloballyQuotedIdentifiers() ? StringHelper.quote( identifier ) : identifier; } - private SimpleValue makeSimpleValue( + private Value locateOrMakeValue( + TableSpecification table, + RelationalValueSource relationalValueSource, + ColumnBindingDefaults columnBindingDefaults) { + if ( ColumnSource.class.isInstance( relationalValueSource ) ) { + final Column column = table.locateColumn( ( (Column) relationalValueSource ).getColumnName().getName() ); + return column == null + ? makeColumn( (ColumnSource) relationalValueSource, columnBindingDefaults, table ) + : column; + } + else { + return makeDerivedValue( (DerivedValueSource) relationalValueSource, table ); + } + } + + private Value makeRelationalValue( EntityBinding entityBinding, RelationalValueSource valueSource, ColumnBindingDefaults columnBindingDefaults) { @@ -1304,7 +1737,7 @@ public class Binder { column.setDefaultValue( columnSource.getDefaultValue() ); column.setSqlType( columnSource.getSqlType() ); column.setSize( columnSource.getSize() ); - column.setDatatype( columnSource.getDatatype() ); + column.setJdbcDataType( columnSource.getDatatype() ); column.setReadFragment( columnSource.getReadFragment() ); column.setWriteFragment( columnSource.getWriteFragment() ); column.setUnique( columnSource.isUnique() ); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/ColumnValuesSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/ColumnValuesSourceImpl.java index a9cf1a91be..0e913668fe 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/ColumnValuesSourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/ColumnValuesSourceImpl.java @@ -24,7 +24,7 @@ package org.hibernate.metamodel.internal.source.annotations.attribute; import org.hibernate.TruthValue; -import org.hibernate.metamodel.spi.relational.Datatype; +import org.hibernate.metamodel.spi.relational.JdbcDataType; import org.hibernate.metamodel.spi.relational.Size; import org.hibernate.metamodel.spi.source.ColumnSource; @@ -68,7 +68,7 @@ public class ColumnValuesSourceImpl implements ColumnSource { } @Override - public Datatype getDatatype() { + public JdbcDataType getDatatype() { return null; } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/ToOneAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/ToOneAttributeSourceImpl.java index f06c90a4a7..05f346778b 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/ToOneAttributeSourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/ToOneAttributeSourceImpl.java @@ -66,6 +66,11 @@ public class ToOneAttributeSourceImpl extends SingularAttributeSourceImpl implem return associationAttribute.getMappedBy(); } + @Override + public String getForeignKeyName() { + return null; + } + @Override public Iterable getCascadeStyles() { return cascadeStyles; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/VersionAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/VersionAttributeSourceImpl.java new file mode 100644 index 0000000000..9162d54f5a --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/VersionAttributeSourceImpl.java @@ -0,0 +1,47 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.internal.source.annotations.attribute; + +import org.hibernate.metamodel.spi.source.VersionAttributeSource; + +/** + * @author Steve Ebersole + */ +public class VersionAttributeSourceImpl + extends SingularAttributeSourceImpl + implements VersionAttributeSource { + + public VersionAttributeSourceImpl(MappedAttribute attribute) { + super( attribute ); + } + + public VersionAttributeSourceImpl(MappedAttribute attribute, AttributeOverride attributeOverride) { + super( attribute, attributeOverride ); + } + + @Override + public String getUnsavedValue() { + return null; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/RootEntitySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/RootEntitySourceImpl.java index 66e58f9527..4301f8eaf6 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/RootEntitySourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/RootEntitySourceImpl.java @@ -27,15 +27,15 @@ import org.hibernate.AssertionFailure; import org.hibernate.EntityMode; import org.hibernate.cfg.NotYetImplementedException; import org.hibernate.engine.OptimisticLockStyle; -import org.hibernate.metamodel.spi.binding.Caching; import org.hibernate.metamodel.internal.source.annotations.attribute.BasicAttribute; import org.hibernate.metamodel.internal.source.annotations.attribute.DiscriminatorSourceImpl; import org.hibernate.metamodel.internal.source.annotations.attribute.SimpleIdentifierSourceImpl; -import org.hibernate.metamodel.internal.source.annotations.attribute.SingularAttributeSourceImpl; +import org.hibernate.metamodel.internal.source.annotations.attribute.VersionAttributeSourceImpl; +import org.hibernate.metamodel.spi.binding.Caching; import org.hibernate.metamodel.spi.source.DiscriminatorSource; import org.hibernate.metamodel.spi.source.IdentifierSource; import org.hibernate.metamodel.spi.source.RootEntitySource; -import org.hibernate.metamodel.spi.source.SingularAttributeSource; +import org.hibernate.metamodel.spi.source.VersionAttributeSource; /** * @author Hardy Ferentschik @@ -66,13 +66,12 @@ public class RootEntitySourceImpl extends EntitySourceImpl implements RootEntity } @Override - public SingularAttributeSource getVersioningAttributeSource() { - SingularAttributeSource attributeSource = null; - EntityClass entityClass = getEntityClass(); - if ( entityClass.getVersionAttribute() != null ) { - attributeSource = new SingularAttributeSourceImpl( entityClass.getVersionAttribute() ); + public VersionAttributeSource getVersioningAttributeSource() { + final EntityClass entityClass = getEntityClass(); + if ( entityClass.getVersionAttribute() == null ) { + return null; } - return attributeSource; + return new VersionAttributeSourceImpl( entityClass.getVersionAttribute() ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/global/TableProcessor.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/global/TableProcessor.java index 19b96c85b3..aff73c0eb6 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/global/TableProcessor.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/global/TableProcessor.java @@ -31,16 +31,16 @@ import org.jboss.logging.Logger; import org.hibernate.AnnotationException; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.util.StringHelper; -import org.hibernate.metamodel.spi.relational.Column; -import org.hibernate.metamodel.spi.relational.ObjectName; -import org.hibernate.metamodel.spi.relational.Schema; -import org.hibernate.metamodel.spi.relational.SimpleValue; -import org.hibernate.metamodel.spi.relational.Table; -import org.hibernate.metamodel.spi.source.MetadataImplementor; import org.hibernate.metamodel.internal.source.annotations.AnnotationBindingContext; import org.hibernate.metamodel.internal.source.annotations.HibernateDotNames; import org.hibernate.metamodel.internal.source.annotations.JandexHelper; +import org.hibernate.metamodel.spi.relational.Column; import org.hibernate.metamodel.spi.relational.Index; +import org.hibernate.metamodel.spi.relational.ObjectName; +import org.hibernate.metamodel.spi.relational.Schema; +import org.hibernate.metamodel.spi.relational.Table; +import org.hibernate.metamodel.spi.relational.Value; +import org.hibernate.metamodel.spi.source.MetadataImplementor; /** * Binds table related information. This binder is called after the entities are bound. @@ -120,7 +120,7 @@ public class TableProcessor { private static Column findColumn(Table table, String columnName) { Column column = null; - for ( SimpleValue value : table.values() ) { + for ( Value value : table.values() ) { if ( value instanceof Column && ( (Column) value ).getColumnName().getName().equals( columnName ) ) { column = (Column) value; break; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ColumnAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ColumnAttributeSourceImpl.java index 7e2b22c2c9..08212cefe1 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ColumnAttributeSourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ColumnAttributeSourceImpl.java @@ -24,7 +24,7 @@ package org.hibernate.metamodel.internal.source.hbm; import org.hibernate.TruthValue; -import org.hibernate.metamodel.spi.relational.Datatype; +import org.hibernate.metamodel.spi.relational.JdbcDataType; import org.hibernate.metamodel.spi.relational.Size; import org.hibernate.metamodel.spi.source.ColumnSource; @@ -103,7 +103,7 @@ class ColumnAttributeSourceImpl implements ColumnSource { } @Override - public Datatype getDatatype() { + public JdbcDataType getDatatype() { return null; } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ColumnSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ColumnSourceImpl.java index 4200131744..bfb54f0fac 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ColumnSourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/ColumnSourceImpl.java @@ -25,7 +25,7 @@ package org.hibernate.metamodel.internal.source.hbm; import org.hibernate.TruthValue; import org.hibernate.internal.jaxb.mapping.hbm.JaxbColumnElement; -import org.hibernate.metamodel.spi.relational.Datatype; +import org.hibernate.metamodel.spi.relational.JdbcDataType; import org.hibernate.metamodel.spi.relational.Size; import org.hibernate.metamodel.spi.source.ColumnSource; @@ -86,7 +86,7 @@ class ColumnSourceImpl implements ColumnSource { } @Override - public Datatype getDatatype() { + public JdbcDataType getDatatype() { return null; } 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 5319b23894..9ae8e4bfdd 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 @@ -268,4 +268,9 @@ class ManyToOneAttributeSourceImpl implements ToOneAttributeSource { public String getReferencedEntityAttributeName() { return manyToOneElement.getPropertyRef(); } + + @Override + public String getForeignKeyName() { + return manyToOneElement.getForeignKey(); + } } 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 0f5f503fb4..3537132b6b 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 @@ -45,6 +45,7 @@ import org.hibernate.metamodel.spi.source.RootEntitySource; import org.hibernate.metamodel.spi.source.SimpleIdentifierSource; import org.hibernate.metamodel.spi.source.SingularAttributeSource; import org.hibernate.metamodel.spi.source.TableSource; +import org.hibernate.metamodel.spi.source.VersionAttributeSource; /** * @author Steve Ebersole @@ -100,7 +101,7 @@ public class RootEntitySourceImpl extends AbstractEntitySourceImpl implements Ro } @Override - public SingularAttributeSource getVersioningAttributeSource() { + public VersionAttributeSource getVersioningAttributeSource() { if ( entityElement().getVersion() != null ) { return new VersionAttributeSourceImpl( entityElement().getVersion(), diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/TimestampAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/TimestampAttributeSourceImpl.java index 2dc8ee4894..f89b745807 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/TimestampAttributeSourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/TimestampAttributeSourceImpl.java @@ -29,20 +29,20 @@ import java.util.Map; import org.hibernate.internal.jaxb.mapping.hbm.JaxbHibernateMapping; import org.hibernate.internal.util.Value; import org.hibernate.mapping.PropertyGeneration; +import org.hibernate.metamodel.spi.source.ExplicitHibernateTypeSource; import org.hibernate.metamodel.spi.source.LocalBindingContext; import org.hibernate.metamodel.spi.source.MappingException; -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.SingularAttributeNature; -import org.hibernate.metamodel.spi.source.SingularAttributeSource; +import org.hibernate.metamodel.spi.source.VersionAttributeSource; /** * Implementation for {@code } mappings * * @author Steve Ebersole */ -class TimestampAttributeSourceImpl implements SingularAttributeSource { +class TimestampAttributeSourceImpl implements VersionAttributeSource { private final JaxbHibernateMapping.JaxbClass.JaxbTimestamp timestampElement; private final LocalBindingContext bindingContext; private final List valueSources; @@ -193,4 +193,9 @@ class TimestampAttributeSourceImpl implements SingularAttributeSource { public Iterable metaAttributes() { return Helper.buildMetaAttributeSources( timestampElement.getMeta() ); } + + @Override + public String getUnsavedValue() { + return timestampElement.getUnsavedValue(); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/VersionAttributeSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/VersionAttributeSourceImpl.java index 13562df5d5..f789f92e3a 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/VersionAttributeSourceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/hbm/VersionAttributeSourceImpl.java @@ -35,14 +35,15 @@ 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.SingularAttributeNature; -import org.hibernate.metamodel.spi.source.SingularAttributeSource; +import org.hibernate.metamodel.spi.source.VersionAttributeSource; + /** * Implementation for {@code } mappings * * @author Steve Ebersole */ -class VersionAttributeSourceImpl implements SingularAttributeSource { +class VersionAttributeSourceImpl implements VersionAttributeSource { private final JaxbHibernateMapping.JaxbClass.JaxbVersion versionElement; private final LocalBindingContext bindingContext; private final List valueSources; @@ -101,6 +102,11 @@ class VersionAttributeSourceImpl implements SingularAttributeSource { } }; + @Override + public String getUnsavedValue() { + return versionElement.getUnsavedValue(); + } + @Override public String getName() { return versionElement.getName(); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractAttributeBinding.java index 72f4f16f8e..758639a692 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractAttributeBinding.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractAttributeBinding.java @@ -42,17 +42,27 @@ public abstract class AbstractAttributeBinding implements AttributeBinding { private final HibernateTypeDescriptor hibernateTypeDescriptor = new HibernateTypeDescriptor(); private final Set entityReferencingAttributeBindings = new HashSet(); - private boolean includedInOptimisticLocking; + private final String propertyAccessorName; + private final boolean includedInOptimisticLocking; + private final boolean isLazy; - private boolean isLazy; - private String propertyAccessorName; private boolean isAlternateUniqueKey; - private MetaAttributeContext metaAttributeContext; + private final MetaAttributeContext metaAttributeContext; - protected AbstractAttributeBinding(AttributeBindingContainer container, Attribute attribute) { + protected AbstractAttributeBinding( + AttributeBindingContainer container, + Attribute attribute, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean isLazy, + MetaAttributeContext metaAttributeContext) { this.container = container; this.attribute = attribute; + this.propertyAccessorName = propertyAccessorName; + this.includedInOptimisticLocking = includedInOptimisticLocking; + this.isLazy = isLazy; + this.metaAttributeContext = metaAttributeContext; } @Override @@ -84,30 +94,19 @@ public abstract class AbstractAttributeBinding implements AttributeBinding { return propertyAccessorName; } - public void setPropertyAccessorName(String propertyAccessorName) { - this.propertyAccessorName = propertyAccessorName; - } - @Override public boolean isIncludedInOptimisticLocking() { return includedInOptimisticLocking; } - public void setIncludedInOptimisticLocking(boolean includedInOptimisticLocking) { - this.includedInOptimisticLocking = includedInOptimisticLocking; - } - @Override public MetaAttributeContext getMetaAttributeContext() { return metaAttributeContext; } - public void setMetaAttributeContext(MetaAttributeContext metaAttributeContext) { - this.metaAttributeContext = metaAttributeContext; - } - @Override public boolean isAlternateUniqueKey() { + // todo : is this the same as "part of natural id"? return isAlternateUniqueKey; } @@ -120,10 +119,6 @@ public abstract class AbstractAttributeBinding implements AttributeBinding { return isLazy; } - public void setLazy(boolean isLazy) { - this.isLazy = isLazy; - } - public void addEntityReferencingAttributeBinding(SingularAssociationAttributeBinding referencingAttributeBinding) { entityReferencingAttributeBindings.add( referencingAttributeBinding ); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractPluralAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractPluralAttributeBinding.java index 7a754bc6cf..eb78ec4c84 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractPluralAttributeBinding.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractPluralAttributeBinding.java @@ -34,6 +34,7 @@ import org.hibernate.engine.FetchTiming; import org.hibernate.metamodel.spi.domain.PluralAttribute; import org.hibernate.metamodel.spi.relational.Table; import org.hibernate.metamodel.spi.relational.TableSpecification; +import org.hibernate.metamodel.spi.source.MetaAttributeContext; import org.hibernate.persister.collection.CollectionPersister; /** @@ -56,7 +57,7 @@ public abstract class AbstractPluralAttributeBinding extends AbstractAttributeBi private boolean mutable = true; - private Class collectionPersisterClass; + private Class explicitPersisterClass; private String where; private String orderBy; @@ -78,8 +79,19 @@ public abstract class AbstractPluralAttributeBinding extends AbstractAttributeBi protected AbstractPluralAttributeBinding( AttributeBindingContainer container, PluralAttribute attribute, - PluralAttributeElementNature pluralAttributeElementNature) { - super( container, attribute ); + PluralAttributeElementNature pluralAttributeElementNature, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean isLazy, + MetaAttributeContext metaAttributeContext) { + super( + container, + attribute, + propertyAccessorName, + includedInOptimisticLocking, + isLazy, + metaAttributeContext + ); this.pluralAttributeKeyBinding = new PluralAttributeKeyBinding( this ); this.pluralAttributeElementBinding = interpretNature( pluralAttributeElementNature ); } @@ -214,12 +226,13 @@ public abstract class AbstractPluralAttributeBinding extends AbstractAttributeBi this.customSqlDeleteAll = customSqlDeleteAll; } - public Class getCollectionPersisterClass() { - return collectionPersisterClass; + @Override + public Class getExplicitPersisterClass() { + return explicitPersisterClass; } - public void setCollectionPersisterClass(Class collectionPersisterClass) { - this.collectionPersisterClass = collectionPersisterClass; + public void setExplicitPersisterClass(Class explicitPersisterClass) { + this.explicitPersisterClass = explicitPersisterClass; } public Caching getCaching() { diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractSingularAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractSingularAttributeBinding.java index 69a8b7d540..b6998aded9 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractSingularAttributeBinding.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AbstractSingularAttributeBinding.java @@ -23,14 +23,10 @@ */ package org.hibernate.metamodel.spi.binding; -import java.util.ArrayList; import java.util.List; -import org.hibernate.AssertionFailure; import org.hibernate.metamodel.spi.domain.SingularAttribute; -import org.hibernate.metamodel.spi.relational.SimpleValue; -import org.hibernate.metamodel.spi.relational.Tuple; -import org.hibernate.metamodel.spi.relational.Value; +import org.hibernate.metamodel.spi.source.MetaAttributeContext; /** * @author Steve Ebersole @@ -39,14 +35,14 @@ public abstract class AbstractSingularAttributeBinding extends AbstractAttributeBinding implements SingularAttributeBinding { - private Value value; - private List simpleValueBindings = new ArrayList(); - - private boolean hasDerivedValue; - private boolean isNullable = true; - - protected AbstractSingularAttributeBinding(AttributeBindingContainer container, SingularAttribute attribute) { - super( container, attribute ); + protected AbstractSingularAttributeBinding( + AttributeBindingContainer container, + SingularAttribute attribute, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + MetaAttributeContext metaAttributeContext) { + super( container, attribute, propertyAccessorName, includedInOptimisticLocking, lazy, metaAttributeContext ); } @Override @@ -54,56 +50,5 @@ public abstract class AbstractSingularAttributeBinding return (SingularAttribute) super.getAttribute(); } - public Value getValue() { - return value; - } - - public void setSimpleValueBindings(Iterable simpleValueBindings) { - List values = new ArrayList(); - for ( SimpleValueBinding simpleValueBinding : simpleValueBindings ) { - this.simpleValueBindings.add( simpleValueBinding ); - values.add( simpleValueBinding.getSimpleValue() ); - this.hasDerivedValue = this.hasDerivedValue || simpleValueBinding.isDerived(); - this.isNullable = this.isNullable && simpleValueBinding.isNullable(); - } - if ( values.size() == 1 ) { - this.value = values.get( 0 ); - } - else { - final Tuple tuple = values.get( 0 ).getTable().createTuple( getRole() ); - for ( SimpleValue value : values ) { - tuple.addValue( value ); - } - this.value = tuple; - } - } - - @Override - public int getSimpleValueSpan() { - checkValueBinding(); - return simpleValueBindings.size(); - } - - protected void checkValueBinding() { - if ( value == null ) { - throw new AssertionFailure( "No values yet bound!" ); - } - } - - @Override - public Iterable getSimpleValueBindings() { - return simpleValueBindings; - } - - @Override - public boolean hasDerivedValue() { - checkValueBinding(); - return hasDerivedValue; - } - - @Override - public boolean isNullable() { - checkValueBinding(); - return isNullable; - } + protected abstract void collectRelationalValueBindings(List valueBindings); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AttributeBinding.java index ae86df18c1..ea2f57ac20 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AttributeBinding.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/AttributeBinding.java @@ -64,12 +64,8 @@ public interface AttributeBinding { public String getPropertyAccessorName(); - public void setPropertyAccessorName(String propertyAccessorName); - public boolean isIncludedInOptimisticLocking(); - public void setIncludedInOptimisticLocking(boolean includedInOptimisticLocking); - /** * Obtain the meta attributes associated with this binding * 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 3e85c76118..590f537718 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 @@ -23,9 +23,14 @@ */ package org.hibernate.metamodel.spi.binding; +import java.util.Comparator; +import java.util.List; + +import org.hibernate.mapping.PropertyGeneration; import org.hibernate.metamodel.spi.domain.AttributeContainer; import org.hibernate.metamodel.spi.domain.PluralAttribute; import org.hibernate.metamodel.spi.domain.SingularAttribute; +import org.hibernate.metamodel.spi.relational.ForeignKey; import org.hibernate.metamodel.spi.source.MetaAttributeContext; /** @@ -72,7 +77,14 @@ public interface AttributeBindingContainer { * * @return The attribute binding instance. */ - public BasicAttributeBinding makeBasicAttributeBinding(SingularAttribute attribute); + public BasicAttributeBinding makeBasicAttributeBinding( + SingularAttribute attribute, + List relationalValueBindings, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + MetaAttributeContext metaAttributeContext, + PropertyGeneration generation); /** * Factory method for component attribute bindings. @@ -81,16 +93,33 @@ public interface AttributeBindingContainer { * * @return The attribute binding instance. */ - public ComponentAttributeBinding makeComponentAttributeBinding(SingularAttribute attribute); + public ComponentAttributeBinding makeComponentAttributeBinding( + SingularAttribute attribute, + SingularAttribute parentReferenceAttribute, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + MetaAttributeContext metaAttributeContext); /** * Factory method for many-to-one attribute bindings. * + * * @param attribute The attribute for which to make a binding. + * @param referencedEntityName + * @param referencedEntityAttributeName * * @return The attribute binding instance. */ - public ManyToOneAttributeBinding makeManyToOneAttributeBinding(SingularAttribute attribute); + public ManyToOneAttributeBinding makeManyToOneAttributeBinding( + SingularAttribute attribute, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + MetaAttributeContext metaAttributeContext, + String referencedEntityName, + String referencedEntityAttributeName, + List valueBindings); /** * Factory method for bag attribute bindings. @@ -100,7 +129,13 @@ public interface AttributeBindingContainer { * * @return The attribute binding instance. */ - public BagBinding makeBagAttributeBinding(PluralAttribute attribute, PluralAttributeElementNature nature); + public BagBinding makeBagAttributeBinding( + PluralAttribute attribute, + PluralAttributeElementNature nature, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + MetaAttributeContext metaAttributeContext); /** * Factory method for bag attribute bindings. @@ -110,7 +145,14 @@ public interface AttributeBindingContainer { * * @return The attribute binding instance. */ - public SetBinding makeSetAttributeBinding(PluralAttribute attribute, PluralAttributeElementNature nature); + public SetBinding makeSetAttributeBinding( + PluralAttribute attribute, + PluralAttributeElementNature nature, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + MetaAttributeContext metaAttributeContext, + Comparator comparator); /** * Seeks out the entity binding that is the root of this component path. diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/BagBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/BagBinding.java index 091b1ac366..04fc168fdc 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/BagBinding.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/BagBinding.java @@ -24,6 +24,7 @@ package org.hibernate.metamodel.spi.binding; import org.hibernate.metamodel.spi.domain.PluralAttribute; +import org.hibernate.metamodel.spi.source.MetaAttributeContext; /** * TODO : javadoc @@ -31,7 +32,22 @@ import org.hibernate.metamodel.spi.domain.PluralAttribute; * @author Steve Ebersole */ public class BagBinding extends AbstractPluralAttributeBinding { - protected BagBinding(AttributeBindingContainer container, PluralAttribute attribute, PluralAttributeElementNature nature) { - super( container, attribute, nature ); + protected BagBinding( + AttributeBindingContainer container, + PluralAttribute attribute, + PluralAttributeElementNature pluralAttributeElementNature, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean isLazy, + MetaAttributeContext metaAttributeContext) { + super( + container, + attribute, + pluralAttributeElementNature, + propertyAccessorName, + includedInOptimisticLocking, + isLazy, + metaAttributeContext + ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/BasicAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/BasicAttributeBinding.java index fddc55214f..ce33921891 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/BasicAttributeBinding.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/BasicAttributeBinding.java @@ -23,6 +23,8 @@ */ package org.hibernate.metamodel.spi.binding; +import java.util.Collections; +import java.util.List; import java.util.Properties; import org.hibernate.MappingException; @@ -33,36 +35,45 @@ import org.hibernate.mapping.PropertyGeneration; import org.hibernate.metamodel.spi.domain.SingularAttribute; import org.hibernate.metamodel.spi.relational.Column; import org.hibernate.metamodel.spi.relational.Schema; -import org.hibernate.metamodel.spi.relational.SimpleValue; +import org.hibernate.metamodel.spi.relational.TableSpecification; import org.hibernate.metamodel.spi.source.MetaAttributeContext; /** - * TODO : javadoc + * TODO : this really needs an overhaul... mainly, get rid of the KeyValueBinding concept... * * @author Steve Ebersole */ public class BasicAttributeBinding - extends AbstractSingularAttributeBinding - implements KeyValueBinding { + extends AbstractSingularAttributeBinding { - private String unsavedValue; - private PropertyGeneration generation; - private boolean includedInOptimisticLocking; - - private boolean forceNonNullable; - private boolean forceUnique; - private boolean keyCascadeDeleteEnabled; - - private MetaAttributeContext metaAttributeContext; + private final List relationalValueBindings; + private boolean hasDerivedValue; + private boolean isNullable = true; + private final PropertyGeneration generation; BasicAttributeBinding( AttributeBindingContainer container, SingularAttribute attribute, - boolean forceNonNullable, - boolean forceUnique) { - super( container, attribute ); - this.forceNonNullable = forceNonNullable; - this.forceUnique = forceUnique; + List relationalValueBindings, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + MetaAttributeContext metaAttributeContext, + PropertyGeneration generation) { + super( + container, + attribute, + propertyAccessorName, + includedInOptimisticLocking, + lazy, + metaAttributeContext + ); + this.relationalValueBindings = Collections.unmodifiableList( relationalValueBindings ); + for ( RelationalValueBinding relationalValueBinding : relationalValueBindings ) { + this.hasDerivedValue = this.hasDerivedValue || relationalValueBinding.isDerived(); + this.isNullable = this.isNullable && relationalValueBinding.isNullable(); + } + this.generation = generation; } @Override @@ -70,68 +81,50 @@ public class BasicAttributeBinding return false; } - @Override - public String getUnsavedValue() { - return unsavedValue; - } - - public void setUnsavedValue(String unsavedValue) { - this.unsavedValue = unsavedValue; + public List getRelationalValueBindings() { + return relationalValueBindings; } @Override + public boolean hasDerivedValue() { + return hasDerivedValue; + } + + @Override + public boolean isNullable() { + return isNullable; + } + public PropertyGeneration getGeneration() { return generation; } - public void setGeneration(PropertyGeneration generation) { - this.generation = generation; - } - - public boolean isIncludedInOptimisticLocking() { - return includedInOptimisticLocking; - } - - public void setIncludedInOptimisticLocking(boolean includedInOptimisticLocking) { - this.includedInOptimisticLocking = includedInOptimisticLocking; - } - - @Override - public boolean isKeyCascadeDeleteEnabled() { - return keyCascadeDeleteEnabled; - } - - public void setKeyCascadeDeleteEnabled(boolean keyCascadeDeleteEnabled) { - this.keyCascadeDeleteEnabled = keyCascadeDeleteEnabled; - } - - public boolean forceNonNullable() { - return forceNonNullable; - } - - public boolean forceUnique() { - return forceUnique; - } - - public MetaAttributeContext getMetaAttributeContext() { - return metaAttributeContext; - } - - public void setMetaAttributeContext(MetaAttributeContext metaAttributeContext) { - this.metaAttributeContext = metaAttributeContext; - } - IdentifierGenerator createIdentifierGenerator( IdGenerator idGenerator, IdentifierGeneratorFactory identifierGeneratorFactory, Properties properties) { + if ( getRelationalValueBindings().size() > 1 ) { + throw new MappingException( + "A SimpleAttributeBinding used for an identifier has more than 1 Value: " + getAttribute().getName() + ); + } + + final RelationalValueBinding relationalValueBinding = getRelationalValueBindings().get( 0 ); + final TableSpecification table = relationalValueBinding.getValue().getTable(); + if ( !Column.class.isInstance( relationalValueBinding.getValue() ) ) { + throw new MappingException( + "Cannot create an IdentifierGenerator because the value is not a column: " + + relationalValueBinding.getValue().toLoggableString() + ); + } + Properties params = new Properties(); params.putAll( properties ); // use the schema/catalog specified by getValue().getTable() - but note that // if the schema/catalog were specified as params, they will already be initialized and //will override the values set here (they are in idGenerator.getParameters().) - Schema schema = getValue().getTable().getSchema(); + Schema schema = table.getSchema(); if ( schema != null ) { if ( schema.getName().getSchema() != null ) { params.setProperty( PersistentIdentifierGenerator.SCHEMA, schema.getName().getSchema().getName() ); @@ -141,57 +134,29 @@ public class BasicAttributeBinding } } - // TODO: not sure how this works for collection IDs... - //pass the entity-name, if not a collection-id - //if ( rootClass!=null) { - params.setProperty( IdentifierGenerator.ENTITY_NAME, getContainer().seekEntityBinding().getEntity().getName() ); - //} + params.setProperty( IdentifierGenerator.ENTITY_NAME, getContainer().seekEntityBinding().getEntity().getName() ); //init the table here instead of earlier, so that we can get a quoted table name //TODO: would it be better to simply pass the qualified table name, instead of // splitting it up into schema/catalog/table names - String tableName = getValue().getTable().getQualifiedName( identifierGeneratorFactory.getDialect() ); + String tableName = table.getQualifiedName( identifierGeneratorFactory.getDialect() ); params.setProperty( PersistentIdentifierGenerator.TABLE, tableName ); - //pass the column name (a generated id almost always has a single column) - if ( getSimpleValueSpan() > 1 ) { - throw new MappingException( - "A SimpleAttributeBinding used for an identifier has more than 1 Value: " + getAttribute().getName() - ); - } - SimpleValue simpleValue = (SimpleValue) getValue(); - if ( !Column.class.isInstance( simpleValue ) ) { - throw new MappingException( - "Cannot create an IdentifierGenerator because the value is not a column: " + - simpleValue.toLoggableString() - ); - } params.setProperty( PersistentIdentifierGenerator.PK, - ( (Column) simpleValue ).getColumnName().encloseInQuotesIfQuoted( + ( (Column) relationalValueBinding.getValue() ).getColumnName().encloseInQuotesIfQuoted( identifierGeneratorFactory.getDialect() ) ); - - // TODO: is this stuff necessary for SimpleValue??? - //if (rootClass!=null) { - // StringBuffer tables = new StringBuffer(); - // Iterator iter = rootClass.getIdentityTables().iterator(); - // while ( iter.hasNext() ) { - // Table table= (Table) iter.next(); - // tables.append( table.getQuotedName(dialect) ); - // if ( iter.hasNext() ) tables.append(", "); - // } - // params.setProperty( PersistentIdentifierGenerator.TABLES, tables.toString() ); - //} - //else { params.setProperty( PersistentIdentifierGenerator.TABLES, tableName ); - //} - params.putAll( idGenerator.getParameters() ); - return identifierGeneratorFactory.createIdentifierGenerator( idGenerator.getStrategy(), getHibernateTypeDescriptor().getResolvedTypeMapping(), params ); } + + @Override + protected void collectRelationalValueBindings(List valueBindings) { + valueBindings.addAll( relationalValueBindings ); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/BasicPluralAttributeElementBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/BasicPluralAttributeElementBinding.java index 4bec64e06a..1f70a61e9d 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/BasicPluralAttributeElementBinding.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/BasicPluralAttributeElementBinding.java @@ -23,13 +23,9 @@ */ package org.hibernate.metamodel.spi.binding; -import java.util.ArrayList; +import java.util.Collections; import java.util.List; -import org.hibernate.metamodel.spi.relational.SimpleValue; -import org.hibernate.metamodel.spi.relational.Tuple; -import org.hibernate.metamodel.spi.relational.Value; - /** * Describes plural attributes of {@link PluralAttributeElementNature#BASIC} elements * @@ -37,8 +33,7 @@ import org.hibernate.metamodel.spi.relational.Value; * @author Gail Badner */ public class BasicPluralAttributeElementBinding extends AbstractPluralAttributeElementBinding { - private Value value; - private List simpleValueBindings = new ArrayList(); + private List relationalValueBindings; private boolean hasDerivedValue; private boolean isNullable = true; @@ -46,29 +41,21 @@ public class BasicPluralAttributeElementBinding extends AbstractPluralAttributeE public BasicPluralAttributeElementBinding(AbstractPluralAttributeBinding binding) { super( binding ); } - + + public List getRelationalValueBindings() { + return relationalValueBindings; + } + @Override public PluralAttributeElementNature getPluralAttributeElementNature() { return PluralAttributeElementNature.BASIC; } - public void setSimpleValueBindings(Iterable simpleValueBindings) { - List values = new ArrayList(); - for ( SimpleValueBinding simpleValueBinding : simpleValueBindings ) { - this.simpleValueBindings.add( simpleValueBinding ); - values.add( simpleValueBinding.getSimpleValue() ); - this.hasDerivedValue = this.hasDerivedValue || simpleValueBinding.isDerived(); - this.isNullable = this.isNullable && simpleValueBinding.isNullable(); - } - if ( values.size() == 1 ) { - this.value = values.get( 0 ); - } - else { - final Tuple tuple = values.get( 0 ).getTable().createTuple( getPluralAttributeBinding().getRole() ); - for ( SimpleValue value : values ) { - tuple.addValue( value ); - } - this.value = tuple; + public void setRelationalValueBindings(List relationalValueBindings) { + this.relationalValueBindings = Collections.unmodifiableList( relationalValueBindings ); + for ( RelationalValueBinding relationalValueBinding : relationalValueBindings ) { + this.hasDerivedValue = this.hasDerivedValue || relationalValueBinding.isDerived(); + this.isNullable = this.isNullable && relationalValueBinding.isNullable(); } } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/ComponentAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/ComponentAttributeBinding.java index 9a39636525..6b1a055f44 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/ComponentAttributeBinding.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/ComponentAttributeBinding.java @@ -23,7 +23,10 @@ */ package org.hibernate.metamodel.spi.binding; +import java.util.ArrayList; +import java.util.Comparator; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.hibernate.mapping.PropertyGeneration; @@ -32,22 +35,55 @@ import org.hibernate.metamodel.spi.domain.Component; import org.hibernate.metamodel.spi.domain.PluralAttribute; import org.hibernate.metamodel.spi.domain.PluralAttributeNature; import org.hibernate.metamodel.spi.domain.SingularAttribute; +import org.hibernate.metamodel.spi.relational.ForeignKey; import org.hibernate.metamodel.spi.source.MetaAttributeContext; /** * @author Steve Ebersole */ -public class ComponentAttributeBinding extends AbstractSingularAttributeBinding implements AttributeBindingContainer { +public class ComponentAttributeBinding + extends AbstractSingularAttributeBinding + implements AttributeBindingContainer { private final String path; + private final SingularAttribute parentReference; private Map attributeBindingMap = new HashMap(); - private SingularAttribute parentReference; - private MetaAttributeContext metaAttributeContext; - public ComponentAttributeBinding(AttributeBindingContainer container, SingularAttribute attribute) { - super( container, attribute ); + public ComponentAttributeBinding( + AttributeBindingContainer container, + SingularAttribute attribute, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + MetaAttributeContext metaAttributeContext, + SingularAttribute parentReference) { + super( + container, + attribute, + propertyAccessorName, + includedInOptimisticLocking, + lazy, + metaAttributeContext + ); + this.parentReference = parentReference; this.path = container.getPathBase() + '.' + attribute.getName(); } + @Override + public List getRelationalValueBindings() { + final List bindings = new ArrayList(); + collectRelationalValueBindings( bindings ); + return bindings; + } + + @Override + protected void collectRelationalValueBindings(List valueBindings) { + for ( AttributeBinding subAttributeBinding : attributeBindings() ) { + if ( AbstractSingularAttributeBinding.class.isInstance( subAttributeBinding ) ) { + ( (AbstractSingularAttributeBinding) subAttributeBinding ).collectRelationalValueBindings( valueBindings ); + } + } + } + @Override public EntityBinding seekEntityBinding() { return getContainer().seekEntityBinding(); @@ -73,12 +109,15 @@ public class ComponentAttributeBinding extends AbstractSingularAttributeBinding } @Override - public MetaAttributeContext getMetaAttributeContext() { - return metaAttributeContext; + public boolean hasDerivedValue() { + // todo : not sure this is even relevant for components + return false; } - public void setMetaAttributeContext(MetaAttributeContext metaAttributeContext) { - this.metaAttributeContext = metaAttributeContext; + @Override + public boolean isNullable() { + // todo : not sure this is even relevant for components + return false; } @Override @@ -92,17 +131,23 @@ public class ComponentAttributeBinding extends AbstractSingularAttributeBinding } @Override - protected void checkValueBinding() { - // do nothing here... - } - - @Override - public BasicAttributeBinding makeBasicAttributeBinding(SingularAttribute attribute) { + public BasicAttributeBinding makeBasicAttributeBinding( + SingularAttribute attribute, + List relationalValueBindings, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + MetaAttributeContext metaAttributeContext, + PropertyGeneration generation) { final BasicAttributeBinding binding = new BasicAttributeBinding( this, attribute, - isNullable(), - isAlternateUniqueKey() // todo : is this accurate? + relationalValueBindings, + propertyAccessorName, + includedInOptimisticLocking, + lazy, + metaAttributeContext, + generation ); registerAttributeBinding( attribute.getName(), binding ); return binding; @@ -114,31 +159,91 @@ public class ComponentAttributeBinding extends AbstractSingularAttributeBinding } @Override - public ComponentAttributeBinding makeComponentAttributeBinding(SingularAttribute attribute) { - final ComponentAttributeBinding binding = new ComponentAttributeBinding( this, attribute ); + public ComponentAttributeBinding makeComponentAttributeBinding( + SingularAttribute attribute, + SingularAttribute parentReferenceAttribute, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + MetaAttributeContext metaAttributeContext) { + final ComponentAttributeBinding binding = new ComponentAttributeBinding( + this, + attribute, + propertyAccessorName, + includedInOptimisticLocking, + lazy, + metaAttributeContext, + parentReferenceAttribute + ); registerAttributeBinding( attribute.getName(), binding ); return binding; } @Override - public ManyToOneAttributeBinding makeManyToOneAttributeBinding(SingularAttribute attribute) { - final ManyToOneAttributeBinding binding = new ManyToOneAttributeBinding( this, attribute ); + public ManyToOneAttributeBinding makeManyToOneAttributeBinding( + SingularAttribute attribute, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + MetaAttributeContext metaAttributeContext, + String referencedEntityName, + String referencedEntityAttributeName, + List valueBindings) { + final ManyToOneAttributeBinding binding = new ManyToOneAttributeBinding( + this, + attribute, + propertyAccessorName, + includedInOptimisticLocking, + lazy, + metaAttributeContext, + valueBindings + ); registerAttributeBinding( attribute.getName(), binding ); return binding; } @Override - public BagBinding makeBagAttributeBinding(PluralAttribute attribute, PluralAttributeElementNature nature) { + public BagBinding makeBagAttributeBinding( + PluralAttribute attribute, + PluralAttributeElementNature nature, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + MetaAttributeContext metaAttributeContext) { Helper.checkPluralAttributeNature( attribute, PluralAttributeNature.BAG ); - final BagBinding binding = new BagBinding( this, attribute, nature ); + final BagBinding binding = new BagBinding( + this, + attribute, + nature, + propertyAccessorName, + includedInOptimisticLocking, + lazy, + metaAttributeContext + ); registerAttributeBinding( attribute.getName(), binding ); return binding; } @Override - public SetBinding makeSetAttributeBinding(PluralAttribute attribute, PluralAttributeElementNature nature) { + public SetBinding makeSetAttributeBinding( + PluralAttribute attribute, + PluralAttributeElementNature nature, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + MetaAttributeContext metaAttributeContext, + Comparator comparator) { Helper.checkPluralAttributeNature( attribute, PluralAttributeNature.SET ); - final SetBinding binding = new SetBinding( this, attribute, nature ); + final SetBinding binding = new SetBinding( + this, + attribute, + nature, + propertyAccessorName, + includedInOptimisticLocking, + lazy, + metaAttributeContext, + comparator + ); registerAttributeBinding( attribute.getName(), binding ); return binding; } @@ -151,14 +256,4 @@ public class ComponentAttributeBinding extends AbstractSingularAttributeBinding public SingularAttribute getParentReference() { return parentReference; } - - public void setParentReference(SingularAttribute parentReference) { - this.parentReference = parentReference; - } - - @Override - public PropertyGeneration getGeneration() { - // todo : not sure the correct thing to return here since it essentially relies on the simple sub-attributes. - return null; - } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityBinding.java index 880992327f..0a154a11a7 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityBinding.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityBinding.java @@ -24,6 +24,7 @@ package org.hibernate.metamodel.spi.binding; import java.util.ArrayList; +import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -35,6 +36,7 @@ import org.hibernate.EntityMode; import org.hibernate.engine.spi.FilterDefinition; import org.hibernate.internal.util.Value; import org.hibernate.internal.util.collections.JoinedIterable; +import org.hibernate.mapping.PropertyGeneration; import org.hibernate.metamodel.spi.domain.AttributeContainer; import org.hibernate.metamodel.spi.domain.Entity; import org.hibernate.metamodel.spi.domain.PluralAttribute; @@ -257,7 +259,7 @@ public class EntityBinding implements AttributeBindingContainer { } public boolean isVersioned() { - return getHierarchyDetails().getVersioningAttributeBinding() != null; + return getHierarchyDetails().getEntityVersion().getVersioningAttributeBinding() != null; } public boolean isDiscriminatorMatchValueNull() { @@ -487,47 +489,114 @@ public class EntityBinding implements AttributeBindingContainer { } @Override - public BasicAttributeBinding makeBasicAttributeBinding(SingularAttribute attribute) { - return makeSimpleAttributeBinding( attribute, false, false ); - } - - private BasicAttributeBinding makeSimpleAttributeBinding(SingularAttribute attribute, boolean forceNonNullable, boolean forceUnique) { + public BasicAttributeBinding makeBasicAttributeBinding( + SingularAttribute attribute, + List relationalValueBindings, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + MetaAttributeContext metaAttributeContext, + PropertyGeneration generation) { final BasicAttributeBinding binding = new BasicAttributeBinding( this, attribute, - forceNonNullable, - forceUnique + relationalValueBindings, + propertyAccessorName, + includedInOptimisticLocking, + lazy, + metaAttributeContext, + generation ); registerAttributeBinding( attribute.getName(), binding ); return binding; } @Override - public ComponentAttributeBinding makeComponentAttributeBinding(SingularAttribute attribute) { - final ComponentAttributeBinding binding = new ComponentAttributeBinding( this, attribute ); + public ComponentAttributeBinding makeComponentAttributeBinding( + SingularAttribute attribute, + SingularAttribute parentReferenceAttribute, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + MetaAttributeContext metaAttributeContext) { + final ComponentAttributeBinding binding = new ComponentAttributeBinding( + this, + attribute, + propertyAccessorName, + includedInOptimisticLocking, + lazy, + metaAttributeContext, + parentReferenceAttribute + ); registerAttributeBinding( attribute.getName(), binding ); return binding; } @Override - public ManyToOneAttributeBinding makeManyToOneAttributeBinding(SingularAttribute attribute) { - final ManyToOneAttributeBinding binding = new ManyToOneAttributeBinding( this, attribute ); + public ManyToOneAttributeBinding makeManyToOneAttributeBinding( + SingularAttribute attribute, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + MetaAttributeContext metaAttributeContext, + String referencedEntityName, + String referencedEntityAttributeName, + List valueBindings) { + final ManyToOneAttributeBinding binding = new ManyToOneAttributeBinding( + this, + attribute, + propertyAccessorName, + includedInOptimisticLocking, + lazy, + metaAttributeContext, + valueBindings + ); registerAttributeBinding( attribute.getName(), binding ); return binding; } @Override - public BagBinding makeBagAttributeBinding(PluralAttribute attribute, PluralAttributeElementNature nature) { + public BagBinding makeBagAttributeBinding( + PluralAttribute attribute, + PluralAttributeElementNature nature, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + MetaAttributeContext metaAttributeContext) { Helper.checkPluralAttributeNature( attribute, PluralAttributeNature.BAG ); - final BagBinding binding = new BagBinding( this, attribute, nature ); + final BagBinding binding = new BagBinding( + this, + attribute, + nature, + propertyAccessorName, + includedInOptimisticLocking, + lazy, + metaAttributeContext + ); registerAttributeBinding( attribute.getName(), binding ); return binding; } @Override - public SetBinding makeSetAttributeBinding(PluralAttribute attribute, PluralAttributeElementNature nature) { + public SetBinding makeSetAttributeBinding( + PluralAttribute attribute, + PluralAttributeElementNature nature, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + MetaAttributeContext metaAttributeContext, + Comparator comparator) { Helper.checkPluralAttributeNature( attribute, PluralAttributeNature.SET ); - final SetBinding binding = new SetBinding( this, attribute, nature ); + final SetBinding binding = new SetBinding( + this, + attribute, + nature, + propertyAccessorName, + includedInOptimisticLocking, + lazy, + metaAttributeContext, + comparator + ); registerAttributeBinding( attribute.getName(), binding ); return binding; } @@ -602,4 +671,5 @@ public class EntityBinding implements AttributeBindingContainer { public Iterable getJpaCallbackClasses() { return jpaCallbackClasses; } + } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityDiscriminator.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityDiscriminator.java index 49271873a4..1b31f064b2 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityDiscriminator.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityDiscriminator.java @@ -23,7 +23,7 @@ */ package org.hibernate.metamodel.spi.binding; -import org.hibernate.metamodel.spi.relational.SimpleValue; +import org.hibernate.metamodel.spi.relational.Value; /** * Binding of the discriminator in a entity hierarchy @@ -34,19 +34,18 @@ import org.hibernate.metamodel.spi.relational.SimpleValue; public class EntityDiscriminator { private final HibernateTypeDescriptor explicitHibernateTypeDescriptor = new HibernateTypeDescriptor(); - private SimpleValue boundValue; - private boolean forced; - private boolean inserted = true; + private final Value relationalValue; + private final boolean inserted; + private final boolean forced; - public EntityDiscriminator() { + public EntityDiscriminator(Value relationalValue, boolean inserted, boolean forced) { + this.relationalValue = relationalValue; + this.inserted = inserted; + this.forced = forced; } - public SimpleValue getBoundValue() { - return boundValue; - } - - public void setBoundValue(SimpleValue boundValue) { - this.boundValue = boundValue; + public Value getRelationalValue() { + return relationalValue; } public HibernateTypeDescriptor getExplicitHibernateTypeDescriptor() { @@ -57,23 +56,15 @@ public class EntityDiscriminator { return forced; } - public void setForced(boolean forced) { - this.forced = forced; - } - public boolean isInserted() { return inserted; } - public void setInserted(boolean inserted) { - this.inserted = inserted; - } - @Override public String toString() { final StringBuilder sb = new StringBuilder(); sb.append( "EntityDiscriminator" ); - sb.append( "{boundValue=" ).append( boundValue ); + sb.append( "{relationalValue=" ).append( relationalValue ); sb.append( ", forced=" ).append( forced ); sb.append( ", inserted=" ).append( inserted ); sb.append( '}' ); 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 aa5623e149..a9048b6dcb 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 @@ -42,6 +42,7 @@ public class EntityIdentifier { private IdGenerator idGenerator; private boolean isIdentifierMapper = false; // todo : mappers, etc + private String unsavedValue; /** * Create an identifier @@ -73,7 +74,7 @@ public class EntityIdentifier { } public boolean isEmbedded() { - return attributeBinding.getSimpleValueSpan() > 1; + return attributeBinding.getRelationalValueBindings().size() > 1; } public boolean isIdentifierMapper() { @@ -92,4 +93,12 @@ public class EntityIdentifier { public IdentifierGenerator getIdentifierGenerator() { return identifierGenerator; } + + public String getUnsavedValue() { + return unsavedValue; + } + + public void setUnsavedValue(String unsavedValue) { + this.unsavedValue = unsavedValue; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityVersion.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityVersion.java new file mode 100644 index 0000000000..afd8203fbd --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityVersion.java @@ -0,0 +1,56 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.binding; + +import org.hibernate.metamodel.spi.source.EntityHierarchy; + +/** + * @author Steve Ebersole + */ +public class EntityVersion { + private final EntityBinding rootEntityBinding; + private BasicAttributeBinding versioningAttributeBinding; + private String unsavedValue; + + public EntityVersion(EntityBinding rootEntityBinding) { + this.rootEntityBinding = rootEntityBinding; + } + + + public BasicAttributeBinding getVersioningAttributeBinding() { + return versioningAttributeBinding; + } + + public void setVersioningAttributeBinding(BasicAttributeBinding versioningAttributeBinding) { + this.versioningAttributeBinding = versioningAttributeBinding; + } + + public String getUnsavedValue() { + return unsavedValue; + } + + public void setUnsavedValue(String unsavedValue) { + this.unsavedValue = unsavedValue; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/HierarchyDetails.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/HierarchyDetails.java index 8658445fbf..2ea970788c 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/HierarchyDetails.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/HierarchyDetails.java @@ -39,7 +39,7 @@ public class HierarchyDetails { private EntityDiscriminator entityDiscriminator; private OptimisticLockStyle optimisticLockStyle; - private BasicAttributeBinding versioningAttributeBinding; + private EntityVersion entityVersion; private Caching caching; @@ -50,6 +50,7 @@ public class HierarchyDetails { this.inheritanceType = inheritanceType; this.entityMode = entityMode; this.entityIdentifier = new EntityIdentifier( rootEntityBinding ); + this.entityVersion = new EntityVersion( rootEntityBinding ); } public EntityBinding getRootEntityBinding() { @@ -84,12 +85,12 @@ public class HierarchyDetails { this.entityDiscriminator = entityDiscriminator; } - public BasicAttributeBinding getVersioningAttributeBinding() { - return versioningAttributeBinding; + public EntityVersion getEntityVersion() { + return entityVersion; } - public void setVersioningAttributeBinding(BasicAttributeBinding versioningAttributeBinding) { - this.versioningAttributeBinding = versioningAttributeBinding; + public void setEntityVersion(EntityVersion entityVersion) { + this.entityVersion = entityVersion; } public Caching getCaching() { diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/ManyToOneAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/ManyToOneAttributeBinding.java index ef64571d9b..980abe1bda 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/ManyToOneAttributeBinding.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/ManyToOneAttributeBinding.java @@ -24,6 +24,7 @@ package org.hibernate.metamodel.spi.binding; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import org.hibernate.AssertionFailure; @@ -32,6 +33,7 @@ import org.hibernate.engine.FetchStyle; import org.hibernate.engine.FetchTiming; import org.hibernate.engine.spi.CascadeStyle; import org.hibernate.metamodel.spi.domain.SingularAttribute; +import org.hibernate.metamodel.spi.source.MetaAttributeContext; /** * TODO : javadoc @@ -39,20 +41,56 @@ import org.hibernate.metamodel.spi.domain.SingularAttribute; * @author Gail Badner * @author Steve Ebersole */ -public class ManyToOneAttributeBinding extends BasicAttributeBinding implements SingularAssociationAttributeBinding { +public class ManyToOneAttributeBinding + extends AbstractSingularAttributeBinding + implements SingularAssociationAttributeBinding { + + private final List relationalValueBindings; + private String referencedEntityName; private String referencedAttributeName; private AttributeBinding referencedAttributeBinding; private boolean isLogicalOneToOne; - private String foreignKeyName; private CascadeStyle cascadeStyle; private FetchTiming fetchTiming; private FetchStyle fetchStyle; - ManyToOneAttributeBinding(AttributeBindingContainer container, SingularAttribute attribute) { - super( container, attribute, false, false ); + public ManyToOneAttributeBinding( + AttributeBindingContainer container, + SingularAttribute attribute, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean lazy, + MetaAttributeContext metaAttributeContext, + List relationalValueBindings) { + super( + container, + attribute, + propertyAccessorName, + includedInOptimisticLocking, + lazy, + metaAttributeContext + ); + this.relationalValueBindings = Collections.unmodifiableList( relationalValueBindings ); + } + + @Override + public List getRelationalValueBindings() { + return relationalValueBindings; + } + + @Override + public boolean hasDerivedValue() { + // todo : not sure this is even relevant for many-to-one + return false; + } + + @Override + public boolean isNullable() { + // todo : not sure this is even relevant for many-to-one + return false; } @Override @@ -237,4 +275,9 @@ public class ManyToOneAttributeBinding extends BasicAttributeBinding implements // } // //TODO: validate that the entity reference is resolved // } + + @Override + protected void collectRelationalValueBindings(List valueBindings) { + valueBindings.addAll( relationalValueBindings ); + } } \ No newline at end of file diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeBinding.java index 949b98fc17..a7c4f584f7 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeBinding.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeBinding.java @@ -63,7 +63,7 @@ public interface PluralAttributeBinding extends AttributeBinding, Fetchable { public Caching getCaching(); - public Class getCollectionPersisterClass(); + public Class getExplicitPersisterClass(); public String getCustomLoaderName(); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeKeyBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeKeyBinding.java index b15c0fa67b..fdcc4bde51 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeKeyBinding.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/PluralAttributeKeyBinding.java @@ -25,7 +25,6 @@ package org.hibernate.metamodel.spi.binding; import org.hibernate.AssertionFailure; import org.hibernate.metamodel.spi.relational.ForeignKey; -import org.hibernate.metamodel.spi.relational.Table; import org.hibernate.metamodel.spi.relational.TableSpecification; /** @@ -99,12 +98,17 @@ public class PluralAttributeKeyBinding { throw new AssertionFailure( "Collection table not yet bound" ); } + if ( foreignKeyName != null ) { + foreignKey = collectionTable.locateForeignKey( foreignKeyName ); + if ( foreignKey != null ) { + return; + } + } + final TableSpecification targetTable = pluralAttributeBinding.getContainer() .seekEntityBinding() .locateTable( targetTableName ); - // todo : handle implicit fk names... - foreignKey = collectionTable.createForeignKey( targetTable, foreignKeyName ); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/SimpleValueBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/RelationalValueBinding.java similarity index 50% rename from hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/SimpleValueBinding.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/RelationalValueBinding.java index 98ccb2fcde..c90016ac10 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/SimpleValueBinding.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/RelationalValueBinding.java @@ -25,60 +25,67 @@ package org.hibernate.metamodel.spi.binding; import org.hibernate.metamodel.spi.relational.Column; import org.hibernate.metamodel.spi.relational.DerivedValue; -import org.hibernate.metamodel.spi.relational.SimpleValue; +import org.hibernate.metamodel.spi.relational.Value; /** + * Represents the binding information of a column/formula. + * + * Different from a {@link Value} because, while the {@link Value} exists only once in the relational model, + * that {@link Value} may be bound to multiple attributes. A {@link RelationalValueBinding} then tracks the + * information that is specific to each attribute's binding to that {@link Value}. + * * @author Steve Ebersole */ -public class SimpleValueBinding { - private SimpleValue simpleValue; +public class RelationalValueBinding { + private final Value value; private boolean includeInInsert; private boolean includeInUpdate; - public SimpleValueBinding() { - this( true, true ); + public RelationalValueBinding(Value value) { + this( value, true, true ); } - public SimpleValueBinding(SimpleValue simpleValue) { - this(); - setSimpleValue( simpleValue ); - } - - public SimpleValueBinding(SimpleValue simpleValue, boolean includeInInsert, boolean includeInUpdate) { - this( includeInInsert, includeInUpdate ); - setSimpleValue( simpleValue ); - } - - public SimpleValueBinding(boolean includeInInsert, boolean includeInUpdate) { - this.includeInInsert = includeInInsert; - this.includeInUpdate = includeInUpdate; - } - - public SimpleValue getSimpleValue() { - return simpleValue; - } - - public void setSimpleValue(SimpleValue simpleValue) { - this.simpleValue = simpleValue; - if ( DerivedValue.class.isInstance( simpleValue ) ) { - includeInInsert = false; - includeInUpdate = false; + public RelationalValueBinding(Value value, boolean includeInInsert, boolean includeInUpdate) { + this.value = value; + if ( DerivedValue.class.isInstance( value ) ) { + this.includeInInsert = false; + this.includeInUpdate = false; + } + else { + this.includeInInsert = includeInInsert; + this.includeInUpdate = includeInUpdate; } } - public boolean isDerived() { - return DerivedValue.class.isInstance( simpleValue ); + /** + * Retrieve the relational value bound here. + * + * @return The relational value. + */ + public Value getValue() { + return value; } + /** + * Is the value bound here derived? Same as checking {@link #getValue()} as a {@link DerivedValue} + * + * @return {@code true} indicates the bound value is derived. + */ + public boolean isDerived() { + return DerivedValue.class.isInstance( value ); + } + + /** + * Is the value bound here nullable? + * + * @return {@code true} indicates the bound value is derived or a column not marked as non-null. + */ public boolean isNullable() { - return isDerived() || Column.class.cast( simpleValue ).isNullable(); + return isDerived() || Column.class.cast( value ).isNullable(); } /** * Is the value to be inserted as part of its binding here? - *

- * NOTE that a column may be bound to multiple attributes. The purpose of this value is to track this - * notion of "insertability" for this particular binding. * * @return {@code true} indicates the value should be included; {@code false} indicates it should not */ @@ -86,15 +93,12 @@ public class SimpleValueBinding { return includeInInsert; } - public void setIncludeInInsert(boolean includeInInsert) { - this.includeInInsert = includeInInsert; - } - + /** + * Is the value to be updated as part of its binding here? + * + * @return {@code true} indicates the value should be included; {@code false} indicates it should not + */ public boolean isIncludeInUpdate() { return includeInUpdate; } - - public void setIncludeInUpdate(boolean includeInUpdate) { - this.includeInUpdate = includeInUpdate; - } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/SetBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/SetBinding.java index 4ec75ae3f6..c83357b388 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/SetBinding.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/SetBinding.java @@ -26,25 +26,36 @@ package org.hibernate.metamodel.spi.binding; import java.util.Comparator; import org.hibernate.metamodel.spi.domain.PluralAttribute; +import org.hibernate.metamodel.spi.source.MetaAttributeContext; /** * @author Steve Ebersole */ public class SetBinding extends AbstractPluralAttributeBinding { - private Comparator comparator; + private final Comparator comparator; - protected SetBinding( + public SetBinding( AttributeBindingContainer container, PluralAttribute attribute, - PluralAttributeElementNature pluralAttributeElementNature) { - super( container, attribute, pluralAttributeElementNature ); + PluralAttributeElementNature pluralAttributeElementNature, + String propertyAccessorName, + boolean includedInOptimisticLocking, + boolean isLazy, + MetaAttributeContext metaAttributeContext, + Comparator comparator) { + super( + container, + attribute, + pluralAttributeElementNature, + propertyAccessorName, + includedInOptimisticLocking, + isLazy, + metaAttributeContext + ); + this.comparator = comparator; } public Comparator getComparator() { return comparator; } - - public void setComparator(Comparator comparator) { - this.comparator = comparator; - } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/SingularAttributeBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/SingularAttributeBinding.java index a56e058fe9..bb943a26fc 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/SingularAttributeBinding.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/SingularAttributeBinding.java @@ -23,8 +23,10 @@ */ package org.hibernate.metamodel.spi.binding; +import java.util.List; + import org.hibernate.mapping.PropertyGeneration; -import org.hibernate.metamodel.spi.relational.Value; +import org.hibernate.metamodel.spi.domain.SingularAttribute; /** * Specialized binding contract for singular (non-collection) attributes @@ -32,33 +34,14 @@ import org.hibernate.metamodel.spi.relational.Value; * @author Steve Ebersole */ public interface SingularAttributeBinding extends AttributeBinding { - /** - * Obtain the value bound here. This could potentially be a {@link org.hibernate.metamodel.spi.relational.Tuple} - * indicating multiple database values are bound, in which case access to the individual values can be achieved by - * either casting this return to {@link org.hibernate.metamodel.spi.relational.Tuple} and using its - * {@link org.hibernate.metamodel.spi.relational.Tuple#values()} method or using the {@link #getSimpleValueBindings()} - * method here and accessing each bindings {@link SimpleValueBinding#getSimpleValue simple value} - * - * @return The bound value - */ - public Value getValue(); + + @Override + public SingularAttribute getAttribute(); + + public List getRelationalValueBindings(); /** - * Returns the number of {@link SimpleValueBinding} objects that will be returned by - * {@link #getSimpleValueBindings()} - * - * @return the number of {@link SimpleValueBinding simple value bindings} - * - * @see #getSimpleValueBindings() - */ - public int getSimpleValueSpan(); - - public Iterable getSimpleValueBindings(); - - public void setSimpleValueBindings(Iterable simpleValueBindings); - - /** - * Convenience method to determine if any {@link SimpleValueBinding simple value bindings} are derived values + * Convenience method to determine if any {@link RelationalValueBinding simple value bindings} are derived values * (formula mappings). * * @return {@code true} indicates that the binding contains a derived value; {@code false} indicates it does not. @@ -66,16 +49,9 @@ public interface SingularAttributeBinding extends AttributeBinding { public boolean hasDerivedValue(); /** - * Convenience method to determine if all {@link SimpleValueBinding simple value bindings} allow nulls. + * Convenience method to determine if all {@link RelationalValueBinding simple value bindings} allow nulls. * * @return {@code true} indicates that all values allow {@code null}; {@code false} indicates one or more do not */ public boolean isNullable(); - - /** - * Obtain the generation strategy for this attribute/value. - * - * @return The generation strategy - */ - public PropertyGeneration getGeneration(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AbstractConstraint.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AbstractConstraint.java index 128aef6330..866df1ef05 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AbstractConstraint.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AbstractConstraint.java @@ -59,7 +59,7 @@ public abstract class AbstractConstraint implements Constraint { return columns; } - protected int getColumnSpan() { + public int getColumnSpan() { return columns.size(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AbstractTableSpecification.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AbstractTableSpecification.java index b162a5e4ff..d9dd89ba45 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AbstractTableSpecification.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AbstractTableSpecification.java @@ -24,6 +24,7 @@ package org.hibernate.metamodel.spi.relational; import java.util.ArrayList; +import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; @@ -38,7 +39,8 @@ public abstract class AbstractTableSpecification implements TableSpecification { private final static AtomicInteger tableCounter = new AtomicInteger( 0 ); private final int tableNumber; - private final LinkedHashMap values = new LinkedHashMap(); + private final List valueList = new ArrayList(); + private final LinkedHashMap valueMap = new LinkedHashMap(); private final PrimaryKey primaryKey = new PrimaryKey( this ); private final List foreignKeys = new ArrayList(); @@ -53,33 +55,38 @@ public abstract class AbstractTableSpecification implements TableSpecification { } @Override - public Iterable values() { - return values.values(); + public List values() { + return Collections.unmodifiableList( valueList ); } @Override public Column locateOrCreateColumn(String name) { - if ( values.containsKey( name ) ) { - return (Column) values.get( name ); + if ( valueMap.containsKey( name ) ) { + return (Column) valueMap.get( name ); } - final Column column = new Column( this, values.size(), name ); - values.put( name, column ); + final Column column = new Column( this, valueList.size(), name ); + valueMap.put( name, column ); + valueList.add( column ); return column; } @Override - public DerivedValue locateOrCreateDerivedValue(String fragment) { - if ( values.containsKey( fragment ) ) { - return (DerivedValue) values.get( fragment ); + public Column locateColumn(String name) { + if ( valueMap.containsKey( name ) ) { + return (Column) valueMap.get( name ); } - final DerivedValue value = new DerivedValue( this, values.size(), fragment ); - values.put( fragment, value ); - return value; + return null; } @Override - public Tuple createTuple(String name) { - return new Tuple( this, name ); + public DerivedValue locateOrCreateDerivedValue(String fragment) { + if ( valueMap.containsKey( fragment ) ) { + return (DerivedValue) valueMap.get( fragment ); + } + final DerivedValue value = new DerivedValue( this, valueList.size(), fragment ); + valueMap.put( fragment, value ); + valueList.add( value ); + return value; } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AbstractSimpleValue.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AbstractValue.java similarity index 60% rename from hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AbstractSimpleValue.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AbstractValue.java index bf2d7fb72d..07059e0549 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AbstractSimpleValue.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/AbstractValue.java @@ -1,10 +1,10 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * Copyright (c) 2010 by Red Hat Inc and/or its affiliates or by - * third-party contributors as indicated by either @author tags or express - * copyright attribution statements applied by the authors. All - * third-party contributions are distributed under license by Red Hat Inc. + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. * * This copyrighted material is made available to anyone wishing to use, modify, * copy, or redistribute it subject to the terms and conditions of the GNU @@ -29,19 +29,19 @@ import org.hibernate.internal.CoreMessageLogger; import org.hibernate.metamodel.ValidationException; /** - * Basic support for {@link SimpleValue} implementations. + * Basic support for {@link Value} implementations. * * @author Steve Ebersole */ -public abstract class AbstractSimpleValue implements SimpleValue { +public abstract class AbstractValue implements Value { - private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, AbstractSimpleValue.class.getName()); + private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, AbstractValue.class.getName()); private final TableSpecification table; private final int position; - private Datatype datatype; + private JdbcDataType jdbcDataType; - protected AbstractSimpleValue(TableSpecification table, int position) { + protected AbstractValue(TableSpecification table, int position) { this.table = table; this.position = position; } @@ -56,23 +56,22 @@ public abstract class AbstractSimpleValue implements SimpleValue { } @Override - public Datatype getDatatype() { - return datatype; + public JdbcDataType getJdbcDataType() { + return jdbcDataType; } - @Override - public void setDatatype(Datatype datatype) { - LOG.debugf( "setting datatype for column %s : %s", toLoggableString(), datatype ); - if ( this.datatype != null && ! this.datatype.equals( datatype ) ) { - LOG.debugf( "overriding previous datatype : %s", this.datatype ); + public void setJdbcDataType(JdbcDataType jdbcDataType) { + LOG.debugf( "setting jdbcDataType for column %s : %s", toLoggableString(), jdbcDataType ); + if ( this.jdbcDataType != null && ! this.jdbcDataType.equals( jdbcDataType ) ) { + LOG.debugf( "overriding previous jdbcDataType : %s", this.jdbcDataType ); } - this.datatype = datatype; + this.jdbcDataType = jdbcDataType; } @Override public void validateJdbcTypes(JdbcCodes typeCodes) { // todo : better compatibility testing... - if ( datatype.getTypeCode() != typeCodes.nextJdbcCde() ) { + if ( jdbcDataType.getTypeCode() != typeCodes.nextJdbcCde() ) { throw new ValidationException( "Mismatched types" ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Column.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Column.java index 933a052495..f648004687 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Column.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Column.java @@ -34,7 +34,7 @@ import org.hibernate.metamodel.spi.relational.state.ColumnRelationalState; * @author Gavin King * @author Steve Ebersole */ -public class Column extends AbstractSimpleValue { +public class Column extends AbstractValue { private final Identifier columnName; private boolean nullable; private boolean unique; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/DerivedValue.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/DerivedValue.java index 25ffe59258..38262355b4 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/DerivedValue.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/DerivedValue.java @@ -30,7 +30,7 @@ import org.hibernate.dialect.Dialect; * * @author Steve Ebersole */ -public class DerivedValue extends AbstractSimpleValue { +public class DerivedValue extends AbstractValue { private final String expression; public DerivedValue(TableSpecification table, int position, String expression) { diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Datatype.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/JdbcDataType.java similarity index 69% rename from hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Datatype.java rename to hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/JdbcDataType.java index 62c97820aa..7421fe9f82 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Datatype.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/JdbcDataType.java @@ -24,26 +24,34 @@ package org.hibernate.metamodel.spi.relational; /** - * Models a JDBC {@link java.sql.Types DATATYPE} + * Models a JDBC {@link java.sql.Types DATATYPE}. Mainly breaks down into 3 pieces of information:

    + *
  • + * {@link #getTypeCode() type code} - The JDBC type code; generally matches a code from {@link java.sql.Types} + * though not necessarily. + *
  • + *
  • + * {@link #getTypeName() type name} - The database type name for the given type code. + *
  • + *
  • + * {@link #getJavaType()} java type} - The java type recommended for representing this JDBC type (if known) + *
  • + *
* - * @todo Do we somehow link this in with {@link org.hibernate.internal.util.jdbc.TypeInfo} ? + * @todo Would love to link this in with {@link org.hibernate.engine.jdbc.internal.TypeInfo} * * @author Steve Ebersole */ -public class Datatype { +public class JdbcDataType { private final int typeCode; private final String typeName; private final Class javaType; private final int hashCode; - public Datatype(int typeCode, String typeName, Class javaType) { + public JdbcDataType(int typeCode, String typeName, Class javaType) { this.typeCode = typeCode; this.typeName = typeName; this.javaType = javaType; - this.hashCode = generateHashCode(); - } - private int generateHashCode() { int result = typeCode; if ( typeName != null ) { result = 31 * result + typeName.hashCode(); @@ -51,8 +59,8 @@ public class Datatype { if ( javaType != null ) { result = 31 * result + javaType.hashCode(); } - return result; - } + this.hashCode = result; + } public int getTypeCode() { return typeCode; @@ -66,6 +74,11 @@ public class Datatype { return javaType; } + @Override + public int hashCode() { + return hashCode; + } + @Override public boolean equals(Object o) { if ( this == o ) { @@ -75,19 +88,14 @@ public class Datatype { return false; } - Datatype datatype = (Datatype) o; + JdbcDataType jdbcDataType = (JdbcDataType) o; - return typeCode == datatype.typeCode - && javaType.equals( datatype.javaType ) - && typeName.equals( datatype.typeName ); + return typeCode == jdbcDataType.typeCode + && javaType.equals( jdbcDataType.javaType ) + && typeName.equals( jdbcDataType.typeName ); } - @Override - public int hashCode() { - return hashCode; - } - @Override public String toString() { return super.toString() + "[code=" + typeCode + ", name=" + typeName + ", javaClass=" + javaType.getName() + "]"; diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/SimpleValue.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/SimpleValue.java deleted file mode 100644 index e64870037f..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/SimpleValue.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010 by Red Hat Inc and/or its affiliates or by - * third-party contributors as indicated by either @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.spi.relational; - -import org.hibernate.dialect.Dialect; - -/** - * Models a simple, non-compound value. - * - * @author Steve Ebersole - */ -public interface SimpleValue extends Value { - /** - * Retrieve the datatype of this value. - * - * @return The value's datatype - */ - public Datatype getDatatype(); - - /** - * Set the datatype of this value. - * - * @param datatype The value's datatype - */ - public void setDatatype(Datatype datatype); - - /** - * For any column name, generate an alias that is unique - * to that column name, unique across tables, and within - * alias size constraints determined by - * {@link org.hibernate.dialect.Dialect#getMaxAliasLength()}. - * - * @param dialect the dialect. - * @return the alias. - */ - public String getAlias(Dialect dialect); -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Table.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Table.java index 07044f809a..41ac427b9a 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Table.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Table.java @@ -162,7 +162,7 @@ public class Table extends AbstractTableSpecification implements Exportable { } boolean isFirst = true; - for ( SimpleValue simpleValue : values() ) { + for ( Value simpleValue : values() ) { if ( ! Column.class.isInstance( simpleValue ) ) { continue; } @@ -183,7 +183,7 @@ public class Table extends AbstractTableSpecification implements Exportable { buf.append( getTypeString( col, dialect ) ); } buf.append( ' ' ) - .append( dialect.getIdentityColumnString( col.getDatatype().getTypeCode() ) ); + .append( dialect.getIdentityColumnString( col.getJdbcDataType().getTypeCode() ) ); } else { buf.append( getTypeString( col, dialect ) ); @@ -271,7 +271,7 @@ public class Table extends AbstractTableSpecification implements Exportable { col.getSize(); typeString = dialect.getTypeName( - col.getDatatype().getTypeCode(), + col.getJdbcDataType().getTypeCode(), size.getLength(), size.getPrecision(), size.getScale() diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/TableSpecification.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/TableSpecification.java index cd9bc70759..2e17804b02 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/TableSpecification.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/TableSpecification.java @@ -62,13 +62,13 @@ public interface TableSpecification extends ValueContainer, Loggable { public Column locateOrCreateColumn(String name); /** - * Factory method for creating a {@link Column} associated with this container. + * Attempt to locate a column with the given name * * @param name The column name * - * @return The generated column + * @return The located column, or {@code null} is none found */ - public Tuple createTuple(String name); + public Column locateColumn(String name); /** * Factory method for creating a {@link DerivedValue} associated with this container. diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Tuple.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Tuple.java deleted file mode 100644 index fe36169a8e..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Tuple.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2010 by Red Hat Inc and/or its affiliates or by - * third-party contributors as indicated by either @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.spi.relational; - -import java.util.LinkedHashSet; - -/** - * Models a compound value (a tuple or row-value-constructor is SQL terms). It is both a {@link Value} and - * a {@link ValueContainer} simultaneously. - *

- * IMPL NOTE : in terms of the tables themselves, SQL has no notion of a tuple/compound-value. We simply model - * it this way because: - *

    - *
  • it is a cleaner mapping to the logical model
  • - *
  • it allows more meaningful traversals from simple values back up to table through any intermediate tuples - * because it gives us a better understanding of the model.
  • - *
  • it better conveys intent
  • - *
  • it adds richness to the model
  • - *
- * - * @author Steve Ebersole - */ -public class Tuple implements Value, ValueContainer, Loggable { - private final TableSpecification table; - private final String name; - private final LinkedHashSet values = new LinkedHashSet(); - - public Tuple(TableSpecification table, String name) { - this.table = table; - this.name = name; - } - - @Override - public TableSpecification getTable() { - return table; - } - - public int valuesSpan() { - return values.size(); - } - - @Override - public Iterable values() { - return values; - } - - public void addValue(SimpleValue value) { - if ( ! value.getTable().equals( getTable() ) ) { - throw new IllegalArgumentException( "Tuple can only group values from same table" ); - } - values.add( value ); - } - - @Override - public String getLoggableValueQualifier() { - return getTable().getLoggableValueQualifier() + '.' + name + "{tuple}"; - } - - @Override - public String toLoggableString() { - return getLoggableValueQualifier(); - } - - @Override - public void validateJdbcTypes(JdbcCodes typeCodes) { - for ( Value value : values() ) { - value.validateJdbcTypes( typeCodes ); - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Value.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Value.java index 815bb9ea62..159fc9219b 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Value.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Value.java @@ -23,9 +23,11 @@ */ package org.hibernate.metamodel.spi.relational; +import org.hibernate.dialect.Dialect; + /** - * Models a value within a {@link ValueContainer}. This will generally be either a {@link Column column} or a - * {@link DerivedValue derived value}, but we also allow the notion of {@link Tuple} at this level + * Models a value within a {@link ValueContainer}. Concretely, either a {@link Column column} or a + * {@link DerivedValue derived value}. * * @author Steve Ebersole */ @@ -37,6 +39,13 @@ public interface Value { */ public TableSpecification getTable(); + /** + * Retrieve the JDBC data type of this value. + * + * @return The value's JDBC data type + */ + public JdbcDataType getJdbcDataType(); + /** * Obtain the string representation of this value usable in log statements. * @@ -44,6 +53,29 @@ public interface Value { */ public String toLoggableString(); + /** + * For any column name, generate an alias that is unique + * to that column name, unique across tables, and within + * alias size constraints determined by + * {@link org.hibernate.dialect.Dialect#getMaxAliasLength()}. + * + * todo : not sure this contract is the best place for this method + * + * @param dialect the dialect. + * @return the alias. + */ + public String getAlias(Dialect dialect); + + /** + * Validate the value against the incoming JDBC type code array, both in terms of number of types + * and compatibility of types. + * + * @param typeCodes The type codes. + * + * @throws org.hibernate.metamodel.ValidationException if validaton fails. + */ + public void validateJdbcTypes(JdbcCodes typeCodes); + /** * Used to track JDBC type usage throughout a series of potential recursive calls to component * values since we do not know ahead of time which values correspond to which indexes of the @@ -66,14 +98,4 @@ public interface Value { } } - /** - * Validate the value against the incoming JDBC type code array, both in terms of number of types - * and compatibility of types. - * - * @param typeCodes The type codes. - * - * @throws org.hibernate.metamodel.ValidationException if validaton fails. - */ - public void validateJdbcTypes(JdbcCodes typeCodes); - } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/ValueContainer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/ValueContainer.java index f62ba1cd47..0fc5473d5d 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/ValueContainer.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/ValueContainer.java @@ -23,20 +23,23 @@ */ package org.hibernate.metamodel.spi.relational; +import java.util.List; + /** * Contract for data containers (what the ANSI SQL spec calls "table specifications") to which we can map - * entity state. The two flavors here are {@link Table physical table} and {@link InLineView inline view}, but a - * {@link Tuple} is a conceptual value container as well. + * entity state. The two flavors here are {@link Table physical table} and {@link InLineView inline view}. * * @author Steve Ebersole */ public interface ValueContainer { /** * Obtain an iterator over this containers current set of value definitions. + *

+ * The returned list is unmodifiable! * * @return Iterator over value definitions. */ - public Iterable values(); + public List values(); /** * Get a qualifier which can be used to qualify {@link Value values} belonging to this container in diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/ColumnSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/ColumnSource.java index 9728a91f83..a860c478af 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/ColumnSource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/ColumnSource.java @@ -24,7 +24,7 @@ package org.hibernate.metamodel.spi.source; import org.hibernate.TruthValue; -import org.hibernate.metamodel.spi.relational.Datatype; +import org.hibernate.metamodel.spi.relational.JdbcDataType; import org.hibernate.metamodel.spi.relational.Size; /** @@ -85,7 +85,7 @@ public interface ColumnSource extends RelationalValueSource { * * @return The column's SQL data type. */ - public Datatype getDatatype(); + public JdbcDataType getDatatype(); /** * Obtain the specified column size. diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/RootEntitySource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/RootEntitySource.java index dcf04b4c2b..331f48b726 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/RootEntitySource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/RootEntitySource.java @@ -50,7 +50,7 @@ public interface RootEntitySource extends EntitySource { * * @return the source information about the attribute used for versioning */ - public SingularAttributeSource getVersioningAttributeSource(); + public VersionAttributeSource getVersioningAttributeSource(); /** * Obtain the source information about the discriminator attribute for single table inheritance diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/SingularAttributeSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/SingularAttributeSource.java index c98a67bcdc..cbb61a2e4a 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/SingularAttributeSource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/SingularAttributeSource.java @@ -23,7 +23,6 @@ */ package org.hibernate.metamodel.spi.source; -import org.hibernate.TruthValue; import org.hibernate.mapping.PropertyGeneration; /** diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/ToOneAttributeSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/ToOneAttributeSource.java index 0a90969928..a3488f5133 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/ToOneAttributeSource.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/ToOneAttributeSource.java @@ -45,4 +45,11 @@ public interface ToOneAttributeSource * @return The name of the referenced attribute; {@code null} indicates the identifier attribute. */ public String getReferencedEntityAttributeName(); + + /** + * Retrieve the name of the foreign key as supplied by the user, or {@code null} if the user supplied none. + * + * @return The user supplied foreign key name. + */ + public String getForeignKeyName(); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/VersionAttributeSource.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/VersionAttributeSource.java new file mode 100644 index 0000000000..a7c5fbce66 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/source/VersionAttributeSource.java @@ -0,0 +1,31 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.metamodel.spi.source; + +/** + * @author Steve Ebersole + */ +public interface VersionAttributeSource extends SingularAttributeSource { + public String getUnsavedValue(); +} diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java index ba158eec94..d7878e12d7 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java @@ -96,8 +96,9 @@ import org.hibernate.mapping.Property; import org.hibernate.mapping.Selectable; import org.hibernate.metadata.ClassMetadata; import org.hibernate.metamodel.spi.binding.AttributeBinding; +import org.hibernate.metamodel.spi.binding.BasicAttributeBinding; import org.hibernate.metamodel.spi.binding.EntityBinding; -import org.hibernate.metamodel.spi.binding.SimpleValueBinding; +import org.hibernate.metamodel.spi.binding.RelationalValueBinding; import org.hibernate.metamodel.spi.binding.SingularAssociationAttributeBinding; import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; import org.hibernate.metamodel.spi.relational.DerivedValue; @@ -795,7 +796,11 @@ public abstract class AbstractEntityPersister // IDENTIFIER - identifierColumnSpan = entityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding().getSimpleValueSpan(); + identifierColumnSpan = entityBinding.getHierarchyDetails() + .getEntityIdentifier() + .getValueBinding() + .getRelationalValueBindings() + .size(); rootTableKeyColumnNames = new String[identifierColumnSpan]; rootTableKeyColumnReaders = new String[identifierColumnSpan]; rootTableKeyColumnReaderTemplates = new String[identifierColumnSpan]; @@ -823,9 +828,20 @@ public abstract class AbstractEntityPersister // VERSION if ( entityBinding.isVersioned() ) { - final Value versioningValue = entityBinding.getHierarchyDetails().getVersioningAttributeBinding().getValue(); + final BasicAttributeBinding versionAttributeBinding = entityBinding.getHierarchyDetails() + .getEntityVersion() + .getVersioningAttributeBinding(); + if ( versionAttributeBinding.getRelationalValueBindings().size() > 1 ) { + throw new AssertionFailure( + "Bad versioning attribute binding, expecting single column but found " + + versionAttributeBinding.getRelationalValueBindings().size() + ); + } + final Value versioningValue = versionAttributeBinding.getRelationalValueBindings().get( 0 ).getValue(); if ( ! org.hibernate.metamodel.spi.relational.Column.class.isInstance( versioningValue ) ) { - throw new AssertionFailure( "Bad versioning attribute binding : " + versioningValue ); + throw new AssertionFailure( + "Bad versioning attribute binding, expecting column but found [" + versioningValue + "]" + ); } org.hibernate.metamodel.spi.relational.Column versionColumn = org.hibernate.metamodel.spi.relational.Column.class.cast( versioningValue ); versionColumnName = versionColumn.getColumnName().encloseInQuotesIfQuoted( factory.getDialect() ); @@ -882,7 +898,7 @@ public abstract class AbstractEntityPersister propertySubclassNames[i] = ( (EntityBinding) singularAttributeBinding.getContainer() ).getEntity().getName(); - int span = singularAttributeBinding.getSimpleValueSpan(); + int span = singularAttributeBinding.getRelationalValueBindings().size(); propertyColumnSpans[i] = span; String[] colNames = new String[span]; @@ -895,14 +911,14 @@ public abstract class AbstractEntityPersister int k = 0; - for ( SimpleValueBinding valueBinding : singularAttributeBinding.getSimpleValueBindings() ) { - colAliases[k] = valueBinding.getSimpleValue().getAlias( factory.getDialect() ); + for ( RelationalValueBinding valueBinding : singularAttributeBinding.getRelationalValueBindings() ) { + colAliases[k] = valueBinding.getValue().getAlias( factory.getDialect() ); if ( valueBinding.isDerived() ) { foundFormula = true; - formulaTemplates[ k ] = getTemplateFromString( ( (DerivedValue) valueBinding.getSimpleValue() ).getExpression(), factory ); + formulaTemplates[ k ] = getTemplateFromString( ( (DerivedValue) valueBinding.getValue() ).getExpression(), factory ); } else { - org.hibernate.metamodel.spi.relational.Column col = (org.hibernate.metamodel.spi.relational.Column) valueBinding.getSimpleValue(); + org.hibernate.metamodel.spi.relational.Column col = (org.hibernate.metamodel.spi.relational.Column) valueBinding.getValue(); colNames[k] = col.getColumnName().encloseInQuotesIfQuoted( factory.getDialect() ); colReaderTemplates[k] = getTemplateFromColumn( col, factory ); colWriters[k] = col.getWriteFragment() == null ? "?" : col.getWriteFragment(); @@ -989,7 +1005,7 @@ public abstract class AbstractEntityPersister propNullables.add( singularAttributeBinding.isNullable() || isDefinedBySubclass ); //TODO: is this completely correct? types.add( singularAttributeBinding.getHibernateTypeDescriptor().getResolvedTypeMapping() ); - final int span = singularAttributeBinding.getSimpleValueSpan(); + final int span = singularAttributeBinding.getRelationalValueBindings().size(); String[] cols = new String[ span ]; String[] readers = new String[ span ]; String[] readerTemplates = new String[ span ]; @@ -998,9 +1014,9 @@ public abstract class AbstractEntityPersister int[] formnos = new int[ span ]; int l = 0; Boolean lazy = singularAttributeBinding.isLazy() && lazyAvailable; - for ( SimpleValueBinding valueBinding : singularAttributeBinding.getSimpleValueBindings() ) { + for ( RelationalValueBinding valueBinding : singularAttributeBinding.getRelationalValueBindings() ) { if ( valueBinding.isDerived() ) { - DerivedValue derivedValue = DerivedValue.class.cast( valueBinding.getSimpleValue() ); + DerivedValue derivedValue = DerivedValue.class.cast( valueBinding.getValue() ); String template = getTemplateFromString( derivedValue.getExpression(), factory ); formnos[l] = formulaTemplates.size(); colnos[l] = -1; @@ -1011,7 +1027,7 @@ public abstract class AbstractEntityPersister formulasLazy.add( lazy ); } else { - org.hibernate.metamodel.spi.relational.Column col = org.hibernate.metamodel.spi.relational.Column.class.cast( valueBinding.getSimpleValue() ); + org.hibernate.metamodel.spi.relational.Column col = org.hibernate.metamodel.spi.relational.Column.class.cast( valueBinding.getValue() ); String colName = col.getColumnName().encloseInQuotesIfQuoted( factory.getDialect() ); colnos[l] = columns.size(); //before add :-) formnos[l] = -1; diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java index 23aed0faea..ee6339035c 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java @@ -50,10 +50,9 @@ import org.hibernate.mapping.Value; import org.hibernate.metamodel.spi.binding.AttributeBinding; import org.hibernate.metamodel.spi.binding.CustomSQL; import org.hibernate.metamodel.spi.binding.EntityBinding; -import org.hibernate.metamodel.spi.binding.SimpleValueBinding; +import org.hibernate.metamodel.spi.binding.RelationalValueBinding; import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; import org.hibernate.metamodel.spi.relational.DerivedValue; -import org.hibernate.metamodel.spi.relational.SimpleValue; import org.hibernate.metamodel.spi.relational.TableSpecification; import org.hibernate.sql.InFragment; import org.hibernate.sql.Insert; @@ -537,7 +536,7 @@ public class SingleTableEntityPersister extends AbstractEntityPersister { // DISCRIMINATOR if ( entityBinding.isPolymorphic() ) { - SimpleValue discriminatorRelationalValue = entityBinding.getHierarchyDetails().getEntityDiscriminator().getBoundValue(); + org.hibernate.metamodel.spi.relational.Value discriminatorRelationalValue = entityBinding.getHierarchyDetails().getEntityDiscriminator().getRelationalValue(); if ( discriminatorRelationalValue == null ) { throw new MappingException("discriminator mapping required for single table polymorphic persistence"); } @@ -652,8 +651,8 @@ public class SingleTableEntityPersister extends AbstractEntityPersister { join ); - for ( SimpleValueBinding simpleValueBinding : singularAttributeBinding.getSimpleValueBindings() ) { - if ( DerivedValue.class.isInstance( simpleValueBinding.getSimpleValue() ) ) { + for ( RelationalValueBinding relationalValueBinding : singularAttributeBinding.getRelationalValueBindings() ) { + if ( DerivedValue.class.isInstance( relationalValueBinding.getValue() ) ) { formulaJoinedNumbers.add( join ); } else { diff --git a/hibernate-core/src/main/java/org/hibernate/persister/internal/PersisterFactoryImpl.java b/hibernate-core/src/main/java/org/hibernate/persister/internal/PersisterFactoryImpl.java index 10e72eabb7..bc2ba73eed 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/internal/PersisterFactoryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/internal/PersisterFactoryImpl.java @@ -203,7 +203,7 @@ public final class PersisterFactoryImpl implements PersisterFactory, ServiceRegi PluralAttributeBinding collectionMetadata, CollectionRegionAccessStrategy cacheAccessStrategy, SessionFactoryImplementor factory) throws HibernateException { - Class persisterClass = collectionMetadata.getCollectionPersisterClass(); + Class persisterClass = collectionMetadata.getExplicitPersisterClass(); if ( persisterClass == null ) { persisterClass = serviceRegistry.getService( PersisterClassResolver.class ).getCollectionPersisterClass( collectionMetadata ); } diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/PropertyFactory.java b/hibernate-core/src/main/java/org/hibernate/tuple/PropertyFactory.java index f996b9a532..77f96a25d2 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/PropertyFactory.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/PropertyFactory.java @@ -42,7 +42,7 @@ import org.hibernate.metamodel.spi.binding.AttributeBinding; import org.hibernate.metamodel.spi.binding.BasicAttributeBinding; import org.hibernate.metamodel.spi.binding.EntityBinding; import org.hibernate.metamodel.spi.binding.PluralAttributeAssociationElementBinding; -import org.hibernate.metamodel.spi.binding.SimpleValueBinding; +import org.hibernate.metamodel.spi.binding.RelationalValueBinding; import org.hibernate.metamodel.spi.binding.SingularAssociationAttributeBinding; import org.hibernate.metamodel.spi.binding.SingularAttributeBinding; import org.hibernate.property.Getter; @@ -117,7 +117,7 @@ public class PropertyFactory { // (steve) virtual attributes will still be attributes, they will simply be marked as virtual. // see org.hibernate.metamodel.domain.AbstractAttributeContainer.locateOrCreateVirtualAttribute() - final String mappedUnsavedValue = property.getUnsavedValue(); + final String mappedUnsavedValue = mappedEntity.getHierarchyDetails().getEntityIdentifier().getUnsavedValue(); final Type type = property.getHibernateTypeDescriptor().getResolvedTypeMapping(); IdentifierValue unsavedValue = UnsavedValueFactory.getUnsavedIdentifierValue( @@ -194,10 +194,12 @@ public class PropertyFactory { * @param lazyAvailable Is property lazy loading currently available. * @return The appropriate VersionProperty definition. */ - public static VersionProperty buildVersionProperty(BasicAttributeBinding property, boolean lazyAvailable) { - String mappedUnsavedValue = ( (KeyValue) property.getValue() ).getNullValue(); - - VersionValue unsavedValue = UnsavedValueFactory.getUnsavedVersionValue( + public static VersionProperty buildVersionProperty( + EntityBinding entityBinding, + BasicAttributeBinding property, + boolean lazyAvailable) { + final String mappedUnsavedValue = entityBinding.getHierarchyDetails().getEntityVersion().getUnsavedValue(); + final VersionValue unsavedValue = UnsavedValueFactory.getUnsavedVersionValue( mappedUnsavedValue, getGetter( property ), (VersionType) property.getHibernateTypeDescriptor().getResolvedTypeMapping(), @@ -297,6 +299,9 @@ public class PropertyFactory { ? ( (SingularAssociationAttributeBinding) singularAttributeBinding ).getFetchMode() : FetchMode.DEFAULT; + PropertyGeneration propertyGeneration = BasicAttributeBinding.class.isInstance( property ) + ? ( (BasicAttributeBinding) property ).getGeneration() + : PropertyGeneration.NEVER; return new StandardProperty( singularAttributeBinding.getAttribute().getName(), null, @@ -304,9 +309,9 @@ public class PropertyFactory { lazyAvailable && singularAttributeBinding.isLazy(), true, // insertable true, // updatable - singularAttributeBinding.getGeneration() == PropertyGeneration.INSERT - || singularAttributeBinding.getGeneration() == PropertyGeneration.ALWAYS, - singularAttributeBinding.getGeneration() == PropertyGeneration.ALWAYS, + propertyGeneration == PropertyGeneration.INSERT + || propertyGeneration == PropertyGeneration.ALWAYS, + propertyGeneration == PropertyGeneration.ALWAYS, singularAttributeBinding.isNullable(), alwaysDirtyCheck || areAllValuesIncludedInUpdate( singularAttributeBinding ), singularAttributeBinding.isIncludedInOptimisticLocking(), @@ -348,7 +353,7 @@ public class PropertyFactory { if ( attributeBinding.hasDerivedValue() ) { return false; } - for ( SimpleValueBinding valueBinding : attributeBinding.getSimpleValueBindings() ) { + for ( RelationalValueBinding valueBinding : attributeBinding.getRelationalValueBindings() ) { if ( ! valueBinding.isIncludeInUpdate() ) { return false; } diff --git a/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityMetamodel.java b/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityMetamodel.java index 82754b35f4..0d45a40a6f 100644 --- a/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityMetamodel.java +++ b/hibernate-core/src/main/java/org/hibernate/tuple/entity/EntityMetamodel.java @@ -428,10 +428,11 @@ public class EntityMetamodel implements Serializable { continue; } - if ( attributeBinding == entityBinding.getHierarchyDetails().getVersioningAttributeBinding() ) { + if ( attributeBinding == entityBinding.getHierarchyDetails().getEntityVersion().getVersioningAttributeBinding() ) { tempVersionProperty = i; properties[i] = PropertyFactory.buildVersionProperty( - entityBinding.getHierarchyDetails().getVersioningAttributeBinding(), + entityBinding, + entityBinding.getHierarchyDetails().getEntityVersion().getVersioningAttributeBinding(), instrumentationMetadata.isInstrumented() ); } diff --git a/hibernate-core/src/matrix/java/org/hibernate/test/version/sybase/User.hbm.xml b/hibernate-core/src/matrix/java/org/hibernate/test/version/sybase/User.hbm.xml index 3f5b3c4fc5..2e385e10d7 100644 --- a/hibernate-core/src/matrix/java/org/hibernate/test/version/sybase/User.hbm.xml +++ b/hibernate-core/src/matrix/java/org/hibernate/test/version/sybase/User.hbm.xml @@ -4,7 +4,7 @@ "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/AssertSourcesTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/AssertSourcesTest.java index c00a8f3543..e1daf40ba3 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/AssertSourcesTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/AssertSourcesTest.java @@ -150,7 +150,7 @@ public class AssertSourcesTest extends BaseUnitTestCase { // assertNull( columnSource.getSqlType() ); // assertNull( columnSource.getCheckCondition() ); // assertNull( columnSource.getComment() ); -// assertNull( columnSource.getDatatype() ); +// assertNull( columnSource.getJdbcDataType() ); // assertNull( columnSource.getSize() ); // // todo : technically, pk has to be unique, but this another semantic case // assertFalse( columnSource.isUnique() ); diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/EmbeddableBindingTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/EmbeddableBindingTest.java index 5b8ef15bb9..7acc372ebf 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/EmbeddableBindingTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/EmbeddableBindingTest.java @@ -31,14 +31,14 @@ import javax.persistence.Embedded; import javax.persistence.Entity; import javax.persistence.Id; -import org.junit.Test; - import org.hibernate.annotations.Parent; import org.hibernate.annotations.Target; import org.hibernate.metamodel.spi.binding.BasicAttributeBinding; import org.hibernate.metamodel.spi.binding.ComponentAttributeBinding; import org.hibernate.metamodel.spi.binding.EntityBinding; +import org.junit.Test; + import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertNotNull; import static junit.framework.Assert.assertTrue; @@ -120,7 +120,9 @@ public class EmbeddableBindingTest extends BaseAnnotationBindingTestCase { assertNotNull( componentBinding.locateAttributeBinding( "name" ) ); BasicAttributeBinding nameAttribute = (BasicAttributeBinding) componentBinding.locateAttributeBinding( "name" ); - org.hibernate.metamodel.spi.relational.Column column = (org.hibernate.metamodel.spi.relational.Column) nameAttribute.getValue(); + assertEquals( 1, nameAttribute.getRelationalValueBindings().size() ); + org.hibernate.metamodel.spi.relational.Column column + = (org.hibernate.metamodel.spi.relational.Column) nameAttribute.getRelationalValueBindings().get( 0 ).getValue(); assertEquals( "Attribute override specifies a custom column name", "FUBAR", column.getColumnName().getName() ); assertEquals( "Attribute override specifies a custom size", 42, column.getSize().getLength() ); } @@ -178,7 +180,9 @@ public class EmbeddableBindingTest extends BaseAnnotationBindingTestCase { BasicAttributeBinding stateAttribute = (BasicAttributeBinding) attributeComponentBinding.locateAttributeBinding( "state" ); - org.hibernate.metamodel.spi.relational.Column column = (org.hibernate.metamodel.spi.relational.Column) stateAttribute.getValue(); + assertEquals( 1, stateAttribute.getRelationalValueBindings().size() ); + org.hibernate.metamodel.spi.relational.Column column + = (org.hibernate.metamodel.spi.relational.Column) stateAttribute.getRelationalValueBindings().get( 0 ).getValue(); assertEquals( "Attribute override specifies a custom column name", "ADDR_STATE", @@ -194,7 +198,8 @@ public class EmbeddableBindingTest extends BaseAnnotationBindingTestCase { ); BasicAttributeBinding nameAttribute = (BasicAttributeBinding) zipComponentBinding.locateAttributeBinding( "zip" ); - column = (org.hibernate.metamodel.spi.relational.Column) nameAttribute.getValue(); + assertEquals( 1, nameAttribute.getRelationalValueBindings().size() ); + column = (org.hibernate.metamodel.spi.relational.Column) nameAttribute.getRelationalValueBindings().get( 0 ).getValue(); assertEquals( "Attribute override specifies a custom column name", "ADDR_ZIP", @@ -270,7 +275,9 @@ public class EmbeddableBindingTest extends BaseAnnotationBindingTestCase { ); BasicAttributeBinding attribute = (BasicAttributeBinding) bComponentBinding.locateAttributeBinding( "foo" ); - org.hibernate.metamodel.spi.relational.Column column = (org.hibernate.metamodel.spi.relational.Column) attribute.getValue(); + assertEquals( 1, attribute.getRelationalValueBindings().size() ); + org.hibernate.metamodel.spi.relational.Column column + = (org.hibernate.metamodel.spi.relational.Column) attribute.getRelationalValueBindings().get( 0 ).getValue(); assertEquals( "Attribute override specifies a custom column name", "BAR", @@ -278,7 +285,8 @@ public class EmbeddableBindingTest extends BaseAnnotationBindingTestCase { ); attribute = (BasicAttributeBinding) bComponentBinding.locateAttributeBinding( "fubar" ); - column = (org.hibernate.metamodel.spi.relational.Column) attribute.getValue(); + assertEquals( 1, attribute.getRelationalValueBindings().size() ); + column = (org.hibernate.metamodel.spi.relational.Column) attribute.getRelationalValueBindings().get( 0 ).getValue(); assertEquals( "Attribute override specifies a custom column name", "C_WINS", diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/InheritanceBindingTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/InheritanceBindingTest.java index 73f905e5c9..fe9d0b4d62 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/InheritanceBindingTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/InheritanceBindingTest.java @@ -41,7 +41,7 @@ import org.hibernate.metamodel.spi.binding.AttributeBinding; import org.hibernate.metamodel.spi.binding.EntityBinding; import org.hibernate.metamodel.spi.binding.EntityDiscriminator; import org.hibernate.metamodel.spi.relational.DerivedValue; -import org.hibernate.metamodel.spi.relational.SimpleValue; +import org.hibernate.metamodel.spi.relational.Value; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; @@ -454,7 +454,7 @@ public class InheritanceBindingTest extends BaseAnnotationBindingTestCase { EntityBinding entityBinding = getEntityBinding( Apple.class ); assertFalse( entityBinding.isRoot() ); EntityDiscriminator discriminator = rootEntityBinding.getHierarchyDetails().getEntityDiscriminator(); - SimpleValue simpleValue = discriminator.getBoundValue(); + Value simpleValue = discriminator.getRelationalValue(); assertTrue( simpleValue instanceof DerivedValue); DerivedValue derivedValue = (DerivedValue)simpleValue; assertEquals( "case when zik_type is null then 0 else zik_type end", derivedValue.getExpression() ); diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/MappedSuperclassTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/MappedSuperclassTest.java index 0d50e5d35b..3c06ffedbd 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/MappedSuperclassTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/MappedSuperclassTest.java @@ -57,7 +57,8 @@ public class MappedSuperclassTest extends BaseAnnotationBindingTestCase { SingularAttributeBinding nameBinding = (SingularAttributeBinding) binding.locateAttributeBinding( "name" ); assertNotNull( "the name attribute should be bound to MyEntity", nameBinding ); - Column column = (Column) nameBinding.getValue(); + assertEquals( 1, nameBinding.getRelationalValueBindings().size() ); + Column column = (Column) nameBinding.getRelationalValueBindings().get( 0 ).getValue(); assertEquals( "Wrong column name", "MY_NAME", column.getColumnName().toString() ); } @@ -68,7 +69,8 @@ public class MappedSuperclassTest extends BaseAnnotationBindingTestCase { SingularAttributeBinding fooBinding = (SingularAttributeBinding) binding.locateAttributeBinding( "foo" ); assertNotNull( "the foo attribute should be bound to MyEntity", fooBinding ); - Column column = (Column) fooBinding.getValue(); + assertEquals( 1, fooBinding.getRelationalValueBindings().size() ); + Column column = (Column) fooBinding.getRelationalValueBindings().get( 0 ).getValue(); assertEquals( "Wrong column name", "MY_FOO", column.getColumnName().toString() ); } diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/SecondaryTableTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/SecondaryTableTest.java index 5a98a719df..83eccb73d5 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/SecondaryTableTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/SecondaryTableTest.java @@ -23,21 +23,18 @@ */ package org.hibernate.metamodel.internal.source.annotations.entity; -import java.util.Iterator; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.SecondaryTable; -import org.junit.Test; - import org.hibernate.AssertionFailure; import org.hibernate.metamodel.spi.binding.EntityBinding; -import org.hibernate.metamodel.spi.relational.SimpleValue; import org.hibernate.metamodel.spi.relational.Table; +import org.junit.Test; + import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertTrue; import static junit.framework.Assert.fail; @@ -47,6 +44,7 @@ import static junit.framework.Assert.fail; public class SecondaryTableTest extends BaseAnnotationBindingTestCase { @Entity @SecondaryTable(name = "SECOND_TABLE") + @SuppressWarnings( {"UnusedDeclaration"}) class EntityWithSecondaryTable { @Id private long id; @@ -62,11 +60,9 @@ public class SecondaryTableTest extends BaseAnnotationBindingTestCase { Table table = (Table) binding.locateTable( "SECOND_TABLE" ); assertEquals( "The secondary table should exist", "SECOND_TABLE", table.getTableName().getName() ); - Iterator valueIterator = table.values().iterator(); - assertTrue( valueIterator.hasNext() ); - org.hibernate.metamodel.spi.relational.Column column = (org.hibernate.metamodel.spi.relational.Column) valueIterator.next(); + assertEquals( 1, table.values().size() ); + org.hibernate.metamodel.spi.relational.Column column = (org.hibernate.metamodel.spi.relational.Column) table.values().get( 0 ); assertEquals( "Wrong column name", "name", column.getColumnName().getName() ); - assertFalse( valueIterator.hasNext() ); } @Test diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/VersionBindingTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/VersionBindingTests.java index 759eb5aab7..7d07e44973 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/VersionBindingTests.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/entity/VersionBindingTests.java @@ -96,6 +96,7 @@ public class VersionBindingTests extends BaseAnnotationBindingTestCase { EntityBinding binding = getEntityBinding( Item2.class ); assertTrue( binding.isVersioned() ); HibernateTypeDescriptor descriptor = binding.getHierarchyDetails() + .getEntityVersion() .getVersioningAttributeBinding() .getHibernateTypeDescriptor(); // assertEquals( "Long", descriptor.getExplicitTypeName() ); @@ -121,6 +122,7 @@ public class VersionBindingTests extends BaseAnnotationBindingTestCase { EntityBinding binding = getEntityBinding( Item3.class ); assertTrue( binding.isVersioned() ); HibernateTypeDescriptor descriptor = binding.getHierarchyDetails() + .getEntityVersion() .getVersioningAttributeBinding() .getHibernateTypeDescriptor(); assertEquals( "dbtimestamp", descriptor.getExplicitTypeName() ); diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/AbstractBasicBindingTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/AbstractBasicBindingTests.java index 8fb8e849a8..8d8ba80dfe 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/AbstractBasicBindingTests.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/AbstractBasicBindingTests.java @@ -28,6 +28,7 @@ import java.util.Iterator; import java.util.Set; import org.junit.After; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -36,8 +37,8 @@ import org.hibernate.metamodel.spi.domain.BasicType; import org.hibernate.metamodel.spi.domain.SingularAttribute; import org.hibernate.metamodel.internal.MetadataImpl; import org.hibernate.metamodel.spi.relational.Column; -import org.hibernate.metamodel.spi.relational.Datatype; -import org.hibernate.metamodel.spi.relational.SimpleValue; +import org.hibernate.metamodel.spi.relational.JdbcDataType; +import org.hibernate.metamodel.spi.relational.Value; import org.hibernate.metamodel.spi.source.MetadataImplementor; import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistryBuilder; @@ -85,7 +86,7 @@ public abstract class AbstractBasicBindingTests extends BaseUnitTestCase { assertRoot( metadata, entityBinding ); assertIdAndSimpleProperty( entityBinding ); - assertNull( entityBinding.getHierarchyDetails().getVersioningAttributeBinding() ); + assertNull( entityBinding.getHierarchyDetails().getEntityVersion().getVersioningAttributeBinding() ); } @Test @@ -96,8 +97,8 @@ public abstract class AbstractBasicBindingTests extends BaseUnitTestCase { EntityBinding entityBinding = metadata.getEntityBinding( SimpleVersionedEntity.class.getName() ); assertIdAndSimpleProperty( entityBinding ); - assertNotNull( entityBinding.getHierarchyDetails().getVersioningAttributeBinding() ); - assertNotNull( entityBinding.getHierarchyDetails().getVersioningAttributeBinding().getAttribute() ); + assertNotNull( entityBinding.getHierarchyDetails().getEntityVersion().getVersioningAttributeBinding() ); + assertNotNull( entityBinding.getHierarchyDetails().getEntityVersion().getVersioningAttributeBinding().getAttribute() ); } @Test @@ -170,9 +171,10 @@ public abstract class AbstractBasicBindingTests extends BaseUnitTestCase { BasicType basicIdAttributeType = ( BasicType ) singularIdAttribute.getSingularAttributeType(); assertSame( Long.class, basicIdAttributeType.getClassReference() ); - assertNotNull( singularIdAttributeBinding.getValue() ); - assertTrue( singularIdAttributeBinding.getValue() instanceof Column ); - Datatype idDataType = ( (Column) singularIdAttributeBinding.getValue() ).getDatatype(); + assertTrue( singularIdAttributeBinding.getRelationalValueBindings().size() == 1 ); + Value value = singularIdAttributeBinding.getRelationalValueBindings().get( 0 ).getValue(); + assertTrue( value instanceof Column ); + JdbcDataType idDataType = value.getJdbcDataType(); assertSame( Long.class, idDataType.getJavaType() ); assertSame( Types.BIGINT, idDataType.getTypeCode() ); assertSame( LongType.INSTANCE.getName(), idDataType.getTypeName() ); @@ -185,15 +187,14 @@ public abstract class AbstractBasicBindingTests extends BaseUnitTestCase { assertTrue( nameBinding.isNullable() ); assertSame( StringType.INSTANCE, nameBinding.getHibernateTypeDescriptor().getResolvedTypeMapping() ); assertNotNull( nameBinding.getAttribute() ); - assertNotNull( nameBinding.getValue() ); - SingularAttribute singularNameAttribute = (SingularAttribute) nameBinding.getAttribute(); + assertNotNull( nameBinding.getRelationalValueBindings().size() ); + SingularAttribute singularNameAttribute = nameBinding.getAttribute(); BasicType basicNameAttributeType = (BasicType) singularNameAttribute.getSingularAttributeType(); assertSame( String.class, basicNameAttributeType.getClassReference() ); - - assertNotNull( nameBinding.getValue() ); - SimpleValue nameValue = (SimpleValue) nameBinding.getValue(); + Assert.assertEquals( 1, nameBinding.getRelationalValueBindings().size() ); + Value nameValue = (Value) nameBinding.getRelationalValueBindings().get( 0 ).getValue(); assertTrue( nameValue instanceof Column ); - Datatype nameDataType = nameValue.getDatatype(); + JdbcDataType nameDataType = nameValue.getJdbcDataType(); assertSame( String.class, nameDataType.getJavaType() ); assertSame( Types.VARCHAR, nameDataType.getTypeCode() ); assertSame( StringType.INSTANCE.getName(), nameDataType.getTypeName() ); diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/SimpleValueBindingTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/SimpleValueBindingTests.java index cf5a906ac2..23ae70504d 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/SimpleValueBindingTests.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/binding/SimpleValueBindingTests.java @@ -24,15 +24,18 @@ package org.hibernate.metamodel.spi.binding; import java.sql.Types; +import java.util.ArrayList; +import java.util.List; import org.junit.Test; import org.hibernate.EntityMode; import org.hibernate.internal.util.Value; +import org.hibernate.mapping.PropertyGeneration; import org.hibernate.metamodel.spi.domain.Entity; import org.hibernate.metamodel.spi.domain.SingularAttribute; import org.hibernate.metamodel.spi.relational.Column; -import org.hibernate.metamodel.spi.relational.Datatype; +import org.hibernate.metamodel.spi.relational.JdbcDataType; import org.hibernate.metamodel.spi.relational.Schema; import org.hibernate.metamodel.spi.relational.Size; import org.hibernate.metamodel.spi.relational.Table; @@ -47,30 +50,46 @@ import static org.junit.Assert.assertSame; * @author Steve Ebersole */ public class SimpleValueBindingTests extends BaseUnitTestCase { - public static final Datatype BIGINT = new Datatype( Types.BIGINT, "BIGINT", Long.class ); - public static final Datatype VARCHAR = new Datatype( Types.VARCHAR, "VARCHAR", String.class ); + public static final JdbcDataType BIGINT = new JdbcDataType( Types.BIGINT, "BIGINT", Long.class ); + public static final JdbcDataType VARCHAR = new JdbcDataType( Types.VARCHAR, "VARCHAR", String.class ); @Test public void testBasicMiddleOutBuilding() { Table table = new Table( new Schema( null, null ), "the_table" ); + Column idColumn = table.locateOrCreateColumn( "id" ); + idColumn.setJdbcDataType( BIGINT ); + idColumn.setSize( Size.precision( 18, 0 ) ); + table.getPrimaryKey().addColumn( idColumn ); + table.getPrimaryKey().setName( "my_table_pk" ); + Entity entity = new Entity( "TheEntity", "NoSuchClass", makeJavaType( "NoSuchClass" ), null ); EntityBinding entityBinding = new EntityBinding( InheritanceType.NO_INHERITANCE, EntityMode.POJO ); entityBinding.setEntity( entity ); entityBinding.setPrimaryTable( table ); + List valueBindings = new ArrayList(); + valueBindings.add( + new RelationalValueBinding( + idColumn, + true, + true + ) + ); SingularAttribute idAttribute = entity.createSingularAttribute( "id" ); - BasicAttributeBinding attributeBinding = entityBinding.makeBasicAttributeBinding( idAttribute ); + BasicAttributeBinding attributeBinding = entityBinding.makeBasicAttributeBinding( + idAttribute, + valueBindings, + "property", + true, + false, + null, + PropertyGeneration.NEVER + ); attributeBinding.getHibernateTypeDescriptor().setExplicitTypeName( "long" ); assertSame( idAttribute, attributeBinding.getAttribute() ); entityBinding.getHierarchyDetails().getEntityIdentifier().setValueBinding( attributeBinding ); - - Column idColumn = table.locateOrCreateColumn( "id" ); - idColumn.setDatatype( BIGINT ); - idColumn.setSize( Size.precision( 18, 0 ) ); - table.getPrimaryKey().addColumn( idColumn ); - table.getPrimaryKey().setName( "my_table_pk" ); //attributeBinding.setValue( idColumn ); } diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/relational/TableManipulationTests.java b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/relational/TableManipulationTests.java index 096cb28060..6d62810152 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/spi/relational/TableManipulationTests.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/spi/relational/TableManipulationTests.java @@ -41,8 +41,8 @@ import static org.junit.Assert.assertTrue; * @author Steve Ebersole */ public class TableManipulationTests extends BaseUnitTestCase { - public static final Datatype VARCHAR = new Datatype( Types.VARCHAR, "VARCHAR", String.class ); - public static final Datatype INTEGER = new Datatype( Types.INTEGER, "INTEGER", Long.class ); + public static final JdbcDataType VARCHAR = new JdbcDataType( Types.VARCHAR, "VARCHAR", String.class ); + public static final JdbcDataType INTEGER = new JdbcDataType( Types.INTEGER, "INTEGER", Long.class ); @Test public void testTableCreation() { @@ -56,7 +56,7 @@ public class TableManipulationTests extends BaseUnitTestCase { assertFalse( table.values().iterator().hasNext() ); Column idColumn = table.locateOrCreateColumn( "id" ); - idColumn.setDatatype( INTEGER ); + idColumn.setJdbcDataType( INTEGER ); idColumn.setSize( Size.precision( 18, 0 ) ); table.getPrimaryKey().addColumn( idColumn ); table.getPrimaryKey().setName( "my_table_pk" ); @@ -64,14 +64,14 @@ public class TableManipulationTests extends BaseUnitTestCase { assertEquals( "my_table.PK", table.getPrimaryKey().getExportIdentifier() ); Column col_1 = table.locateOrCreateColumn( "col_1" ); - col_1.setDatatype( VARCHAR ); + col_1.setJdbcDataType( VARCHAR ); col_1.setSize( Size.length( 512 ) ); for ( Value value : table.values() ) { assertTrue( Column.class.isInstance( value ) ); Column column = ( Column ) value; if ( column.getColumnName().getName().equals( "id" ) ) { - assertEquals( INTEGER, column.getDatatype() ); + assertEquals( INTEGER, column.getJdbcDataType() ); assertEquals( 18, column.getSize().getPrecision() ); assertEquals( 0, column.getSize().getScale() ); assertEquals( -1, column.getSize().getLength() ); @@ -79,7 +79,7 @@ public class TableManipulationTests extends BaseUnitTestCase { } else { assertEquals( "col_1", column.getColumnName().getName() ); - assertEquals( VARCHAR, column.getDatatype() ); + assertEquals( VARCHAR, column.getJdbcDataType() ); assertEquals( -1, column.getSize().getPrecision() ); assertEquals( -1, column.getSize().getScale() ); assertEquals( 512, column.getSize().getLength() ); @@ -109,7 +109,7 @@ public class TableManipulationTests extends BaseUnitTestCase { Table book = schema.createTable( Identifier.toIdentifier( "BOOK" ) ); Column bookId = book.locateOrCreateColumn( "id" ); - bookId.setDatatype( INTEGER ); + bookId.setJdbcDataType( INTEGER ); bookId.setSize( Size.precision( 18, 0 ) ); book.getPrimaryKey().addColumn( bookId ); book.getPrimaryKey().setName( "BOOK_PK" ); @@ -117,13 +117,13 @@ public class TableManipulationTests extends BaseUnitTestCase { Table page = schema.createTable( Identifier.toIdentifier( "PAGE" ) ); Column pageId = page.locateOrCreateColumn( "id" ); - pageId.setDatatype( INTEGER ); + pageId.setJdbcDataType( INTEGER ); pageId.setSize( Size.precision( 18, 0 ) ); page.getPrimaryKey().addColumn( pageId ); page.getPrimaryKey().setName( "PAGE_PK" ); Column pageBookId = page.locateOrCreateColumn( "BOOK_ID" ); - pageId.setDatatype( INTEGER ); + pageId.setJdbcDataType( INTEGER ); pageId.setSize( Size.precision( 18, 0 ) ); ForeignKey pageBookFk = page.createForeignKey( book, "PAGE_BOOK_FK" ); pageBookFk.addColumn( pageBookId );