This is an automated email from the ASF dual-hosted git repository. borinquenkid pushed a commit to branch 8.0.x-hibernate7 in repository https://gitbox.apache.org/repos/asf/grails-core.git
commit f5e79abf38a8b424993fef92ca4a76a92cb83160 Author: Walter Duque de Estrada <[email protected]> AuthorDate: Tue Feb 24 21:00:55 2026 -0600 moving methods down from GrailsHibernatePersistentProperty --- .../cfg/domainbinding/binder/PropertyBinder.java | 4 +- .../GrailsHibernatePersistentProperty.java | 80 ++-------------------- .../hibernate/HibernateAssociation.java | 14 ++++ .../hibernate/HibernateToManyProperty.java | 36 ++++++++++ .../hibernate/HibernateToOneProperty.java | 42 +++++++++++- .../secondpass/CollectionSecondPassBinder.java | 1 + .../secondpass/MapSecondPassBinder.java | 3 +- .../util/ColumnNameForPropertyAndPathFetcher.java | 1 - .../cfg/domainbinding/PropertyBinderSpec.groovy | 3 +- .../cfg/domainbinding/VersionBinderSpec.groovy | 2 +- 10 files changed, 106 insertions(+), 80 deletions(-) diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/PropertyBinder.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/PropertyBinder.java index 87ad5535bf..29fa22ccf5 100644 --- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/PropertyBinder.java +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/PropertyBinder.java @@ -25,6 +25,7 @@ import org.grails.datastore.mapping.reflect.EntityReflector; import org.grails.orm.hibernate.access.TraitPropertyAccessStrategy; import org.grails.orm.hibernate.cfg.PropertyConfig; import org.grails.orm.hibernate.cfg.domainbinding.hibernate.GrailsHibernatePersistentProperty; +import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateAssociation; import org.grails.orm.hibernate.cfg.domainbinding.util.CascadeBehaviorFetcher; import org.hibernate.boot.spi.AccessType; import org.hibernate.mapping.Property; @@ -60,7 +61,8 @@ public class PropertyBinder { config = new PropertyConfig(); } - if (persistentProperty.isBidirectionalManyToOneWithListMapping(prop)) { + if (persistentProperty instanceof HibernateAssociation assoc + && assoc.isBidirectionalManyToOneWithListMapping(prop)) { prop.setInsertable(false); prop.setUpdatable(false); } else { diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/GrailsHibernatePersistentProperty.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/GrailsHibernatePersistentProperty.java index f4630851dd..7f1b5f758b 100644 --- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/GrailsHibernatePersistentProperty.java +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/GrailsHibernatePersistentProperty.java @@ -18,7 +18,6 @@ */ package org.grails.orm.hibernate.cfg.domainbinding.hibernate; -import java.util.List; import java.util.Optional; import org.grails.datastore.mapping.model.PersistentProperty; import org.grails.datastore.mapping.model.types.Association; @@ -26,13 +25,9 @@ import org.grails.datastore.mapping.model.types.Embedded; import org.grails.orm.hibernate.cfg.ColumnConfig; import org.grails.orm.hibernate.cfg.JoinTable; import org.grails.orm.hibernate.cfg.Mapping; -import org.grails.orm.hibernate.cfg.PersistentEntityNamingStrategy; import org.grails.orm.hibernate.cfg.PropertyConfig; -import org.grails.orm.hibernate.cfg.domainbinding.binder.GrailsDomainBinder; import org.hibernate.MappingException; import org.hibernate.mapping.DependantValue; -import org.hibernate.mapping.IndexedCollection; -import org.hibernate.mapping.ManyToOne; import org.hibernate.mapping.Property; import org.hibernate.mapping.SimpleValue; import org.hibernate.usertype.UserCollectionType; @@ -40,12 +35,8 @@ import org.hibernate.usertype.UserCollectionType; /** Interface for Hibernate persistent properties */ public interface GrailsHibernatePersistentProperty extends PersistentProperty<PropertyConfig> { - default boolean isOwningSide() { - return this instanceof Association<?> association && association.isOwningSide(); - } - - default boolean isBidirectional() { - return this instanceof Association<?> association && association.isBidirectional(); + default boolean isBidirectionalManyToOneWithListMapping(Property prop) { + return false; } default HibernateAssociation getHibernateInverseSide() { @@ -54,9 +45,6 @@ public interface GrailsHibernatePersistentProperty extends PersistentProperty<Pr : null; } - default boolean isCircular() { - return this instanceof Association<?> association && association.isCircular(); - } default GrailsHibernatePersistentEntity getHibernateAssociatedEntity() { return this instanceof Association<?> association @@ -64,10 +52,6 @@ public interface GrailsHibernatePersistentProperty extends PersistentProperty<Pr : null; } - default boolean isBidirectionalOneToManyMap() { - return this instanceof Association<?> association && association.isBidirectionalOneToManyMap(); - } - /** * @return The type name */ @@ -151,26 +135,14 @@ public interface GrailsHibernatePersistentProperty extends PersistentProperty<Pr } default boolean isHibernateOneToOne() { - validateAssociation(); - return this instanceof org.grails.datastore.mapping.model.types.OneToOne association - && (association.canBindOneToOneWithSingleColumnAndForeignKey() - || (association.isHasOne() - && association.isBidirectional() - && association.getInverseSide() != null)); + return false; } default boolean isHibernateManyToOne() { - validateAssociation(); - if (!(this instanceof Association)) { - return false; - } - return this instanceof org.grails.datastore.mapping.model.types.ManyToOne - || (this instanceof org.grails.datastore.mapping.model.types.OneToOne - && !isHibernateOneToOne()); + return false; } default boolean isEmbedded() { - validateAssociation(); return this instanceof Embedded; } @@ -197,36 +169,9 @@ public interface GrailsHibernatePersistentProperty extends PersistentProperty<Pr return "serializable".equals(getTypeName()); } - default String getIndexColumnType(String defaultType) { - return Optional.ofNullable(getMappedForm()) - .map(PropertyConfig::getIndexColumn) - .map(ic -> getTypeName(ic, getHibernateOwner().getMappedForm())) - .orElse(defaultType); - } - - default String getIndexColumnName(PersistentEntityNamingStrategy namingStrategy) { - return Optional.ofNullable(getMappedForm()) - .map(PropertyConfig::getIndexColumn) - .map(PropertyConfig::getColumn) - .orElseGet( - () -> - namingStrategy.resolveColumnName(getName()) - + GrailsDomainBinder.UNDERSCORE - + IndexedCollection.DEFAULT_INDEX_COLUMN_NAME); - } - - default String getMapElementName(PersistentEntityNamingStrategy namingStrategy) { - return Optional.ofNullable(getMappedForm()) - .map(PropertyConfig::getJoinTable) - .map(JoinTable::getColumn) - .map(ColumnConfig::getName) - .orElseGet( - () -> - namingStrategy.resolveColumnName(getName()) - + GrailsDomainBinder.UNDERSCORE - + IndexedCollection.DEFAULT_ELEMENT_COLUMN_NAME); - } - + /** + * @return true if the property has a join key mapping + */ default boolean isJoinKeyMapped() { return getMappedForm() != null && getMappedForm().hasJoinKeyMapping() @@ -251,17 +196,6 @@ public interface GrailsHibernatePersistentProperty extends PersistentProperty<Pr .orElseGet(this::getMappedColumnName)); } - default boolean isBidirectionalManyToOneWithListMapping(Property prop) { - if (this instanceof Association<?> association) { - return association.isBidirectional() - && association.getInverseSide() != null - && List.class.isAssignableFrom(this.getType()) - && prop != null - && prop.getValue() instanceof ManyToOne; - } - return false; - } - /** * @param simpleValue The Hibernate simple value * @return The type name diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateAssociation.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateAssociation.java index b894cbbcc4..77bb386634 100644 --- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateAssociation.java +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateAssociation.java @@ -18,6 +18,10 @@ */ package org.grails.orm.hibernate.cfg.domainbinding.hibernate; +import java.util.List; +import org.hibernate.mapping.ManyToOne; +import org.hibernate.mapping.Property; + /** * Common interface for all Hibernate association properties (both ToOne and ToMany). Extends * {@link GrailsHibernatePersistentProperty} and declares the key {@link @@ -42,6 +46,8 @@ public interface HibernateAssociation extends GrailsHibernatePersistentProperty boolean isCircular(); + boolean isBidirectionalOneToManyMap(); + // --- Hibernate-typed overrides, removing instanceof guards --- /** Returns the inverse side as a {@link HibernateAssociation}, eliminating cast at call sites. */ @@ -54,4 +60,12 @@ public interface HibernateAssociation extends GrailsHibernatePersistentProperty default GrailsHibernatePersistentEntity getHibernateAssociatedEntity() { return (GrailsHibernatePersistentEntity) getAssociatedEntity(); } + + default boolean isBidirectionalManyToOneWithListMapping(Property prop) { + return isBidirectional() + && getInverseSide() != null + && List.class.isAssignableFrom(getType()) + && prop != null + && prop.getValue() instanceof ManyToOne; + } } diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateToManyProperty.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateToManyProperty.java index 4e92e2b190..f664d16f33 100644 --- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateToManyProperty.java +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateToManyProperty.java @@ -21,8 +21,13 @@ package org.grails.orm.hibernate.cfg.domainbinding.hibernate; import java.util.Map; import org.grails.datastore.mapping.model.types.Basic; import org.grails.datastore.mapping.model.types.mapping.PropertyWithMapping; +import org.grails.orm.hibernate.cfg.ColumnConfig; +import org.grails.orm.hibernate.cfg.JoinTable; +import org.grails.orm.hibernate.cfg.PersistentEntityNamingStrategy; import org.grails.orm.hibernate.cfg.PropertyConfig; +import org.grails.orm.hibernate.cfg.domainbinding.binder.GrailsDomainBinder; import org.hibernate.FetchMode; +import org.hibernate.mapping.IndexedCollection; import org.springframework.util.StringUtils; /** Marker interface for Hibernate to-many associations */ @@ -53,6 +58,7 @@ public interface HibernateToManyProperty return getMappedForm().getLazy(); } + /** * @return Whether the collection should be bound with a foreign key */ @@ -63,4 +69,34 @@ public interface HibernateToManyProperty && !(this instanceof HibernateManyToManyProperty) && !(this instanceof Basic); } + + default String getIndexColumnType(String defaultType) { + return java.util.Optional.ofNullable(getMappedForm()) + .map(PropertyConfig::getIndexColumn) + .map(ic -> getTypeName(ic, getHibernateOwner().getMappedForm())) + .orElse(defaultType); + } + + default String getIndexColumnName(PersistentEntityNamingStrategy namingStrategy) { + return java.util.Optional.ofNullable(getMappedForm()) + .map(PropertyConfig::getIndexColumn) + .map(PropertyConfig::getColumn) + .orElseGet( + () -> + namingStrategy.resolveColumnName(getName()) + + GrailsDomainBinder.UNDERSCORE + + IndexedCollection.DEFAULT_INDEX_COLUMN_NAME); + } + + default String getMapElementName(PersistentEntityNamingStrategy namingStrategy) { + return java.util.Optional.ofNullable(getMappedForm()) + .map(PropertyConfig::getJoinTable) + .map(JoinTable::getColumn) + .map(ColumnConfig::getName) + .orElseGet( + () -> + namingStrategy.resolveColumnName(getName()) + + GrailsDomainBinder.UNDERSCORE + + IndexedCollection.DEFAULT_ELEMENT_COLUMN_NAME); + } } diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateToOneProperty.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateToOneProperty.java index 12471c35ab..8d9f7374bb 100644 --- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateToOneProperty.java +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateToOneProperty.java @@ -18,8 +18,48 @@ */ package org.grails.orm.hibernate.cfg.domainbinding.hibernate; +import org.grails.datastore.mapping.model.types.OneToOne; +import org.hibernate.MappingException; +import org.hibernate.mapping.ManyToOne; +import org.hibernate.mapping.Property; + /** * Marker interface for Hibernate to-one associations ({@link HibernateManyToOneProperty} and * {@link HibernateOneToOneProperty}). Parallel to {@link HibernateToManyProperty}. */ -public interface HibernateToOneProperty extends HibernateAssociation {} +public interface HibernateToOneProperty extends HibernateAssociation { + + default void validateAssociation() { + if (getUserType() != null) { + throw new MappingException( + "Cannot bind association property [" + + getName() + + "] of type [" + + getType() + + "] to a user type"); + } + if (this instanceof OneToOne oneToOne) { + if (oneToOne.isHasOne() && !oneToOne.isBidirectional()) { + throw new MappingException( + "hasOne property [" + + getName() + + "] is not bidirectional. Specify the other side of the relationship!"); + } + } + } + + default boolean isHibernateOneToOne() { + validateAssociation(); + return this instanceof OneToOne association + && (association.canBindOneToOneWithSingleColumnAndForeignKey() + || (association.isHasOne() + && association.isBidirectional() + && association.getInverseSide() != null)); + } + + default boolean isHibernateManyToOne() { + validateAssociation(); + return this instanceof org.grails.datastore.mapping.model.types.ManyToOne + || (this instanceof OneToOne && !isHibernateOneToOne()); + } +} diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionSecondPassBinder.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionSecondPassBinder.java index e452c90536..d73ebead18 100644 --- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionSecondPassBinder.java +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionSecondPassBinder.java @@ -26,6 +26,7 @@ import java.util.Map; import java.util.Set; import org.grails.datastore.mapping.model.DatastoreConfigurationException; import org.grails.datastore.mapping.model.config.GormProperties; +import org.grails.datastore.mapping.model.types.Association; import org.grails.orm.hibernate.cfg.domainbinding.binder.CollectionForPropertyConfigBinder; import org.grails.orm.hibernate.cfg.domainbinding.binder.ManyToOneBinder; import org.grails.orm.hibernate.cfg.domainbinding.binder.SimpleValueColumnBinder; diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/MapSecondPassBinder.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/MapSecondPassBinder.java index 3e02c8a89b..2926a3a946 100644 --- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/MapSecondPassBinder.java +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/MapSecondPassBinder.java @@ -27,7 +27,6 @@ import org.grails.orm.hibernate.cfg.PersistentEntityNamingStrategy; import org.grails.orm.hibernate.cfg.PropertyConfig; import org.grails.orm.hibernate.cfg.domainbinding.binder.ColumnConfigToColumnBinder; import org.grails.orm.hibernate.cfg.domainbinding.binder.SimpleValueColumnBinder; -import org.grails.orm.hibernate.cfg.domainbinding.hibernate.GrailsHibernatePersistentProperty; import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateManyToManyProperty; import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateOneToManyProperty; import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateToManyProperty; @@ -72,7 +71,7 @@ public class MapSecondPassBinder { collectionSecondPassBinder.bindCollectionSecondPass(property, mappings, persistentClasses, map); SimpleValue value = new BasicValue(metadataBuildingContext, map.getCollectionTable()); - String type = ((GrailsHibernatePersistentProperty) property).getIndexColumnType("string"); + String type = property.getIndexColumnType("string"); String columnName1 = property.getIndexColumnName(namingStrategy); simpleValueColumnBinder.bindSimpleValue(value, type, columnName1, true); PropertyConfig mappedForm = property.getMappedForm(); diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/util/ColumnNameForPropertyAndPathFetcher.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/util/ColumnNameForPropertyAndPathFetcher.java index 84c2ac3e8e..e0fde7a372 100644 --- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/util/ColumnNameForPropertyAndPathFetcher.java +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/util/ColumnNameForPropertyAndPathFetcher.java @@ -23,7 +23,6 @@ import org.grails.orm.hibernate.cfg.ColumnConfig; import org.grails.orm.hibernate.cfg.GrailsHibernateUtil; import org.grails.orm.hibernate.cfg.PersistentEntityNamingStrategy; import org.grails.orm.hibernate.cfg.domainbinding.hibernate.GrailsHibernatePersistentProperty; - public class ColumnNameForPropertyAndPathFetcher { private final PersistentEntityNamingStrategy namingStrategy; diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/PropertyBinderSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/PropertyBinderSpec.groovy index 59dbd28ab2..1072d0f674 100644 --- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/PropertyBinderSpec.groovy +++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/PropertyBinderSpec.groovy @@ -6,6 +6,7 @@ import org.grails.datastore.mapping.model.MappingContext import org.grails.datastore.mapping.model.PersistentEntity import org.grails.datastore.mapping.model.types.Association import org.grails.orm.hibernate.cfg.domainbinding.hibernate.GrailsHibernatePersistentProperty +import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateAssociation import org.grails.orm.hibernate.cfg.PropertyConfig import spock.lang.Unroll @@ -29,7 +30,7 @@ class PropertyBinderSpec extends HibernateGormDatastoreSpec { def cascadeBehaviorFetcher = Mock(CascadeBehaviorFetcher) def binder = new PropertyBinder(cascadeBehaviorFetcher) - def persistentProperty = Mock(GrailsHibernatePersistentProperty) + def persistentProperty = Mock(GrailsHibernatePersistentProperty, additionalInterfaces: [HibernateAssociation]) def value = Mock(Value) def config = Mock(PropertyConfig) diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/VersionBinderSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/VersionBinderSpec.groovy index fe1624dad3..633fdd9067 100644 --- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/VersionBinderSpec.groovy +++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/VersionBinderSpec.groovy @@ -107,6 +107,6 @@ class VersionBinderSpec extends HibernateGormDatastoreSpec { @Override EntityReflector.PropertyWriter getWriter() { null } @Override String getOwnerClassName() { "Test" } @Override boolean isLazyAble() { false } - @Override boolean isBidirectionalManyToOneWithListMapping(Property prop) { false } + boolean isBidirectionalManyToOneWithListMapping(Property prop) { false } } }
