You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@grails.apache.org by bo...@apache.org on 2026/04/06 19:16:53 UTC
(grails-core) 03/12: H7 Features & Refactoring * Hierarchy-Based Binding: Refactored CollectionSecondPassBinder and CollectionMultiTenantFilterBinder to use the HibernateToManyEntityProperty and HibernateToManyCollectionProperty sub-interfaces for logical grouping. * Property API Extension: Added isManyToMany() and isOneToMany() default methods to HibernateToManyProperty, replacing brittle implementation-level checks in the binders. * Unified Enum Detection: Implemented a default is [...]
This is an automated email from the ASF dual-hosted git repository.
borinquenkid pushed a commit to branch 8.0.x-hibernate7-dev
in repository https://gitbox.apache.org/repos/asf/grails-core.git
commit f6e917712682b5c70ee001c357e6e695d18fa17f
Author: Walter Duque de Estrada <wb...@mac.com>
AuthorDate: Sat Apr 4 18:49:58 2026 -0500
H7 Features & Refactoring
* Hierarchy-Based Binding: Refactored CollectionSecondPassBinder and CollectionMultiTenantFilterBinder to use the HibernateToManyEntityProperty and HibernateToManyCollectionProperty sub-interfaces
for logical grouping.
* Property API Extension: Added isManyToMany() and isOneToMany() default methods to HibernateToManyProperty, replacing brittle implementation-level checks in the binders.
* Unified Enum Detection: Implemented a default isEnum() method in the HibernatePersistentProperty base interface to provide a consistent classification API across all property types.
---
.../cfg/domainbinding/binder/CollectionBinder.java | 10 +-
.../hibernate/HibernateAssociation.java | 2 +-
.../hibernate/HibernateBasicProperty.java | 2 +-
.../HibernateEmbeddedCollectionProperty.java | 2 +-
.../hibernate/HibernateManyToManyProperty.java | 2 +-
.../hibernate/HibernateOneToManyProperty.java | 2 +-
.../hibernate/HibernatePersistentProperty.java | 7 +
.../HibernateToManyCollectionProperty.java | 5 +
...rty.java => HibernateToManyEntityProperty.java} | 2 +-
.../hibernate/HibernateToManyProperty.java | 12 +-
...der.java => CollectionEntityOrderByBinder.java} | 10 +-
.../CollectionMultiTenantFilterBinder.java | 19 ++-
.../secondpass/CollectionSecondPassBinder.java | 33 ++---
.../HibernatePersistentPropertySpec.groovy | 153 ++++++++++-----------
.../BidirectionalMapElementBinderSpec.groovy | 2 +-
...vy => CollectionEntityOrderByBinderSpec.groovy} | 13 +-
.../CollectionSecondPassBinderSpec.groovy | 18 +--
.../datastore/mapping/model/types/Association.java | 2 +-
18 files changed, 156 insertions(+), 140 deletions(-)
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/CollectionBinder.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/CollectionBinder.java
index 04c8aed198..c1f69d73e3 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/CollectionBinder.java
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/CollectionBinder.java
@@ -32,7 +32,7 @@ import org.grails.orm.hibernate.cfg.PersistentEntityNamingStrategy;
import org.grails.orm.hibernate.cfg.PropertyConfig;
import org.grails.orm.hibernate.cfg.domainbinding.collectionType.CollectionHolder;
import org.grails.orm.hibernate.cfg.domainbinding.collectionType.CollectionType;
-import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateCollectionProperty;
+import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateToManyEntityProperty;
import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernatePersistentProperty;
import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateToManyProperty;
import org.grails.orm.hibernate.cfg.domainbinding.secondpass.BasicCollectionElementBinder;
@@ -41,7 +41,7 @@ import org.grails.orm.hibernate.cfg.domainbinding.secondpass.BidirectionalOneToM
import org.grails.orm.hibernate.cfg.domainbinding.secondpass.CollectionKeyBinder;
import org.grails.orm.hibernate.cfg.domainbinding.secondpass.CollectionKeyColumnUpdater;
import org.grails.orm.hibernate.cfg.domainbinding.secondpass.CollectionMultiTenantFilterBinder;
-import org.grails.orm.hibernate.cfg.domainbinding.secondpass.CollectionOrderByBinder;
+import org.grails.orm.hibernate.cfg.domainbinding.secondpass.CollectionEntityOrderByBinder;
import org.grails.orm.hibernate.cfg.domainbinding.secondpass.CollectionSecondPassBinder;
import org.grails.orm.hibernate.cfg.domainbinding.secondpass.CollectionWithJoinTableBinder;
import org.grails.orm.hibernate.cfg.domainbinding.secondpass.DependentKeyValueBinder;
@@ -119,7 +119,7 @@ public class CollectionBinder {
collectionForPropertyConfigBinder,
new BidirectionalMapElementBinder(manyToOneBinder, collectionForPropertyConfigBinder),
new ManyToManyElementBinder(manyToOneBinder, collectionForPropertyConfigBinder),
- new CollectionOrderByBinder(),
+ new CollectionEntityOrderByBinder(),
new CollectionMultiTenantFilterBinder(new DefaultColumnNameFetcher(namingStrategy)));
this.listSecondPassBinder = new ListSecondPassBinder(
metadataBuildingContext, namingStrategy, collectionSecondPassBinder, simpleValueColumnBinder, mappings);
@@ -167,7 +167,7 @@ public class CollectionBinder {
if (property.shouldBindWithForeignKey()) {
OneToMany oneToMany = new OneToMany(metadataBuildingContext, collection.getOwner());
collection.setElement(oneToMany);
- bindOneToMany((HibernateCollectionProperty) property, oneToMany);
+ bindOneToMany((HibernateToManyEntityProperty) property, oneToMany);
} else {
bindCollectionTable(property, _persistentClass.getTable());
@@ -203,7 +203,7 @@ public class CollectionBinder {
return property.getName();
}
- private void bindOneToMany(HibernateCollectionProperty currentGrailsProp, OneToMany one) {
+ private void bindOneToMany(HibernateToManyEntityProperty currentGrailsProp, OneToMany one) {
one.setReferencedEntityName(
currentGrailsProp.getHibernateAssociatedEntity().getName());
one.setIgnoreNotFound(true);
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 800ec30d11..6e74814f07 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
@@ -53,7 +53,7 @@ public interface HibernateAssociation extends HibernatePersistentProperty {
boolean isCircular();
- boolean isBidirectionalOneToManyMap();
+ boolean isBidirectionalToManyMap();
/**
* Returns the nullable value for the FK column when this property is an association without a
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateBasicProperty.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateBasicProperty.java
index 16d34ab72c..565781defc 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateBasicProperty.java
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateBasicProperty.java
@@ -27,7 +27,7 @@ import org.grails.datastore.mapping.model.types.mapping.BasicWithMapping;
import org.grails.orm.hibernate.cfg.PropertyConfig;
/** Hibernate implementation of {@link org.grails.datastore.mapping.model.types.Basic} */
-public class HibernateBasicProperty extends BasicWithMapping<PropertyConfig> implements HibernateToManyProperty {
+public class HibernateBasicProperty extends BasicWithMapping<PropertyConfig> implements HibernateToManyCollectionProperty {
private Collection collection;
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateEmbeddedCollectionProperty.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateEmbeddedCollectionProperty.java
index fb6286ada8..0769b42ba6 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateEmbeddedCollectionProperty.java
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateEmbeddedCollectionProperty.java
@@ -31,7 +31,7 @@ import org.grails.orm.hibernate.cfg.PropertyConfig;
* Hibernate implementation of {@link org.grails.datastore.mapping.model.types.EmbeddedCollection}
*/
public class HibernateEmbeddedCollectionProperty extends EmbeddedCollectionWithMapping<PropertyConfig>
- implements HibernateToManyProperty {
+ implements HibernateToManyCollectionProperty {
private Collection collection;
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateManyToManyProperty.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateManyToManyProperty.java
index 7e743a40ee..488655ba96 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateManyToManyProperty.java
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateManyToManyProperty.java
@@ -29,7 +29,7 @@ import org.grails.orm.hibernate.cfg.PropertyConfig;
/** Hibernate implementation of {@link org.grails.datastore.mapping.model.types.ManyToMany} */
public class HibernateManyToManyProperty extends ManyToManyWithMapping<PropertyConfig>
- implements HibernateCollectionProperty {
+ implements HibernateToManyEntityProperty {
private Collection collection;
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateOneToManyProperty.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateOneToManyProperty.java
index a194983338..fc8bda609a 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateOneToManyProperty.java
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateOneToManyProperty.java
@@ -30,7 +30,7 @@ import org.grails.orm.hibernate.cfg.PropertyConfig;
/** Hibernate implementation of {@link org.grails.datastore.mapping.model.types.OneToMany} */
public class HibernateOneToManyProperty extends OneToManyWithMapping<PropertyConfig>
- implements HibernateCollectionProperty {
+ implements HibernateToManyEntityProperty {
private Collection collection;
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernatePersistentProperty.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernatePersistentProperty.java
index 6d55fe32f6..dc31cdb3cf 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernatePersistentProperty.java
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernatePersistentProperty.java
@@ -134,6 +134,13 @@ public interface HibernatePersistentProperty extends PersistentProperty<Property
return Optional.ofNullable(getType()).map(Class::isEnum).orElse(false);
}
+ /**
+ * @return Whether this property is an enum property.
+ */
+ default boolean isEnum() {
+ return this instanceof HibernateEnumProperty;
+ }
+
default boolean isValidHibernateOneToOne() {
return false;
}
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateToManyCollectionProperty.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateToManyCollectionProperty.java
new file mode 100644
index 0000000000..add950220d
--- /dev/null
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateToManyCollectionProperty.java
@@ -0,0 +1,5 @@
+package org.grails.orm.hibernate.cfg.domainbinding.hibernate;
+
+public interface HibernateToManyCollectionProperty extends HibernateToManyProperty{
+
+}
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateCollectionProperty.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateToManyEntityProperty.java
similarity index 94%
rename from grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateCollectionProperty.java
rename to grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateToManyEntityProperty.java
index 01a0dca341..6f9c704436 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateCollectionProperty.java
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateToManyEntityProperty.java
@@ -24,7 +24,7 @@ import org.hibernate.mapping.PersistentClass;
/**
* Marker interface for Hibernate Collections
*/
-public interface HibernateCollectionProperty extends HibernateToManyProperty {
+public interface HibernateToManyEntityProperty extends HibernateToManyProperty {
@Override
HibernatePersistentEntity getHibernateAssociatedEntity();
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 288a626121..4976eb08d3 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
@@ -79,6 +79,14 @@ public interface HibernateToManyProperty extends PropertyWithMapping<PropertyCon
return this instanceof Basic;
}
+ default boolean isManyToMany() {
+ return this instanceof HibernateManyToManyProperty;
+ }
+
+ default boolean isOneToMany() {
+ return this instanceof HibernateOneToManyProperty;
+ }
+
/**
* Returns the component type for basic (scalar/enum) collections, or {@code null} if this is not
* a basic collection.
@@ -223,8 +231,10 @@ public interface HibernateToManyProperty extends PropertyWithMapping<PropertyCon
return Optional.ofNullable(getHibernateMappedForm()).map(PropertyConfig::getJoinTableColumnConfig);
}
+ @Override
default boolean isEnum() {
- return getComponentType().isEnum();
+ Class<?> componentType = getComponentType();
+ return componentType != null && componentType.isEnum();
}
/**
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionOrderByBinder.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionEntityOrderByBinder.java
similarity index 93%
rename from grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionOrderByBinder.java
rename to grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionEntityOrderByBinder.java
index 60da182a0c..ab9a343b9a 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionOrderByBinder.java
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionEntityOrderByBinder.java
@@ -27,24 +27,24 @@ import org.hibernate.mapping.PersistentClass;
import org.grails.orm.hibernate.cfg.domainbinding.binder.CollectionForPropertyConfigBinder;
import org.grails.orm.hibernate.cfg.domainbinding.hibernate.GrailsHibernatePersistentEntity;
-import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateCollectionProperty;
+import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateToManyEntityProperty;
import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernatePersistentProperty;
import org.grails.orm.hibernate.cfg.domainbinding.util.OrderByClauseBuilder;
/** Binds the order-by clause and discriminator where condition to a collection. */
-public class CollectionOrderByBinder {
+public class CollectionEntityOrderByBinder {
private final OrderByClauseBuilder orderByClauseBuilder;
private final CollectionForPropertyConfigBinder collectionForPropertyConfigBinder;
- /** Creates a new {@link CollectionOrderByBinder} instance. */
- public CollectionOrderByBinder() {
+ /** Creates a new {@link CollectionEntityOrderByBinder} instance. */
+ public CollectionEntityOrderByBinder() {
this.orderByClauseBuilder = new OrderByClauseBuilder();
this.collectionForPropertyConfigBinder = new CollectionForPropertyConfigBinder();
}
/** Binds the order-by clause and discriminator where condition to the given collection. */
- public void bind(HibernateCollectionProperty property) {
+ public void bind(HibernateToManyEntityProperty property) {
Collection collection = property.getCollection();
PersistentClass associatedClass = property.getAssociatedClass();
GrailsHibernatePersistentEntity referenced = property.getHibernateAssociatedEntity();
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionMultiTenantFilterBinder.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionMultiTenantFilterBinder.java
index 25f006d573..f8be0b2338 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionMultiTenantFilterBinder.java
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionMultiTenantFilterBinder.java
@@ -24,7 +24,9 @@ import java.util.Optional;
import org.hibernate.mapping.Collection;
import org.grails.datastore.mapping.model.config.GormProperties;
+import org.grails.orm.hibernate.cfg.domainbinding.hibernate.GrailsHibernatePersistentEntity;
import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateManyToManyProperty;
+import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateToManyEntityProperty;
import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateToManyProperty;
import org.grails.orm.hibernate.cfg.domainbinding.util.DefaultColumnNameFetcher;
@@ -40,12 +42,13 @@ public class CollectionMultiTenantFilterBinder {
/** Applies the multi-tenant filter to the collection if the associated entity is multi-tenant. */
public void bind(HibernateToManyProperty property) {
- Collection collection = property.getCollection();
- Optional.ofNullable(property.getHibernateAssociatedEntity())
- .filter(referenced -> !(property instanceof HibernateManyToManyProperty) && referenced.isMultiTenant())
- .map(referenced -> referenced.getMultiTenantFilterCondition(defaultColumnNameFetcher))
- .ifPresent(filterCondition -> {
- if (property.isUnidirectionalOneToMany()) {
+ if (property instanceof HibernateToManyEntityProperty entityProperty) {
+ GrailsHibernatePersistentEntity referenced = entityProperty.getHibernateAssociatedEntity();
+ if (entityProperty.isOneToMany() && referenced.isMultiTenant()) {
+ String filterCondition = referenced.getMultiTenantFilterCondition(defaultColumnNameFetcher);
+ if (filterCondition != null) {
+ Collection collection = property.getCollection();
+ if (entityProperty.isUnidirectionalOneToMany()) {
collection.addManyToManyFilter(
GormProperties.TENANT_IDENTITY,
filterCondition,
@@ -60,6 +63,8 @@ public class CollectionMultiTenantFilterBinder {
Collections.emptyMap(),
Collections.emptyMap());
}
- });
+ }
+ }
+ }
}
}
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 4333149d1d..8b2cb7d749 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,7 +26,8 @@ import org.hibernate.mapping.Collection;
import org.hibernate.mapping.PersistentClass;
import org.grails.orm.hibernate.cfg.domainbinding.binder.CollectionForPropertyConfigBinder;
-import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateCollectionProperty;
+import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateToManyCollectionProperty;
+import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateToManyEntityProperty;
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;
@@ -37,7 +38,7 @@ import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateToManyPrope
@SuppressWarnings("PMD.DataflowAnomalyAnalysis")
public class CollectionSecondPassBinder {
- private final CollectionOrderByBinder collectionOrderByBinder;
+ private final CollectionEntityOrderByBinder collectionEntityOrderByBinder;
private final CollectionMultiTenantFilterBinder collectionMultiTenantFilterBinder;
private final CollectionKeyColumnUpdater collectionKeyColumnUpdater;
private final BidirectionalMapElementBinder bidirectionalMapElementBinder;
@@ -53,7 +54,7 @@ public class CollectionSecondPassBinder {
CollectionForPropertyConfigBinder collectionForPropertyConfigBinder,
BidirectionalMapElementBinder bidirectionalMapElementBinder,
ManyToManyElementBinder manyToManyElementBinder,
- CollectionOrderByBinder collectionOrderByBinder,
+ CollectionEntityOrderByBinder collectionEntityOrderByBinder,
CollectionMultiTenantFilterBinder collectionMultiTenantFilterBinder) {
this.collectionKeyColumnUpdater = collectionKeyColumnUpdater;
this.unidirectionalOneToManyBinder = unidirectionalOneToManyBinder;
@@ -61,7 +62,7 @@ public class CollectionSecondPassBinder {
this.collectionForPropertyConfigBinder = collectionForPropertyConfigBinder;
this.bidirectionalMapElementBinder = bidirectionalMapElementBinder;
this.manyToManyElementBinder = manyToManyElementBinder;
- this.collectionOrderByBinder = collectionOrderByBinder;
+ this.collectionEntityOrderByBinder = collectionEntityOrderByBinder;
this.collectionMultiTenantFilterBinder = collectionMultiTenantFilterBinder;
}
@@ -69,18 +70,18 @@ public class CollectionSecondPassBinder {
PersistentClass ownerClass = property.getHibernateOwner().getPersistentClass();
- if (property instanceof HibernateCollectionProperty collectionProperty) {
- collectionOrderByBinder.bind(collectionProperty);
- }
- if (property instanceof HibernateManyToManyProperty manyToMany && manyToMany.isBidirectional()) {
- manyToManyElementBinder.bind(manyToMany);
- } else if (property.isBidirectionalToManyMap() && property.isBidirectional()) {
- bidirectionalMapElementBinder.bind(property);
- } else if (property instanceof HibernateOneToManyProperty oneToManyProperty &&
- oneToManyProperty.isUnidirectionalOneToMany()) {
- unidirectionalOneToManyBinder.bind(oneToManyProperty);
- } else if (property.supportsJoinColumnMapping()) {
- collectionWithJoinTableBinder.bindCollectionWithJoinTable(property);
+ if (property instanceof HibernateToManyEntityProperty entityProperty) {
+ collectionEntityOrderByBinder.bind(entityProperty);
+ if (entityProperty.isManyToMany() && entityProperty.isBidirectional()) {
+ manyToManyElementBinder.bind((HibernateManyToManyProperty) entityProperty);
+ } else if (entityProperty.isBidirectionalToManyMap() && entityProperty.isBidirectional()) {
+ bidirectionalMapElementBinder.bind(entityProperty);
+ } else if (entityProperty.isOneToMany() && entityProperty.isUnidirectionalOneToMany()) {
+ unidirectionalOneToManyBinder.bind((HibernateOneToManyProperty) entityProperty);
+ }
+ } else if (property instanceof HibernateToManyCollectionProperty collectionProperty &&
+ collectionProperty.supportsJoinColumnMapping()) {
+ collectionWithJoinTableBinder.bindCollectionWithJoinTable(collectionProperty);
}
collectionMultiTenantFilterBinder.bind(property);
collectionKeyColumnUpdater.bind(property, ownerClass);
diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernatePersistentPropertySpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernatePersistentPropertySpec.groovy
index 2b71af76f3..4284d5d738 100644
--- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernatePersistentPropertySpec.groovy
+++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernatePersistentPropertySpec.groovy
@@ -28,7 +28,8 @@ class HibernatePersistentPropertySpec extends HibernateGormDatastoreSpec {
void setupSpec() {
manager.addAllDomainClasses([
LazyBook, LazyAuthor, ExplicitNonLazy, JoinFetchEntity, EnumEntity,
- GeneratorDefaultEntity, GeneratorUuid2Entity, CompositeKeyEntity
+ GeneratorDefaultEntity, GeneratorUuid2Entity, CompositeKeyEntity,
+ HPPSManyA, HPPSManyB
])
}
@@ -60,68 +61,52 @@ class HibernatePersistentPropertySpec extends HibernateGormDatastoreSpec {
property.isLazy()
}
- def "test isLazy for association"() {
+ def "test isLazy for collection with fetch join"() {
given:
- def entity = (HibernatePersistentEntity) getMappingContext().getPersistentEntity(LazyBook.name)
- def property = (HibernatePersistentProperty) entity.getPropertyByName("author")
-
- expect:
- property.isLazyAble()
- property.isLazy()
- }
-
- def "test isLazy for explicit lazy false"() {
- given:
- def entity = (HibernatePersistentEntity) getMappingContext().getPersistentEntity(ExplicitNonLazy.name)
- def property = (HibernatePersistentProperty) entity.getPropertyByName("author")
+ def entity = (HibernatePersistentEntity) getMappingContext().getPersistentEntity(JoinFetchEntity.name)
+ def property = (HibernatePersistentProperty) entity.getPropertyByName("items")
expect:
!property.isLazy()
}
- def "test isLazy for fetch join"() {
+ def "test isLazy for explicit non-lazy"() {
given:
- def entity = (HibernatePersistentEntity) getMappingContext().getPersistentEntity(JoinFetchEntity.name)
- def property = (HibernatePersistentProperty) entity.getPropertyByName("author")
+ def entity = (HibernatePersistentEntity) getMappingContext().getPersistentEntity(ExplicitNonLazy.name)
+ def property = (HibernatePersistentProperty) entity.getPropertyByName("name")
expect:
!property.isLazy()
}
- def "test getTypeName"() {
+ def "test getHibernateOwner"() {
given:
def entity = (HibernatePersistentEntity) getMappingContext().getPersistentEntity(LazyBook.name)
def property = (HibernatePersistentProperty) entity.getPropertyByName("title")
expect:
- property.getTypeName() == String.name
+ property.getHibernateOwner() == entity
}
- def "test isEnumType"() {
+ def "test isEnum"() {
given:
def entity = (HibernatePersistentEntity) getMappingContext().getPersistentEntity(EnumEntity.name)
- def property = (HibernatePersistentProperty) entity.getPropertyByName("status")
-
- expect:
- property.isEnumType()
- }
-
- def "test getHibernateOwner"() {
- given:
- def entity = (HibernatePersistentEntity) getMappingContext().getPersistentEntity(LazyBook.name)
- def property = (HibernatePersistentProperty) entity.getPropertyByName("title")
+ def enumProp = (HibernatePersistentProperty) entity.getPropertyByName("type")
+ def stringProp = (HibernatePersistentProperty) entity.getPropertyByName("name")
expect:
- property.getHibernateOwner() == entity
+ enumProp.isEnum()
+ !stringProp.isEnum()
}
- def "test isJoinKeyMapped"() {
+ def "test getGeneratorName"() {
given:
- def entity = (HibernatePersistentEntity) getMappingContext().getPersistentEntity(JoinFetchEntity.name)
- def property = (HibernatePersistentProperty) entity.getPropertyByName("author")
+ def defaultEntity = (HibernatePersistentEntity) getMappingContext().getPersistentEntity(GeneratorDefaultEntity.name)
+ def uuidEntity = (HibernatePersistentEntity) getMappingContext().getPersistentEntity(GeneratorUuid2Entity.name)
expect:
- !property.isJoinKeyMapped() // Default many-to-one doesn't have join table usually
+ defaultEntity.getIdentityProperty().getGeneratorName() == "identity"
+ uuidEntity.getIdentityProperty().getGeneratorName() == "uuid2"
}
def "test getPersistentClass"() {
@@ -146,6 +131,22 @@ class HibernatePersistentPropertySpec extends HibernateGormDatastoreSpec {
result == property
}
+ def "test isManyToMany and isOneToMany"() {
+ given:
+ def authorEntity = (HibernatePersistentEntity) getMappingContext().getPersistentEntity(LazyAuthor.name)
+ def entityA = (HibernatePersistentEntity) getMappingContext().getPersistentEntity(HPPSManyA.name)
+
+ def oneToMany = (HibernateToManyProperty) authorEntity.getPropertyByName("books")
+ def manyToMany = (HibernateToManyProperty) entityA.getPropertyByName("others")
+
+ expect:
+ oneToMany.isOneToMany()
+ !oneToMany.isManyToMany()
+
+ manyToMany.isManyToMany()
+ !manyToMany.isOneToMany()
+ }
+
def "getIdentityProperty returns HibernateCompositeIdentityProperty with all parts for composite key entity"() {
given:
def entity = (HibernatePersistentEntity) getMappingContext().getPersistentEntity(CompositeKeyEntity.name)
@@ -160,43 +161,13 @@ class HibernatePersistentPropertySpec extends HibernateGormDatastoreSpec {
parts != null
parts.length == 2
parts.every { it instanceof HibernatePersistentProperty }
- parts*.name.toSet() == ['firstName', 'lastName'].toSet()
- }
-
-
- def "getGeneratorName returns null for regular property with no generator configured"() {
- given:
- def entity = (HibernatePersistentEntity) getMappingContext().getPersistentEntity(GeneratorDefaultEntity.name)
- def property = (HibernatePersistentProperty) entity.getPropertyByName("name")
-
- expect:
- property.getGeneratorName() == null
- }
-
- def "getGeneratorName on identity with no explicit generator delegates to entity"() {
- given:
- def entity = (HibernatePersistentEntity) getMappingContext().getPersistentEntity(GeneratorDefaultEntity.name)
- def identity = (HibernateSimpleIdentityProperty) entity.getIdentityProperty()
-
- expect:
- identity.getGeneratorName() == entity.getIdentityGeneratorName()
- identity.getGeneratorName() != null
- }
-
- def "getGeneratorName on identity with explicit generator returns that generator"() {
- given:
- def entity = (HibernatePersistentEntity) getMappingContext().getPersistentEntity(GeneratorUuid2Entity.name)
- def identity = (HibernateSimpleIdentityProperty) entity.getIdentityProperty()
-
- expect:
- identity.getGeneratorName() == GrailsSequenceGeneratorEnum.UUID2.toString()
+ parts*.name.sort() == ["code", "name"]
}
}
@Entity
class LazyBook {
Long id
- Long version
String title
LazyAuthor author
}
@@ -211,37 +182,28 @@ class LazyAuthor {
@Entity
class ExplicitNonLazy {
Long id
- LazyAuthor author
+ String name
static mapping = {
- author lazy: false
+ name lazy: false
}
+
+ boolean isLazyFalse() { false }
}
@Entity
class JoinFetchEntity {
Long id
- LazyAuthor author
+ static hasMany = [items: String]
static mapping = {
- author fetch: 'join'
+ items fetch: "join"
}
}
-enum Status { ACTIVE, INACTIVE }
-
@Entity
class EnumEntity {
Long id
- Status status
-}
-
-@Entity
-class CompositeKeyEntity implements Serializable {
- String firstName
- String lastName
- Long version
- static mapping = {
- id composite: ['firstName', 'lastName']
- }
+ String name
+ GrailsSequenceGeneratorEnum type
}
@Entity
@@ -258,3 +220,28 @@ class GeneratorUuid2Entity {
id generator: 'uuid2'
}
}
+
+@Entity
+class CompositeKeyEntity implements Serializable {
+ String name
+ Integer code
+ static mapping = {
+ id composite: ['name', 'code']
+ }
+}
+
+@Entity
+class HPPSManyA {
+ Long id
+ static hasMany = [others: HPPSManyB]
+ static mapping = {
+ others joinTable: [name: 'many_a_others']
+ }
+}
+
+@Entity
+class HPPSManyB {
+ Long id
+ static hasMany = [owners: HPPSManyA]
+ static belongsTo = [owners: HPPSManyA]
+}
diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/BidirectionalMapElementBinderSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/BidirectionalMapElementBinderSpec.groovy
index 29322c3325..b56aae908c 100644
--- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/BidirectionalMapElementBinderSpec.groovy
+++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/BidirectionalMapElementBinderSpec.groovy
@@ -81,7 +81,7 @@ class BidirectionalMapElementBinderSpec extends HibernateGormDatastoreSpec {
def property = propertyFor(BBMEOwner)
expect:
- property.isBidirectionalOneToManyMap()
+ property.isBidirectionalToManyMap()
property.isBidirectional()
}
}
diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionOrderByBinderSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionEntityOrderByBinderSpec.groovy
similarity index 93%
rename from grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionOrderByBinderSpec.groovy
rename to grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionEntityOrderByBinderSpec.groovy
index 1dfeaf04ef..dee029c6e8 100644
--- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionOrderByBinderSpec.groovy
+++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionEntityOrderByBinderSpec.groovy
@@ -21,8 +21,8 @@ package org.grails.orm.hibernate.cfg.domainbinding.secondpass
import grails.gorm.annotation.Entity
import grails.gorm.specs.HibernateGormDatastoreSpec
import org.grails.orm.hibernate.cfg.domainbinding.hibernate.GrailsHibernatePersistentEntity
-import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateCollectionProperty
-import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateToManyProperty
+import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateToManyEntityProperty
+
import org.hibernate.mapping.Bag
import org.hibernate.mapping.BasicValue
import org.hibernate.mapping.Column
@@ -32,10 +32,11 @@ import org.hibernate.mapping.RootClass
import org.hibernate.mapping.Table
import spock.lang.Subject
-class CollectionOrderByBinderSpec extends HibernateGormDatastoreSpec {
+class CollectionEntityOrderByBinderSpec extends HibernateGormDatastoreSpec {
@Subject
- CollectionOrderByBinder binder = new CollectionOrderByBinder()
+ CollectionEntityOrderByBinder binder = new CollectionEntityOrderByBinder()
+
void setupSpec() {
manager.addAllDomainClasses([
@@ -48,8 +49,8 @@ class CollectionOrderByBinderSpec extends HibernateGormDatastoreSpec {
])
}
- private HibernateCollectionProperty propertyFor(Class ownerClass, String name = "items") {
- (getPersistentEntity(ownerClass) as GrailsHibernatePersistentEntity).getPropertyByName(name) as HibernateCollectionProperty
+ private HibernateToManyEntityProperty propertyFor(Class ownerClass, String name = "items") {
+ (getPersistentEntity(ownerClass) as GrailsHibernatePersistentEntity).getPropertyByName(name) as HibernateToManyEntityProperty
}
private RootClass rootClassWith(String entityName, String propertyName, String columnName) {
diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionSecondPassBinderSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionSecondPassBinderSpec.groovy
index 0e1ad43411..c687c46504 100644
--- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionSecondPassBinderSpec.groovy
+++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionSecondPassBinderSpec.groovy
@@ -27,7 +27,7 @@ import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernatePersistentP
import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateToManyProperty
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.HibernateCollectionProperty
+import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateToManyEntityProperty
import org.hibernate.mapping.ManyToOne
@@ -66,7 +66,7 @@ class CollectionSecondPassBinderSpec extends HibernateGormDatastoreSpec {
def svcb = new SimpleValueColumnBinder()
def cku = new CollectionKeyColumnUpdater(new CollectionKeyBinder(botml, dkvb, svcb, pkvc))
- binder = new CollectionSecondPassBinder(cku, uotmb, cwjtb, cfpcb, mockBidirectionalMapElementBinder, new ManyToManyElementBinder(mtob, cfpcb), new CollectionOrderByBinder(), new CollectionMultiTenantFilterBinder(dcnf))
+ binder = new CollectionSecondPassBinder(cku, uotmb, cwjtb, cfpcb, mockBidirectionalMapElementBinder, new ManyToManyElementBinder(mtob, cfpcb), new CollectionEntityOrderByBinder(), new CollectionMultiTenantFilterBinder(dcnf))
}
protected HibernatePersistentProperty createTestHibernateToManyProperty(Class<?> domainClass, String propertyName) {
@@ -90,7 +90,7 @@ class CollectionSecondPassBinderSpec extends HibernateGormDatastoreSpec {
then:
noExceptionThrown()
- !(property instanceof HibernateCollectionProperty)
+ !(property instanceof HibernateToManyEntityProperty)
}
def "bindCollectionSecondPass succeeds for Unidirectional One-to-Many"() {
@@ -105,7 +105,7 @@ class CollectionSecondPassBinderSpec extends HibernateGormDatastoreSpec {
then:
noExceptionThrown()
- property instanceof HibernateCollectionProperty
+ property instanceof HibernateToManyEntityProperty
property.getCollection() != null
}
@@ -122,7 +122,7 @@ class CollectionSecondPassBinderSpec extends HibernateGormDatastoreSpec {
then:
noExceptionThrown()
- property instanceof HibernateCollectionProperty
+ property instanceof HibernateToManyEntityProperty
property.isBidirectional()
// In Hibernate 7 many-to-many element is mapped as ManyToOne to the join table
property.getCollection().getElement() instanceof ManyToOne
@@ -140,7 +140,7 @@ class CollectionSecondPassBinderSpec extends HibernateGormDatastoreSpec {
then:
noExceptionThrown()
- property instanceof HibernateCollectionProperty
+ property instanceof HibernateToManyEntityProperty
property.getCollection().getOrderBy() != null
}
@@ -156,7 +156,7 @@ class CollectionSecondPassBinderSpec extends HibernateGormDatastoreSpec {
then:
noExceptionThrown()
- !(property instanceof HibernateCollectionProperty)
+ !(property instanceof HibernateToManyEntityProperty)
property.getCollection() != null
}
@@ -179,10 +179,10 @@ class CollectionSecondPassBinderSpec extends HibernateGormDatastoreSpec {
def "HibernateCollectionProperty getAssociatedClass returns PersistentClass or throws MappingException"() {
given: "A collection property that implements HibernateCollectionProperty"
- def property = createTestHibernateToManyProperty(CSPBUniOwner, "items") as HibernateCollectionProperty
+ def property = createTestHibernateToManyProperty(CSPBUniOwner, "items") as HibernateToManyEntityProperty
expect:
- property instanceof HibernateCollectionProperty
+ property instanceof HibernateToManyEntityProperty
when: "Persistent class is present (after first pass)"
hibernateFirstPass()
diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/Association.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/Association.java
index 1a83c09a51..02ad87e5e0 100644
--- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/Association.java
+++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/model/types/Association.java
@@ -369,7 +369,7 @@ public abstract class Association<T extends Property> extends AbstractPersistent
.orElse(false);
}
- public boolean isBidirectionalOneToManyMap() {
+ public boolean isBidirectionalToManyMap() {
return Map.class.isAssignableFrom(this.getType()) && this.isBidirectional();
}
}