diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/AbstractEntitySourceImpl.java b/hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/AbstractEntitySourceImpl.java
index b8cc59f58235..2c2addd58c71 100644
--- a/hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/AbstractEntitySourceImpl.java
+++ b/hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/AbstractEntitySourceImpl.java
@@ -41,6 +41,8 @@
import org.hibernate.internal.util.collections.CollectionHelper;
import static java.util.Collections.emptyMap;
+import static org.hibernate.internal.util.StringHelper.isNotEmpty;
+import static org.hibernate.internal.util.StringHelper.unqualify;
/**
* @author Steve Ebersole
@@ -97,19 +99,20 @@ protected AbstractEntitySourceImpl(MappingDocument sourceMappingDocument, JaxbHb
);
}
- public static EntityNamingSourceImpl extractEntityNamingSource(
+ static EntityNamingSourceImpl extractEntityNamingSource(
MappingDocument sourceMappingDocument,
EntityInfo jaxbEntityMapping) {
final String className = sourceMappingDocument.qualifyClassName( jaxbEntityMapping.getName() );
+ final String mappingEntityName = jaxbEntityMapping.getEntityName();
final String entityName;
final String jpaEntityName;
- if ( StringHelper.isNotEmpty( jaxbEntityMapping.getEntityName() ) ) {
- entityName = jaxbEntityMapping.getEntityName();
- jpaEntityName = jaxbEntityMapping.getEntityName();
+ if ( isNotEmpty( mappingEntityName ) ) {
+ entityName = mappingEntityName;
+ jpaEntityName = mappingEntityName;
}
else {
entityName = className;
- jpaEntityName = StringHelper.unqualify( className );
+ jpaEntityName = unqualify( className );
}
return new EntityNamingSourceImpl( entityName, className, jpaEntityName );
}
@@ -122,7 +125,7 @@ private FilterSource[] buildFilterSources() {
return NO_FILTER_SOURCES;
}
- FilterSource[] results = new FilterSource[size];
+ final var results = new FilterSource[size];
for ( int i = 0; i < size; i++ ) {
JaxbHbmFilterType element = jaxbClassElement.getFilter().get( i );
results[i] = new FilterSourceImpl( sourceMappingDocument(), element );
diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/EntityNamingSourceImpl.java b/hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/EntityNamingSourceImpl.java
index 68bc41743838..dd9cc77701be 100644
--- a/hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/EntityNamingSourceImpl.java
+++ b/hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/EntityNamingSourceImpl.java
@@ -5,9 +5,10 @@
package org.hibernate.boot.model.source.internal.hbm;
import org.hibernate.boot.model.source.spi.EntityNamingSource;
-import org.hibernate.internal.util.StringHelper;
import org.hibernate.mapping.PersistentClass;
+import static org.hibernate.internal.util.StringHelper.isNotEmpty;
+
/**
* Implementation of EntityNamingSource
*
@@ -24,12 +25,13 @@ public EntityNamingSourceImpl(String entityName, String className, String jpaEnt
this.entityName = entityName;
this.className = className;
this.jpaEntityName = jpaEntityName;
-
- this.typeName = StringHelper.isNotEmpty( className ) ? className : entityName;
+ this.typeName = isNotEmpty( className ) ? className : entityName;
}
public EntityNamingSourceImpl(PersistentClass entityBinding) {
- this( entityBinding.getEntityName(), entityBinding.getClassName(), entityBinding.getJpaEntityName() );
+ this( entityBinding.getEntityName(),
+ entityBinding.getClassName(),
+ entityBinding.getJpaEntityName() );
}
@Override
diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/ModelBinder.java b/hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/ModelBinder.java
index 4277507b3062..9cdaa0178438 100644
--- a/hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/ModelBinder.java
+++ b/hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/ModelBinder.java
@@ -45,6 +45,7 @@
import org.hibernate.boot.spi.NaturalIdUniqueKeyBinder;
import org.hibernate.boot.spi.SecondPass;
import org.hibernate.cache.spi.access.AccessType;
+import org.hibernate.dialect.Dialect;
import org.hibernate.engine.FetchStyle;
import org.hibernate.engine.FetchTiming;
import org.hibernate.generator.internal.GeneratedGeneration;
@@ -80,6 +81,7 @@
import org.hibernate.mapping.SingleTableSubclass;
import org.hibernate.mapping.SortableValue;
import org.hibernate.mapping.Table;
+import org.hibernate.mapping.ToOne;
import org.hibernate.mapping.UnionSubclass;
import org.hibernate.mapping.UniqueKey;
import org.hibernate.mapping.Value;
@@ -470,7 +472,7 @@ private void bindJoinedSubclassEntity(
keyBinding.makeNationalized();
}
entityDescriptor.setKey( keyBinding );
- keyBinding.setOnDeleteAction( getOnDeleteAction( entitySource.isCascadeDeleteEnabled() ) );
+ keyBinding.setOnDeleteAction( getOnDeleteAction( entitySource ) );
relationalObjectBinder.bindColumns(
mappingDocument,
entitySource.getPrimaryKeyColumnSources(),
@@ -486,7 +488,8 @@ public Identifier determineImplicitName(LocalMetadataBuildingContext context) {
}
);
keyBinding.sortProperties();
- setForeignKeyName( keyBinding, entitySource.getExplicitForeignKeyName() );
+ setForeignKeyName( keyBinding,
+ entitySource.getExplicitForeignKeyName() );
// model.getKey().setType( new Type( model.getIdentifier() ) );
entityDescriptor.createPrimaryKey();
entityDescriptor.createForeignKey();
@@ -1209,9 +1212,10 @@ private void bindCollectionMetadata(MappingDocument mappingDocument, PluralAttri
binding.setTypeName( typeName );
binding.setTypeParameters( typeParameters );
- if ( source.getFetchCharacteristics().getFetchTiming() == FetchTiming.DELAYED ) {
+ final var fetchCharacteristics = source.getFetchCharacteristics();
+ if ( fetchCharacteristics.getFetchTiming() == FetchTiming.DELAYED ) {
binding.setLazy( true );
- binding.setExtraLazy( source.getFetchCharacteristics().isExtraLazy() );
+ binding.setExtraLazy( fetchCharacteristics.isExtraLazy() );
}
else {
binding.setLazy( false );
@@ -1293,7 +1297,8 @@ private static void bindCustomSql(PluralAttributeSource source, Collection bindi
}
private static void setupFetching(PluralAttributeSource source, Collection binding) {
- switch ( source.getFetchCharacteristics().getFetchStyle() ) {
+ final var fetchCharacteristics = source.getFetchCharacteristics();
+ switch ( fetchCharacteristics.getFetchStyle() ) {
case SELECT:
binding.setFetchMode( FetchMode.SELECT );
break;
@@ -1302,7 +1307,7 @@ private static void setupFetching(PluralAttributeSource source, Collection bindi
break;
case BATCH:
binding.setFetchMode( FetchMode.SELECT );
- binding.setBatchSize( source.getFetchCharacteristics().getBatchSize() );
+ binding.setBatchSize( fetchCharacteristics.getBatchSize() );
break;
case SUBSELECT:
binding.setFetchMode( FetchMode.SELECT );
@@ -1312,7 +1317,7 @@ private static void setupFetching(PluralAttributeSource source, Collection bindi
break;
default:
throw new AssertionFailure( "Unexpected FetchStyle : "
- + source.getFetchCharacteristics().getFetchStyle().name() );
+ + fetchCharacteristics.getFetchStyle().name() );
}
}
@@ -1385,7 +1390,8 @@ private Identifier determineTable(
for ( var relationalValueSource : relationalValueSources ) {
// We need to get the containing table name for both columns and formulas,
// particularly when a column/formula is for a property on a secondary table.
- if ( !Objects.equals( tableName, relationalValueSource.getContainingTableName() ) ) {
+ final String containingTableName = relationalValueSource.getContainingTableName();
+ if ( !Objects.equals( tableName, containingTableName ) ) {
if ( tableName != null ) {
throw new MappingException(
String.format(
@@ -1393,12 +1399,12 @@ private Identifier determineTable(
"Attribute [%s] referenced columns from multiple tables: %s, %s",
attributeName,
tableName,
- relationalValueSource.getContainingTableName()
+ containingTableName
),
mappingDocument.getOrigin()
);
}
- tableName = relationalValueSource.getContainingTableName();
+ tableName = containingTableName;
}
}
return database.toIdentifier( tableName );
@@ -1429,8 +1435,7 @@ private void bindSecondaryTable(
}
secondaryTable.setComment( tableSource.getComment() );
}
- else {
- final var inLineViewSource = (InLineViewSource) tableSpecificationSource;
+ else if ( tableSpecificationSource instanceof InLineViewSource inLineViewSource ) {
logicalTableName = toIdentifier( inLineViewSource.getLogicalName() );
secondaryTable = new Table(
metadataBuildingContext.getCurrentContributorName(),
@@ -1439,6 +1444,9 @@ private void bindSecondaryTable(
false
);
}
+ else {
+ throw new AssertionFailure( "Unexpected table specification soure type" );
+ }
secondaryTableJoin.setTable( secondaryTable );
entityTableXref.addSecondaryTable( mappingDocument, logicalTableName, secondaryTableJoin );
@@ -1456,13 +1464,14 @@ private void bindSecondaryTable(
}
final var keyBinding =
- new DependantValue( mappingDocument, secondaryTable, persistentClass.getIdentifier() );
+ new DependantValue( mappingDocument, secondaryTable,
+ persistentClass.getIdentifier() );
if ( mappingDocument.getBuildingOptions().useNationalizedCharacterData() ) {
keyBinding.makeNationalized();
}
secondaryTableJoin.setKey( keyBinding );
- keyBinding.setOnDeleteAction( getOnDeleteAction( secondaryTableSource.isCascadeDeleteEnabled() ) );
+ keyBinding.setOnDeleteAction( getOnDeleteAction( secondaryTableSource ) );
// NOTE: no Type info to bind...
@@ -1482,7 +1491,8 @@ public Identifier determineImplicitName(LocalMetadataBuildingContext context) {
);
keyBinding.sortProperties();
- setForeignKeyName( keyBinding, secondaryTableSource.getExplicitForeignKeyName() );
+ setForeignKeyName( keyBinding,
+ secondaryTableSource.getExplicitForeignKeyName() );
// skip creating primary and foreign keys for a subselect.
if ( secondaryTable.getSubselect() == null ) {
@@ -1633,15 +1643,8 @@ private Property createOneToOneAttribute(
oneToOneSource.getAttributeRole()
);
- final String propertyRef = oneToOneBinding.getReferencedPropertyName();
- if ( propertyRef != null ) {
- handlePropertyReference(
- sourceDocument,
- oneToOneBinding.getReferencedEntityName(),
- propertyRef,
- ""
- );
- }
+ handlePropertyRef( sourceDocument, oneToOneBinding,
+ "" );
// Defer the creation of the foreign key as we need the
// associated entity persister to be initialized so that
@@ -1656,25 +1659,36 @@ private Property createOneToOneAttribute(
return property;
}
+ private void handlePropertyRef(
+ MappingDocument sourceDocument,
+ ToOne binding,
+ String synopsis) {
+ final String propertyRef = binding.getReferencedPropertyName();
+ if ( propertyRef != null ) {
+ handlePropertyReference(
+ sourceDocument,
+ binding.getReferencedEntityName(),
+ propertyRef,
+ synopsis
+ );
+ }
+ }
+
private void handlePropertyReference(
MappingDocument mappingDocument,
String referencedEntityName,
String referencedPropertyName,
String sourceElementSynopsis) {
- final var entityBinding =
- mappingDocument.getMetadataCollector()
- .getEntityBinding( referencedEntityName );
+ final var collector = mappingDocument.getMetadataCollector();
+ final var entityBinding = collector.getEntityBinding( referencedEntityName );
if ( entityBinding == null ) {
// entity may just not have been processed yet - set up a delayed handler
registerDelayedPropertyReferenceHandler(
- new DelayedPropertyReferenceHandlerImpl(
- referencedEntityName,
- referencedPropertyName,
- true,
- sourceElementSynopsis,
- mappingDocument.getOrigin()
- ),
- mappingDocument
+ mappingDocument,
+ referencedEntityName,
+ referencedPropertyName,
+ sourceElementSynopsis,
+ collector
);
}
else {
@@ -1683,14 +1697,11 @@ private void handlePropertyReference(
if ( propertyBinding == null ) {
// attribute may just not have been processed yet - set up a delayed handler
registerDelayedPropertyReferenceHandler(
- new DelayedPropertyReferenceHandlerImpl(
- referencedEntityName,
- referencedPropertyName,
- true,
- sourceElementSynopsis,
- mappingDocument.getOrigin()
- ),
- mappingDocument
+ mappingDocument,
+ referencedEntityName,
+ referencedPropertyName,
+ sourceElementSynopsis,
+ collector
);
}
else {
@@ -1706,15 +1717,26 @@ private void handlePropertyReference(
}
private void registerDelayedPropertyReferenceHandler(
- DelayedPropertyReferenceHandlerImpl handler,
- MetadataBuildingContext buildingContext) {
+ MappingDocument mappingDocument,
+ String referencedEntityName,
+ String referencedPropertyName,
+ String sourceElementSynopsis,
+ InFlightMetadataCollector collector) {
+ final var handler =
+ new DelayedPropertyReferenceHandlerImpl(
+ referencedEntityName,
+ referencedPropertyName,
+ true,
+ sourceElementSynopsis,
+ mappingDocument.getOrigin()
+ );
BOOT_LOGGER.tracef(
"Property [%s.%s] referenced by property-ref [%s] was not yet available - creating delayed handler",
handler.referencedEntityName,
handler.referencedPropertyName,
handler.sourceElementSynopsis
);
- buildingContext.getMetadataCollector().addDelayedPropertyReferenceHandler( handler );
+ collector.addDelayedPropertyReferenceHandler( handler );
}
public void bindOneToOne(
@@ -1729,19 +1751,8 @@ public void bindOneToOne(
oneToOneBinding
);
-
if ( oneToOneSource.isConstrained() ) {
- final String cascadeStyleName = oneToOneSource.getCascadeStyleName();
- if ( cascadeStyleName != null && cascadeStyleName.contains( "delete-orphan" ) ) {
- throw new MappingException(
- String.format(
- Locale.ENGLISH,
- "one-to-one attribute [%s] cannot specify orphan delete cascading as it is constrained",
- oneToOneSource.getAttributeRole().getFullPath()
- ),
- sourceDocument.getOrigin()
- );
- }
+ checkConstrainedOneToOneOrphanDelete( sourceDocument, oneToOneSource );
oneToOneBinding.setConstrained( true );
oneToOneBinding.setForeignKeyType( ForeignKeyDirection.FROM_PARENT );
}
@@ -1749,15 +1760,7 @@ public void bindOneToOne(
oneToOneBinding.setForeignKeyType( ForeignKeyDirection.TO_PARENT );
}
- final var fetchCharacteristics = oneToOneSource.getFetchCharacteristics();
- oneToOneBinding.setLazy( fetchCharacteristics.getFetchTiming() == FetchTiming.DELAYED );
- oneToOneBinding.setFetchMode(
- fetchCharacteristics.getFetchStyle() == FetchStyle.SELECT
- ? FetchMode.SELECT
- : FetchMode.JOIN
- );
- oneToOneBinding.setUnwrapProxy( fetchCharacteristics.isUnwrapProxies() );
-
+ handleFetchCharacteristics( oneToOneSource, oneToOneBinding );
final String referencedEntityAttributeName = oneToOneSource.getReferencedEntityAttributeName();
if ( isNotEmpty( referencedEntityAttributeName ) ) {
@@ -1775,11 +1778,21 @@ public void bindOneToOne(
DEPRECATION_LOGGER.logDeprecationOfEmbedXmlSupport();
}
- if ( isNotEmpty( oneToOneSource.getExplicitForeignKeyName() ) ) {
- setForeignKeyName( oneToOneBinding, oneToOneSource.getExplicitForeignKeyName() );
- }
+ setForeignKeyName( oneToOneBinding,
+ oneToOneSource.getExplicitForeignKeyName() );
- oneToOneBinding.setOnDeleteAction( getOnDeleteAction( oneToOneSource.isCascadeDeleteEnabled() ) );
+ oneToOneBinding.setOnDeleteAction( getOnDeleteAction( oneToOneSource ) );
+ }
+
+ private static void handleFetchCharacteristics(SingularAttributeSourceToOne toOneSource, ToOne toOneBinding) {
+ final var fetchCharacteristics = toOneSource.getFetchCharacteristics();
+ toOneBinding.setLazy( fetchCharacteristics.getFetchTiming() == FetchTiming.DELAYED );
+ toOneBinding.setFetchMode(
+ fetchCharacteristics.getFetchStyle() == FetchStyle.SELECT
+ ? FetchMode.SELECT
+ : FetchMode.JOIN
+ );
+ toOneBinding.setUnwrapProxy( fetchCharacteristics.isUnwrapProxies() );
}
private Property createManyToOneAttribute(
@@ -1787,18 +1800,42 @@ private Property createManyToOneAttribute(
SingularAttributeSourceManyToOne manyToOneSource,
ManyToOne manyToOneBinding,
String containingClassName) {
- final String attributeName = manyToOneSource.getName();
+ final String referencedEntityName =
+ handleReferencedEntity( sourceDocument, manyToOneSource, manyToOneBinding, containingClassName );
+
+ if ( manyToOneSource.isUnique() ) {
+ manyToOneBinding.markAsLogicalOneToOne();
+ }
+ bindManyToOneAttribute( sourceDocument, manyToOneSource, manyToOneBinding, referencedEntityName );
+
+ handlePropertyRef( sourceDocument, manyToOneBinding,
+ "" );
+
+ final var property = new Property();
+ property.setValue( manyToOneBinding );
+ bindProperty( sourceDocument, manyToOneSource, property );
+
+ checkManyToOneOrphanDelete( sourceDocument, manyToOneSource, manyToOneBinding );
+
+ return property;
+ }
+
+ private String handleReferencedEntity(
+ MappingDocument sourceDocument,
+ SingularAttributeSourceManyToOne manyToOneSource,
+ ManyToOne manyToOneBinding,
+ String containingClassName) {
final String explicitReferencedEntityName = manyToOneSource.getReferencedEntityName();
- final String referencedEntityName;
if ( explicitReferencedEntityName != null ) {
- referencedEntityName = explicitReferencedEntityName;
+ return explicitReferencedEntityName;
}
else {
+ final String attributeName = manyToOneSource.getName();
final var reflectedPropertyClass =
reflectedPropertyClass( sourceDocument, containingClassName, attributeName );
if ( reflectedPropertyClass != null ) {
- referencedEntityName = reflectedPropertyClass.getName();
+ return reflectedPropertyClass.getName();
}
else {
prepareValueTypeViaReflection(
@@ -1808,57 +1845,54 @@ private Property createManyToOneAttribute(
attributeName,
manyToOneSource.getAttributeRole()
);
- referencedEntityName = manyToOneBinding.getTypeName();
+ return manyToOneBinding.getTypeName();
}
}
+ }
- if ( manyToOneSource.isUnique() ) {
- manyToOneBinding.markAsLogicalOneToOne();
- }
-
- bindManyToOneAttribute( sourceDocument, manyToOneSource, manyToOneBinding, referencedEntityName );
-
- final String propertyRef = manyToOneBinding.getReferencedPropertyName();
- if ( propertyRef != null ) {
- handlePropertyReference(
- sourceDocument,
- manyToOneBinding.getReferencedEntityName(),
- propertyRef,
- ""
+ private static void checkManyToOneOrphanDelete(
+ MappingDocument sourceDocument,
+ SingularAttributeSourceManyToOne manyToOneSource,
+ ManyToOne manyToOneBinding) {
+ // TODO: would be better to delay this until the end of binding (second pass, etc)
+ // in order to properly allow for a singular unique column for a many-to-one to
+ // to also trigger a "logical one-to-one". As is, this can occasionally lead to
+ // false exceptions if the many-to-one column binding is delayed and the
+ // uniqueness is indicated on the rather than on the
+ //
+ // Ideally, would love to see a SimpleValue#validate approach, rather than a
+ // SimpleValue#isValid that is then handled at a higher level (Property, etc).
+ // The reason being that the current approach misses the exact reason a
+ // "validation" fails since it loses "context"
+ final String cascadeStyleName = manyToOneSource.getCascadeStyleName();
+ if ( cascadeStyleName != null && cascadeStyleName.contains( "delete-orphan" )
+ && !manyToOneBinding.isLogicalOneToOne() ) {
+ throw new MappingException(
+ String.format(
+ Locale.ENGLISH,
+ "many-to-one attribute [%s] specified delete-orphan but is not specified as unique; " +
+ "remove delete-orphan cascading or specify unique=\"true\"",
+ manyToOneSource.getAttributeRole().getFullPath()
+ ),
+ sourceDocument.getOrigin()
);
}
+ }
- final var property = new Property();
- property.setValue( manyToOneBinding );
- bindProperty( sourceDocument, manyToOneSource, property );
-
- if ( isNotEmpty( manyToOneSource.getCascadeStyleName() ) ) {
- // todo : would be better to delay this the end of binding (second pass, etc)
- // in order to properly allow for a singular unique column for a many-to-one to
- // also trigger a "logical one-to-one". As-is, this can occasionally lead to
- // false exceptions if the many-to-one column binding is delayed and the
- // uniqueness is indicated on the rather than on the
- //
- // Ideally, would love to see a SimpleValue#validate approach, rather than a
- // SimpleValue#isValid that is then handled at a higher level (Property, etc).
- // The reason being that the current approach misses the exact reason
- // a "validation" fails since it loses "context"
- if ( manyToOneSource.getCascadeStyleName().contains( "delete-orphan" ) ) {
- if ( !manyToOneBinding.isLogicalOneToOne() ) {
- throw new MappingException(
- String.format(
- Locale.ENGLISH,
- "many-to-one attribute [%s] specified delete-orphan but is not specified as unique; " +
- "remove delete-orphan cascading or specify unique=\"true\"",
- manyToOneSource.getAttributeRole().getFullPath()
- ),
- sourceDocument.getOrigin()
- );
- }
- }
+ private static void checkConstrainedOneToOneOrphanDelete(
+ MappingDocument sourceDocument,
+ SingularAttributeSourceOneToOne oneToOneSource) {
+ final String cascadeStyleName = oneToOneSource.getCascadeStyleName();
+ if ( cascadeStyleName != null && cascadeStyleName.contains( "delete-orphan" ) ) {
+ throw new MappingException(
+ String.format(
+ Locale.ENGLISH,
+ "one-to-one attribute [%s] cannot specify orphan delete cascading as it is constrained",
+ oneToOneSource.getAttributeRole().getFullPath()
+ ),
+ sourceDocument.getOrigin()
+ );
}
-
- return property;
}
private void bindManyToOneAttribute(
@@ -1868,24 +1902,10 @@ private void bindManyToOneAttribute(
String referencedEntityName) {
// NOTE: no type information to bind
- manyToOneBinding.setReferencedEntityName( referencedEntityName );
- final String referencedEntityAttributeName = manyToOneSource.getReferencedEntityAttributeName();
- if ( isNotEmpty( referencedEntityAttributeName ) ) {
- manyToOneBinding.setReferencedPropertyName( referencedEntityAttributeName );
- manyToOneBinding.setReferenceToPrimaryKey( false );
- }
- else {
- manyToOneBinding.setReferenceToPrimaryKey( true );
- }
+ handleReferencedEntity( manyToOneBinding, referencedEntityName,
+ manyToOneSource.getReferencedEntityAttributeName() );
- final var fetchCharacteristics = manyToOneSource.getFetchCharacteristics();
- manyToOneBinding.setLazy( fetchCharacteristics.getFetchTiming() == FetchTiming.DELAYED );
- manyToOneBinding.setUnwrapProxy( fetchCharacteristics.isUnwrapProxies() );
- manyToOneBinding.setFetchMode(
- fetchCharacteristics.getFetchStyle() == FetchStyle.SELECT
- ? FetchMode.SELECT
- : FetchMode.JOIN
- );
+ handleFetchCharacteristics( manyToOneSource, manyToOneBinding );
if ( manyToOneSource.isEmbedXml() == Boolean.TRUE ) {
DEPRECATION_LOGGER.logDeprecationOfEmbedXmlSupport();
@@ -1893,7 +1913,8 @@ private void bindManyToOneAttribute(
manyToOneBinding.setIgnoreNotFound( manyToOneSource.isIgnoreNotFound() );
- setForeignKeyName( manyToOneBinding, manyToOneSource.getExplicitForeignKeyName() );
+ setForeignKeyName( manyToOneBinding,
+ manyToOneSource.getExplicitForeignKeyName() );
final var columnBinder = new ManyToOneColumnBinder(
sourceDocument,
@@ -1918,7 +1939,6 @@ private void bindManyToOneAttribute(
manyToOneBinding,
referencedEntityName
);
-
if ( canBindColumnsImmediately && fkSecondPass.canProcessImmediately() ) {
fkSecondPass.doSecondPass( null );
}
@@ -1927,7 +1947,19 @@ private void bindManyToOneAttribute(
}
}
- manyToOneBinding.setOnDeleteAction( getOnDeleteAction( manyToOneSource.isCascadeDeleteEnabled() ) );
+ manyToOneBinding.setOnDeleteAction( getOnDeleteAction( manyToOneSource ) );
+ }
+
+ private static void handleReferencedEntity(
+ ManyToOne manyToOneBinding, String referencedEntityName, String referencedEntityAttributeName) {
+ manyToOneBinding.setReferencedEntityName( referencedEntityName );
+ if ( isNotEmpty( referencedEntityAttributeName ) ) {
+ manyToOneBinding.setReferencedPropertyName( referencedEntityAttributeName );
+ manyToOneBinding.setReferenceToPrimaryKey( false );
+ }
+ else {
+ manyToOneBinding.setReferenceToPrimaryKey( true );
+ }
}
private static void setForeignKeyName(SimpleValue manyToOneBinding, String foreignKeyName) {
@@ -1946,13 +1978,9 @@ private Property createAnyAssociationAttribute(
SingularAttributeSourceAny anyMapping,
Any anyBinding,
String entityName) {
-
final var attributeRole = anyMapping.getAttributeRole();
-
bindAny( sourceDocument, anyMapping, anyBinding, attributeRole );
-
prepareValueTypeViaReflection( sourceDocument, anyBinding, entityName, anyMapping.getName(), attributeRole );
-
anyBinding.createForeignKey();
final var property = new Property();
@@ -1999,9 +2027,7 @@ private void bindAny(
anyMapping.getKeySource().getRelationalValueSources(),
anyBinding.getKeyMapping(),
true,
- context -> implicitNamingStrategy.determineAnyKeyColumnName(
- anyMapping.getKeySource()
- )
+ context -> implicitNamingStrategy.determineAnyKeyColumnName( anyMapping.getKeySource() )
);
}
@@ -2111,11 +2137,8 @@ private BasicType> resolveExplicitlyNamedAnyDiscriminatorType(
}
throw new org.hibernate.MappingException(
- String.format(
- Locale.ROOT,
- "Unable to resolve explicit any-discriminator type name - %s",
- typeName
- )
+ "Unable to resolve explicit any-discriminator type name:"
+ + typeName
);
}
}
@@ -2141,7 +2164,8 @@ private void prepareValueTypeViaReflection(
throw new MappingException(
String.format(
Locale.ENGLISH,
- "Attribute mapping must define a name attribute: containingClassName=[%s], propertyName=[%s], role=[%s]",
+ "Attribute mapping must define a name attribute:"
+ + " containingClassName=[%s], propertyName=[%s], role=[%s]",
containingClassName,
propertyName,
attributeRole.getFullPath()
@@ -2157,7 +2181,8 @@ private void prepareValueTypeViaReflection(
throw new MappingException(
String.format(
Locale.ENGLISH,
- "Error calling Value#setTypeUsingReflection: containingClassName=[%s], propertyName=[%s], role=[%s]",
+ "Error calling Value#setTypeUsingReflection:"
+ + " containingClassName=[%s], propertyName=[%s], role=[%s]",
containingClassName,
propertyName,
attributeRole.getFullPath()
@@ -2194,13 +2219,15 @@ private void bindProperty(
property.setUpdatable( singularAttributeSource.isUpdatable() );
// isBytecodeLazy() refers to whether a property is lazy via bytecode enhancement (not proxies)
property.setLazy( singularAttributeSource.isBytecodeLazy() );
- handleGenerationTiming( mappingDocument, propertySource, property, singularAttributeSource.getGenerationTiming() );
+ handleGenerationTiming( mappingDocument, propertySource, property,
+ singularAttributeSource.getGenerationTiming() );
}
property.setMetaAttributes( propertySource.getToolingHintContext().getMetaAttributeMap() );
if ( BOOT_LOGGER.isTraceEnabled() ) {
- BOOT_LOGGER.trace( "Mapped property: " + propertySource.getName() + " -> [" + columns( property.getValue() ) + "]" );
+ BOOT_LOGGER.trace( "Mapped property: " + propertySource.getName()
+ + " -> [" + columns( property.getValue() ) + "]" );
}
}
@@ -2362,8 +2389,9 @@ private static void bindVirtual(String role, Component componentBinding) {
// virtual (what used to be called embedded) is just a conceptual composition...
// for example
if ( componentBinding.getOwner().hasPojoRepresentation() ) {
- BOOT_LOGGER.bindingVirtualComponentToOwner( role, componentBinding.getOwner().getClassName() );
- componentBinding.setComponentClassName( componentBinding.getOwner().getClassName() );
+ final String ownerClassName = componentBinding.getOwner().getClassName();
+ BOOT_LOGGER.bindingVirtualComponentToOwner( role, ownerClassName );
+ componentBinding.setComponentClassName( ownerClassName );
}
else {
BOOT_LOGGER.bindingVirtualComponentAsDynamic( role );
@@ -2552,8 +2580,9 @@ private static TypeResolution resolveType(
else {
// the explicit name referred to a type-def
typeName = typeDefinition.getTypeImplementorClass().getName();
- if ( typeDefinition.getParameters() != null ) {
- typeParameters.putAll( typeDefinition.getParameters() );
+ final var parameters = typeDefinition.getParameters();
+ if ( parameters != null ) {
+ typeParameters.putAll( parameters );
}
}
@@ -2573,12 +2602,10 @@ private Table bindEntityTableSpecification(
final EntitySource entitySource,
PersistentClass entityDescriptor) {
final String contributorName = mappingDocument.getCurrentContributorName();
- final boolean isTable = tableSpecSource instanceof TableSource;
final boolean isAbstract = entityDescriptor.isAbstract() != null && entityDescriptor.isAbstract();
final Identifier logicalTableName;
final Table table;
- if ( isTable ) {
- final var tableSource = (TableSource) tableSpecSource;
+ if ( tableSpecSource instanceof TableSource tableSource ) {
logicalTableName = logicalTableName( mappingDocument, entitySource, tableSource );
table = tableForEntity(
tableSource,
@@ -2588,8 +2615,7 @@ private Table bindEntityTableSpecification(
isAbstract
);
}
- else {
- final var inlineViewSource = (InLineViewSource) tableSpecSource;
+ else if ( tableSpecSource instanceof InLineViewSource inlineViewSource ) {
logicalTableName = database.toIdentifier( inlineViewSource.getLogicalName() );
table = tableForSubselect(
inlineViewSource,
@@ -2599,6 +2625,9 @@ private Table bindEntityTableSpecification(
logicalTableName
);
}
+ else {
+ throw new AssertionFailure( "Unexpected table specification source type" );
+ }
final var metadataCollector = mappingDocument.getMetadataCollector();
@@ -2609,8 +2638,7 @@ private Table bindEntityTableSpecification(
superEntityTableXref( mappingDocument, entitySource, entityDescriptor, metadataCollector )
);
- if ( isTable ) {
- final var tableSource = (TableSource) tableSpecSource;
+ if ( tableSpecSource instanceof TableSource tableSource ) {
table.setRowId( tableSource.getRowId() );
final String checkConstraint = tableSource.getCheckConstraint();
if ( isNotEmpty( checkConstraint ) ) {
@@ -2805,7 +2833,6 @@ private void registerSecondPass(SecondPass secondPass, MetadataBuildingContext c
}
-
public static final class DelayedPropertyReferenceHandlerImpl
implements InFlightMetadataCollector.DelayedPropertyReferenceHandler {
public final String referencedEntityName;
@@ -2947,9 +2974,7 @@ private void bindCollectionTable() {
}
else {
final var tableSpecSource = pluralAttributeSource.getCollectionTableSpecificationSource();
- final Identifier logicalCatalogName = determineCatalogName( tableSpecSource );
- final Identifier logicalSchemaName = determineSchemaName( tableSpecSource );
- final var namespace = database.locateNamespace( logicalCatalogName, logicalSchemaName );
+ final var namespace = locateTableNamespace( tableSpecSource );
final Table collectionTable;
if ( tableSpecSource instanceof TableSource tableSource ) {
@@ -2963,19 +2988,21 @@ private void bindCollectionTable() {
)
);
}
- else {
+ else if ( tableSpecSource instanceof InLineViewSource inlineViewSource ) {
collectionTable = new Table(
metadataBuildingContext.getCurrentContributorName(),
namespace,
- ( (InLineViewSource) tableSpecSource ).getSelectStatement(),
+ inlineViewSource.getSelectStatement(),
false
);
}
+ else {
+ throw new AssertionFailure( "Unexpected table specification source type" );
+ }
collectionBinding.setCollectionTable( collectionTable );
}
-
final var collectionTable = collectionBinding.getCollectionTable();
if ( BOOT_LOGGER.isTraceEnabled() ) {
@@ -2984,36 +3011,33 @@ private void bindCollectionTable() {
collectionTable.getName() );
}
- if ( pluralAttributeSource.getCollectionTableComment() != null ) {
- collectionTable.setComment( pluralAttributeSource.getCollectionTableComment() );
+ final String tableComment = pluralAttributeSource.getCollectionTableComment();
+ if ( tableComment != null ) {
+ collectionTable.setComment( tableComment );
}
- if ( pluralAttributeSource.getCollectionTableCheck() != null ) {
- collectionTable.addCheckConstraint( pluralAttributeSource.getCollectionTableCheck() );
+ final String tableCheck = pluralAttributeSource.getCollectionTableCheck();
+ if ( tableCheck != null ) {
+ collectionTable.addCheckConstraint( tableCheck );
}
}
private Identifier logicalName(TableSource tableSource) {
- if ( isNotEmpty( tableSource.getExplicitTableName() ) ) {
- return toIdentifier( tableSource.getExplicitTableName(),
+ final String explicitTableName = tableSource.getExplicitTableName();
+ if ( isNotEmpty( explicitTableName ) ) {
+ return toIdentifier( explicitTableName,
mappingDocument.getEffectiveDefaults().isDefaultQuoteIdentifiers() );
}
else {
- final var owner = collectionBinding.getOwner();
- final var ownerEntityNaming = new EntityNamingSourceImpl(
- owner.getEntityName(),
- owner.getClassName(),
- owner.getJpaEntityName()
- );
final var implicitNamingSource =
new ImplicitCollectionTableNameSource() {
@Override
public Identifier getOwningPhysicalTableName() {
- return owner.getTable().getNameIdentifier();
+ return collectionBinding.getOwner().getTable().getNameIdentifier();
}
@Override
public EntityNaming getOwningEntityNaming() {
- return ownerEntityNaming;
+ return new EntityNamingSourceImpl( collectionBinding.getOwner() );
}
@Override
@@ -3037,10 +3061,11 @@ protected void createBackReferences() {
&& !collectionBinding.getKey().isNullable() ) {
// for non-inverse one-to-many, with a not-null fk, add a backref!
final var oneToMany = (OneToMany) collectionBinding.getElement();
- final String entityName = oneToMany.getReferencedEntityName();
- final var referenced = getReferencedEntityBinding( entityName );
+ final var referenced =
+ getReferencedEntityBinding( oneToMany.getReferencedEntityName() );
final var backref = new Backref();
- backref.setName( '_' + collectionBinding.getOwnerEntityName() + "." + pluralAttributeSource.getName() + "Backref" );
+ backref.setName( '_' + collectionBinding.getOwnerEntityName()
+ + "." + pluralAttributeSource.getName() + "Backref" );
backref.setOptional( true );
backref.setUpdatable( false );
backref.setSelectable( false );
@@ -3075,8 +3100,9 @@ protected void bindCollectionKey() {
collectionBinding.getCollectionTable(),
keyVal
);
- setForeignKeyName( key, keySource.getExplicitForeignKeyName() );
- key.setOnDeleteAction( getOnDeleteAction( pluralAttributeSource.getKeySource().isCascadeDeleteEnabled() ) );
+ setForeignKeyName( key,
+ keySource.getExplicitForeignKeyName() );
+ key.setOnDeleteAction( getOnDeleteAction( keySource ) );
// final ImplicitJoinColumnNameSource.Nature implicitNamingNature;
// if ( getPluralAttributeSource().getElementSource() instanceof PluralAttributeElementSourceManyToMany
@@ -3105,7 +3131,7 @@ protected void bindCollectionKey() {
}
protected void bindCollectionIdentifier() {
- final CollectionIdSource idSource = getPluralAttributeSource().getCollectionIdSource();
+ final var idSource = getPluralAttributeSource().getCollectionIdSource();
if ( idSource != null ) {
final var idBagBinding = (IdentifierCollection) getCollectionBinding();
final var idBinding = new BasicValue(
@@ -3142,158 +3168,106 @@ protected void bindCollectionIndex() {
}
protected void bindCollectionElement() {
- final PluralAttributeElementSource pluralElementSource = getPluralAttributeSource().getElementSource();
+ final var pluralElementSource = pluralAttributeSource.getElementSource();
if ( BOOT_LOGGER.isTraceEnabled() ) {
- BOOT_LOGGER.tracef(
- "Binding [%s] element type for a [%s]",
- pluralElementSource.getNature(),
- getPluralAttributeSource().getNature()
- );
+ BOOT_LOGGER.tracef( "Binding [%s] element type for a [%s]",
+ pluralElementSource.getNature(), pluralAttributeSource.getNature() );
}
- final var collectionBinding = getCollectionBinding();
- final var mappingDocument = getMappingDocument();
if ( pluralElementSource instanceof PluralAttributeElementSourceBasic elementSource ) {
- final var elementBinding =
- new BasicValue( mappingDocument, collectionBinding.getCollectionTable() );
-
- bindSimpleValueType(
- mappingDocument,
- elementSource.getExplicitHibernateTypeSource(),
- elementBinding
- );
-
- relationalObjectBinder.bindColumnsAndFormulas(
- this.mappingDocument,
- elementSource.getRelationalValueSources(),
- elementBinding,
- elementSource.areValuesNullableByDefault(),
- context -> context.getMetadataCollector().getDatabase()
- .toIdentifier( Collection.DEFAULT_ELEMENT_COLUMN_NAME )
- );
-
- collectionBinding.setElement( elementBinding );
- // Collection#setWhere is used to set the "where" clause that applies to the collection table
- // (the table containing the basic elements)
- // This "where" clause comes from the collection mapping; e.g.,
- collectionBinding.setWhere( getPluralAttributeSource().getWhere() );
+ bindBasicElement( elementSource );
}
else if ( pluralElementSource instanceof PluralAttributeElementSourceEmbedded elementSource ) {
- final var elementBinding = new Component( mappingDocument, collectionBinding );
-
- final var embeddableSource = elementSource.getEmbeddableSource();
- bindComponent(
- this.mappingDocument,
- embeddableSource,
- elementBinding,
- null,
- embeddableSource.getAttributePathBase().getProperty(),
- false
- );
-
- collectionBinding.setElement( elementBinding );
- // Collection#setWhere is used to set the "where" clause that applies to the collection table
- // (the table containing the embeddable elements)
- // This "where" clause comes from the collection mapping; e.g.,
- collectionBinding.setWhere( getPluralAttributeSource().getWhere() );
+ bindEmbeddedElement( elementSource );
}
else if ( pluralElementSource instanceof PluralAttributeElementSourceOneToMany elementSource ) {
- final var elementBinding =
- new OneToMany( mappingDocument, collectionBinding.getOwner() );
- this.collectionBinding.setElement( elementBinding );
-
- final var referencedEntityBinding =
- getReferencedEntityBinding( elementSource.getReferencedEntityName() );
-
- this.collectionBinding.setWhere(
- getNonEmptyOrConjunctionIfBothNonEmpty(
- referencedEntityBinding.getWhere(),
- getPluralAttributeSource().getWhere()
- )
- );
-
- elementBinding.setReferencedEntityName( referencedEntityBinding.getEntityName() );
- elementBinding.setAssociatedClass( referencedEntityBinding );
- elementBinding.setIgnoreNotFound( elementSource.isIgnoreNotFound() );
+ bindOneToManyElement( elementSource );
}
else if ( pluralElementSource instanceof PluralAttributeElementSourceManyToMany elementSource ) {
- final var elementBinding =
- new ManyToOne( mappingDocument, collectionBinding.getCollectionTable() );
-
- relationalObjectBinder.bindColumnsAndFormulas(
- mappingDocument,
- elementSource.getRelationalValueSources(),
- elementBinding,
- false,
- context -> context.getMetadataCollector().getDatabase()
- .toIdentifier( Collection.DEFAULT_ELEMENT_COLUMN_NAME )
- );
+ bindManyToManyElement( elementSource );
+ }
+ else if ( pluralElementSource instanceof PluralAttributeElementSourceManyToAny elementSource ) {
+ bindManyToAnyElement( elementSource );
+ }
+ }
- final var fetchCharacteristics = elementSource.getFetchCharacteristics();
- elementBinding.setLazy( fetchCharacteristics.getFetchTiming() != FetchTiming.IMMEDIATE );
- elementBinding.setFetchMode(
- fetchCharacteristics.getFetchStyle() == FetchStyle.SELECT
- ? FetchMode.SELECT
- : FetchMode.JOIN
- );
+ private void bindManyToAnyElement(PluralAttributeElementSourceManyToAny elementSource) {
+ final var elementBinding =
+ new Any( mappingDocument,
+ collectionBinding.getCollectionTable() );
+ bindAny( mappingDocument, elementSource, elementBinding,
+ pluralAttributeSource.getAttributeRole().append( "element" ) );
+ collectionBinding.setElement( elementBinding );
+ // Collection#setWhere is used to set the "where" clause that applies to the collection table
+ // (which is the join table for a many-to-any association).
+ // This "where" clause comes from the collection mapping; e.g.,
+ collectionBinding.setWhere( getPluralAttributeSource().getWhere() );
+ }
- setForeignKeyName( elementBinding, elementSource.getExplicitForeignKeyName() );
+ private void bindManyToManyElement(PluralAttributeElementSourceManyToMany elementSource) {
+ final var elementBinding =
+ new ManyToOne( mappingDocument,
+ collectionBinding.getCollectionTable() );
+ relationalObjectBinder.bindColumnsAndFormulas(
+ mappingDocument,
+ elementSource.getRelationalValueSources(),
+ elementBinding,
+ false,
+ context -> context.getMetadataCollector().getDatabase()
+ .toIdentifier( Collection.DEFAULT_ELEMENT_COLUMN_NAME )
+ );
+ handleFetchCharacteristics( elementSource, elementBinding );
+ setForeignKeyName( elementBinding,
+ elementSource.getExplicitForeignKeyName() );
+ final String referencedEntityName = elementSource.getReferencedEntityName();
+ handleReferencedEntity( elementBinding, referencedEntityName,
+ elementSource.getReferencedEntityAttributeName() );
+ collectionBinding.setElement( elementBinding );
+ final var referencedEntityBinding = getReferencedEntityBinding( referencedEntityName );
+ // Collection#setWhere is used to set the "where" clause that applies to the collection table
+ // (which is the join table for a many-to-many association).
+ // This "where" clause comes from the collection mapping; e.g.,
+ collectionBinding.setWhere( pluralAttributeSource.getWhere() );
+ collectionBinding.setManyToManyWhere(
+ getNonEmptyOrConjunctionIfBothNonEmpty(
+ referencedEntityBinding.getWhere(),
+ elementSource.getWhere()
+ )
+ );
+ collectionBinding.setManyToManyOrdering( elementSource.getOrder() );
+ bindManyToManyFilters( elementSource, mappingDocument, collectionBinding, elementBinding );
+ }
- final String referencedEntityName = elementSource.getReferencedEntityName();
- elementBinding.setReferencedEntityName( referencedEntityName );
- final String referencedEntityAttributeName = elementSource.getReferencedEntityAttributeName();
- if ( isNotEmpty( referencedEntityAttributeName ) ) {
- elementBinding.setReferencedPropertyName( referencedEntityAttributeName );
- elementBinding.setReferenceToPrimaryKey( false );
- }
- else {
- elementBinding.setReferenceToPrimaryKey( true );
+ private void bindManyToManyFilters(
+ PluralAttributeElementSourceManyToMany elementSource,
+ MappingDocument mappingDocument,
+ Collection collectionBinding,
+ ManyToOne elementBinding) {
+ if ( !isEmpty( elementSource.getFilterSources() )
+ || elementSource.getWhere() != null ) {
+ if ( collectionBinding.getFetchMode() == FetchMode.JOIN
+ && elementBinding.getFetchMode() != FetchMode.JOIN ) {
+ throw new MappingException(
+ String.format(
+ Locale.ENGLISH,
+ "many-to-many defining filter or where without join fetching is not " +
+ "valid within collection [%s] using join fetching",
+ getPluralAttributeSource().getAttributeRole().getFullPath()
+ ),
+ mappingDocument.getOrigin()
+ );
}
+ }
- collectionBinding.setElement( elementBinding );
-
- final PersistentClass referencedEntityBinding = getReferencedEntityBinding( referencedEntityName );
-
- // Collection#setWhere is used to set the "where" clause that applies to the collection table
- // (which is the join table for a many-to-many association).
- // This "where" clause comes from the collection mapping; e.g.,
- collectionBinding.setWhere( getPluralAttributeSource().getWhere() );
-
- collectionBinding.setManyToManyWhere(
- getNonEmptyOrConjunctionIfBothNonEmpty(
- referencedEntityBinding.getWhere(),
- elementSource.getWhere()
- )
- );
-
- collectionBinding.setManyToManyOrdering( elementSource.getOrder() );
-
- if ( !isEmpty( elementSource.getFilterSources() )
- || elementSource.getWhere() != null ) {
- if ( collectionBinding.getFetchMode() == FetchMode.JOIN
- && elementBinding.getFetchMode() != FetchMode.JOIN ) {
- throw new MappingException(
- String.format(
- Locale.ENGLISH,
- "many-to-many defining filter or where without join fetching is not " +
- "valid within collection [%s] using join fetching",
- getPluralAttributeSource().getAttributeRole().getFullPath()
- ),
- mappingDocument.getOrigin()
+ for ( var filterSource : elementSource.getFilterSources() ) {
+ if ( filterSource.getName() == null ) {
+ if ( BOOT_LOGGER.isTraceEnabled() ) {
+ BOOT_LOGGER.tracef(
+ "Encountered filter with no name associated with many-to-many [%s]; skipping",
+ getPluralAttributeSource().getAttributeRole().getFullPath()
);
}
}
-
- for ( var filterSource : elementSource.getFilterSources() ) {
- if ( filterSource.getName() == null ) {
- if ( BOOT_LOGGER.isTraceEnabled() ) {
- BOOT_LOGGER.tracef(
- "Encountered filter with no name associated with many-to-many [%s]; skipping",
- getPluralAttributeSource().getAttributeRole().getFullPath()
- );
- }
- continue;
- }
-
+ else {
if ( filterSource.getCondition() == null ) {
throw new MappingException(
String.format(
@@ -3305,7 +3279,6 @@ else if ( pluralElementSource instanceof PluralAttributeElementSourceManyToMany
mappingDocument.getOrigin()
);
}
-
if ( BOOT_LOGGER.isTraceEnabled() ) {
BOOT_LOGGER.tracef(
"Applying many-to-many filter [%s] as [%s] to collection [%s]",
@@ -3314,7 +3287,6 @@ else if ( pluralElementSource instanceof PluralAttributeElementSourceManyToMany
getPluralAttributeSource().getAttributeRole().getFullPath()
);
}
-
collectionBinding.addManyToManyFilter(
filterSource.getName(),
filterSource.getCondition(),
@@ -3324,20 +3296,67 @@ else if ( pluralElementSource instanceof PluralAttributeElementSourceManyToMany
);
}
}
- else if ( pluralElementSource instanceof PluralAttributeElementSourceManyToAny elementSource ) {
- final var elementBinding = new Any( mappingDocument, collectionBinding.getCollectionTable() );
- bindAny(
- this.mappingDocument,
- elementSource,
- elementBinding,
- getPluralAttributeSource().getAttributeRole().append( "element" )
- );
- collectionBinding.setElement( elementBinding );
- // Collection#setWhere is used to set the "where" clause that applies to the collection table
- // (which is the join table for a many-to-any association).
- // This "where" clause comes from the collection mapping; e.g.,
- collectionBinding.setWhere( getPluralAttributeSource().getWhere() );
- }
+ }
+
+ private void bindOneToManyElement(PluralAttributeElementSourceOneToMany elementSource) {
+ final var elementBinding =
+ new OneToMany( mappingDocument,
+ collectionBinding.getOwner() );
+ collectionBinding.setElement( elementBinding );
+ final var referencedEntityBinding =
+ getReferencedEntityBinding( elementSource.getReferencedEntityName() );
+ collectionBinding.setWhere(
+ getNonEmptyOrConjunctionIfBothNonEmpty(
+ referencedEntityBinding.getWhere(),
+ pluralAttributeSource.getWhere()
+ )
+ );
+ elementBinding.setReferencedEntityName( referencedEntityBinding.getEntityName() );
+ elementBinding.setAssociatedClass( referencedEntityBinding );
+ elementBinding.setIgnoreNotFound( elementSource.isIgnoreNotFound() );
+ }
+
+ private void bindEmbeddedElement(PluralAttributeElementSourceEmbedded elementSource) {
+ final var elementBinding = new Component( mappingDocument, collectionBinding );
+ final var embeddableSource = elementSource.getEmbeddableSource();
+ bindComponent( mappingDocument, embeddableSource, elementBinding, null,
+ embeddableSource.getAttributePathBase().getProperty(), false );
+ collectionBinding.setElement( elementBinding );
+ // Collection#setWhere is used to set the "where" clause that applies to the collection table
+ // (the table containing the embeddable elements)
+ // This "where" clause comes from the collection mapping; e.g.,
+ collectionBinding.setWhere( pluralAttributeSource.getWhere() );
+ }
+
+ private void bindBasicElement(PluralAttributeElementSourceBasic elementSource) {
+ final var elementBinding =
+ new BasicValue( mappingDocument,
+ collectionBinding.getCollectionTable() );
+ bindSimpleValueType( mappingDocument, elementSource.getExplicitHibernateTypeSource(), elementBinding );
+ relationalObjectBinder.bindColumnsAndFormulas(
+ mappingDocument,
+ elementSource.getRelationalValueSources(),
+ elementBinding,
+ elementSource.areValuesNullableByDefault(),
+ context -> context.getMetadataCollector().getDatabase()
+ .toIdentifier( Collection.DEFAULT_ELEMENT_COLUMN_NAME )
+ );
+ collectionBinding.setElement( elementBinding );
+ // Collection#setWhere is used to set the "where" clause that applies to the collection table
+ // (the table containing the basic elements)
+ // This "where" clause comes from the collection mapping; e.g.,
+ collectionBinding.setWhere( pluralAttributeSource.getWhere() );
+ }
+
+ private static void handleFetchCharacteristics(
+ PluralAttributeElementSourceManyToMany elementSource, ManyToOne elementBinding) {
+ final var characteristics = elementSource.getFetchCharacteristics();
+ elementBinding.setLazy( characteristics.getFetchTiming() != FetchTiming.IMMEDIATE );
+ elementBinding.setFetchMode(
+ characteristics.getFetchStyle() == FetchStyle.SELECT
+ ? FetchMode.SELECT
+ : FetchMode.JOIN
+ );
}
private PersistentClass getReferencedEntityBinding(String referencedEntityName) {
@@ -3352,7 +3371,7 @@ private PersistentClass getReferencedEntityBinding(String referencedEntityName)
getPluralAttributeSource().getAttributeRole().getFullPath(),
referencedEntityName
),
- getMappingDocument().getOrigin()
+ mappingDocument.getOrigin()
);
}
return entityBinding;
@@ -3453,9 +3472,12 @@ protected void createBackReferences() {
&& !indexIsFormula ) {
final var oneToMany = (OneToMany) collectionBinding.getElement();
final String entityName = oneToMany.getReferencedEntityName();
- final var referenced = getMappingDocument().getMetadataCollector().getEntityBinding( entityName );
+ final var referenced =
+ getMappingDocument().getMetadataCollector()
+ .getEntityBinding( entityName );
final var backref = new IndexBackref();
- backref.setName( '_' + collectionBinding.getOwnerEntityName() + "." + getPluralAttributeSource().getName() + "IndexBackref" );
+ backref.setName( '_' + collectionBinding.getOwnerEntityName()
+ + "." + getPluralAttributeSource().getName() + "IndexBackref" );
backref.setOptional( true );
backref.setUpdatable( false );
backref.setSelectable( false );
@@ -3532,9 +3554,12 @@ private void createIndexBackRef(
&& !collectionBinding.isInverse() ) {
final var oneToMany = (OneToMany) collectionBinding.getElement();
final String entityName = oneToMany.getReferencedEntityName();
- final var referenced = mappingDocument.getMetadataCollector().getEntityBinding( entityName );
+ final var referenced =
+ mappingDocument.getMetadataCollector()
+ .getEntityBinding( entityName );
final var backref = new IndexBackref();
- backref.setName( '_' + collectionBinding.getOwnerEntityName() + "." + pluralAttributeSource.getName() + "IndexBackref" );
+ backref.setName( '_' + collectionBinding.getOwnerEntityName()
+ + "." + pluralAttributeSource.getName() + "IndexBackref" );
backref.setOptional( true );
backref.setUpdatable( false );
backref.setSelectable( false );
@@ -3575,7 +3600,6 @@ protected void bindCollectionIndex() {
@Override
protected void createBackReferences() {
super.createBackReferences();
-
createIndexBackRef(
getMappingDocument(),
getPluralAttributeSource(),
@@ -3591,7 +3615,9 @@ public void bindListOrArrayIndex(
final var indexSource =
(PluralAttributeSequentialIndexSource)
attributeSource.getIndexSource();
- final var indexBinding = new BasicValue( mappingDocument, collectionBinding.getCollectionTable() );
+ final var indexBinding =
+ new BasicValue( mappingDocument,
+ collectionBinding.getCollectionTable() );
bindSimpleValueType( mappingDocument, indexSource.getTypeInformation(), indexBinding );
relationalObjectBinder.bindColumnsAndFormulas(
@@ -3624,70 +3650,108 @@ private void bindMapKey(
final org.hibernate.mapping.Map collectionBinding) {
final var indexSource = pluralAttributeSource.getIndexSource();
if ( indexSource instanceof PluralAttributeMapKeySourceBasic mapKeySource ) {
- final var value = new BasicValue( mappingDocument, collectionBinding.getCollectionTable() );
- bindSimpleValueType( mappingDocument, mapKeySource.getTypeInformation(), value );
- if ( !value.isTypeSpecified() ) {
- throw new MappingException(
- "map index element must specify a type: "
- + pluralAttributeSource.getAttributeRole().getFullPath(),
- mappingDocument.getOrigin()
- );
- }
-
- relationalObjectBinder.bindColumnsAndFormulas(
- mappingDocument,
- mapKeySource.getRelationalValueSources(),
- value,
- true,
- context -> database.toIdentifier( IndexedCollection.DEFAULT_INDEX_COLUMN_NAME )
- );
-
- collectionBinding.setIndex( value );
+ bindBasicMapKey( mappingDocument, pluralAttributeSource, collectionBinding, mapKeySource );
}
else if ( indexSource instanceof PluralAttributeMapKeySourceEmbedded mapKeySource ) {
- final var componentBinding = new Component( mappingDocument, collectionBinding );
- bindComponent(
- mappingDocument,
- mapKeySource.getEmbeddableSource(),
- componentBinding,
- null,
- pluralAttributeSource.getName(),
- false
- );
- collectionBinding.setIndex( componentBinding );
+ bindEmbeddedMapKey( mappingDocument, pluralAttributeSource, collectionBinding, mapKeySource );
}
else if ( indexSource instanceof PluralAttributeMapKeyManyToManySource mapKeySource ) {
- final var mapKeyBinding = new ManyToOne( mappingDocument, collectionBinding.getCollectionTable() );
+ bindManyToManyMapKey( mappingDocument, pluralAttributeSource, collectionBinding, mapKeySource );
+ }
+ else if ( indexSource instanceof PluralAttributeMapKeyManyToAnySource mapKeySource) {
+ bindManyToAnyMapKey( mappingDocument, pluralAttributeSource, collectionBinding, mapKeySource );
+ }
+ }
- mapKeyBinding.setReferencedEntityName( mapKeySource.getReferencedEntityName() );
+ private void bindManyToAnyMapKey(
+ MappingDocument mappingDocument,
+ IndexedPluralAttributeSource pluralAttributeSource,
+ org.hibernate.mapping.Map collectionBinding,
+ PluralAttributeMapKeyManyToAnySource mapKeySource) {
+ final var mapKeyBinding =
+ new Any( mappingDocument,
+ collectionBinding.getCollectionTable() );
+ bindAny( mappingDocument, mapKeySource, mapKeyBinding,
+ pluralAttributeSource.getAttributeRole().append( "key" ) );
+ collectionBinding.setIndex( mapKeyBinding );
+ }
- relationalObjectBinder.bindColumnsAndFormulas(
- mappingDocument,
- mapKeySource.getRelationalValueSources(),
- mapKeyBinding,
- true,
- context -> implicitNamingStrategy.determineMapKeyColumnName(
- new ImplicitMapKeyColumnNameSource() {
- @Override
- public AttributePath getPluralAttributePath() {
- return pluralAttributeSource.getAttributePath();
- }
+ private void bindManyToManyMapKey(
+ MappingDocument mappingDocument,
+ IndexedPluralAttributeSource pluralAttributeSource,
+ org.hibernate.mapping.Map collectionBinding,
+ PluralAttributeMapKeyManyToManySource mapKeySource) {
+ final var mapKeyBinding =
+ new ManyToOne( mappingDocument,
+ collectionBinding.getCollectionTable() );
- @Override
- public MetadataBuildingContext getBuildingContext() {
- return context;
- }
+ mapKeyBinding.setReferencedEntityName( mapKeySource.getReferencedEntityName() );
+
+ relationalObjectBinder.bindColumnsAndFormulas(
+ mappingDocument,
+ mapKeySource.getRelationalValueSources(),
+ mapKeyBinding,
+ true,
+ context -> implicitNamingStrategy.determineMapKeyColumnName(
+ new ImplicitMapKeyColumnNameSource() {
+ @Override
+ public AttributePath getPluralAttributePath() {
+ return pluralAttributeSource.getAttributePath();
}
- )
+
+ @Override
+ public MetadataBuildingContext getBuildingContext() {
+ return context;
+ }
+ }
+ )
+ );
+ collectionBinding.setIndex( mapKeyBinding );
+ }
+
+ private void bindEmbeddedMapKey(
+ MappingDocument mappingDocument,
+ IndexedPluralAttributeSource pluralAttributeSource,
+ org.hibernate.mapping.Map collectionBinding,
+ PluralAttributeMapKeySourceEmbedded mapKeySource) {
+ final var componentBinding = new Component( mappingDocument, collectionBinding );
+ bindComponent(
+ mappingDocument,
+ mapKeySource.getEmbeddableSource(),
+ componentBinding,
+ null,
+ pluralAttributeSource.getName(),
+ false
+ );
+ collectionBinding.setIndex( componentBinding );
+ }
+
+ private void bindBasicMapKey(
+ MappingDocument mappingDocument,
+ IndexedPluralAttributeSource pluralAttributeSource,
+ org.hibernate.mapping.Map collectionBinding,
+ PluralAttributeMapKeySourceBasic mapKeySource) {
+ final var value =
+ new BasicValue( mappingDocument,
+ collectionBinding.getCollectionTable() );
+ bindSimpleValueType( mappingDocument, mapKeySource.getTypeInformation(), value );
+ if ( !value.isTypeSpecified() ) {
+ throw new MappingException(
+ "map index element must specify a type: "
+ + pluralAttributeSource.getAttributeRole().getFullPath(),
+ mappingDocument.getOrigin()
);
- collectionBinding.setIndex( mapKeyBinding );
- }
- else if ( indexSource instanceof PluralAttributeMapKeyManyToAnySource mapKeySource) {
- final var mapKeyBinding = new Any( mappingDocument, collectionBinding.getCollectionTable() );
- bindAny( mappingDocument, mapKeySource, mapKeyBinding,
- pluralAttributeSource.getAttributeRole().append( "key" ) );
- collectionBinding.setIndex( mapKeyBinding );
}
+
+ relationalObjectBinder.bindColumnsAndFormulas(
+ mappingDocument,
+ mapKeySource.getRelationalValueSources(),
+ value,
+ true,
+ context -> database.toIdentifier( IndexedCollection.DEFAULT_INDEX_COLUMN_NAME )
+ );
+
+ collectionBinding.setIndex( value );
}
private class ManyToOneColumnBinder implements ImplicitColumnNamingSecondPass {
@@ -3727,7 +3791,8 @@ public boolean canProcessImmediately() {
}
final var referencedEntityBinding =
- mappingDocument.getMetadataCollector().getEntityBinding( referencedEntityName );
+ mappingDocument.getMetadataCollector()
+ .getEntityBinding( referencedEntityName );
if ( referencedEntityBinding == null ) {
return false;
}
@@ -3759,7 +3824,8 @@ public void doSecondPass(Map persistentClasses) {
// column making up the FK.
final var referencedEntityBinding =
- mappingDocument.getMetadataCollector().getEntityBinding( referencedEntityName );
+ mappingDocument.getMetadataCollector()
+ .getEntityBinding( referencedEntityName );
if ( referencedEntityBinding == null ) {
throw new AssertionFailure(
@@ -3810,7 +3876,8 @@ private ManyToOneFkSecondPass(
String referencedEntityName) {
if ( referencedEntityName == null ) {
throw new MappingException(
- "entity name referenced by many-to-one required [" + manyToOneSource.getAttributeRole().getFullPath() + "]",
+ "entity name referenced by many-to-one required ["
+ + manyToOneSource.getAttributeRole().getFullPath() + "]",
mappingDocument.getOrigin()
);
}
@@ -3841,7 +3908,9 @@ public void doSecondPass(Map persistentClasses) throws
manyToOneBinding.createForeignKey();
}
else {
- manyToOneBinding.createPropertyRefConstraints( mappingDocument.getMetadataCollector().getEntityBindingMap() );
+ manyToOneBinding.createPropertyRefConstraints(
+ mappingDocument.getMetadataCollector()
+ .getEntityBindingMap() );
}
}
@@ -3945,10 +4014,14 @@ public Identifier getUserProvidedIdentifier() {
}
}
);
- uniqueKey.setName( uniqueKeyName.render( mappingDocument.getMetadataCollector().getDatabase().getDialect() ) );
+ uniqueKey.setName( uniqueKeyName.render( getDialect() ) );
entityBinding.getTable().addUniqueKey( uniqueKey );
}
+
+ private Dialect getDialect() {
+ return mappingDocument.getMetadataCollector().getDatabase().getDialect();
+ }
}
private String columns(Value value) {
@@ -3962,7 +4035,7 @@ private String columns(Value value) {
return builder.toString();
}
- private static OnDeleteAction getOnDeleteAction(boolean entitySource) {
- return entitySource ? OnDeleteAction.CASCADE : OnDeleteAction.NO_ACTION;
+ private static OnDeleteAction getOnDeleteAction(ForeignKeyContributingSource entitySource) {
+ return entitySource.isCascadeDeleteEnabled() ? OnDeleteAction.CASCADE : OnDeleteAction.NO_ACTION;
}
}