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 2d842d8a5e67a93435555a79478125b0aa4d328b Author: Walter Duque de Estrada <[email protected]> AuthorDate: Sat Feb 14 11:20:22 2026 -0600 Refactor type resolution from SimpleValueBinder to GrailsHibernatePersistentProperty. - GrailsHibernatePersistentProperty: Added getTypeName(SimpleValue) and getTypeParameters(SimpleValue) default methods to encapsulate type resolution logic. - SimpleValueBinder: Simplified bindSimpleValue to use the new property methods. - GrailsHibernatePersistentPropertySpec: Added tests for the new type resolution methods. - SimpleValueBinderSpec: Updated mock expectations to align with the new logic. --- .../cfg/GrailsHibernatePersistentProperty.java | 47 ++++++++++++++++++++-- .../domainbinding/binder/SimpleValueBinder.java | 18 +-------- .../GrailsHibernatePersistentPropertySpec.groovy | 44 ++++++++++++++++++++ .../cfg/domainbinding/SimpleValueBinderSpec.groovy | 12 ++++++ 4 files changed, 101 insertions(+), 20 deletions(-) diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsHibernatePersistentProperty.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsHibernatePersistentProperty.java index ba33ea79b1..b1bb48c7eb 100644 --- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsHibernatePersistentProperty.java +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsHibernatePersistentProperty.java @@ -8,9 +8,11 @@ import java.util.List; import java.util.Optional; 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; /** @@ -153,18 +155,55 @@ public interface GrailsHibernatePersistentProperty extends PersistentProperty<Pr .orElseGet(this::getMappedColumnName)); } - default boolean isBidirectionalManyToOneWithListMapping( Property prop) { - if(this instanceof Association<?> association) { - + 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 + */ + default String getTypeName(SimpleValue simpleValue) { + GrailsHibernatePersistentProperty actualTypeProperty = getTypeProperty(simpleValue); + String typeName = actualTypeProperty.getTypeName(); + if (typeName == null) { + if (!(actualTypeProperty instanceof Association)) { + Class<?> type = actualTypeProperty.getType(); + if (type != null) { + return type.getName(); + } + } + return null; + } + return typeName; + } + /** + * @param simpleValue The Hibernate simple value + * @return The type parameters + */ + default java.util.Properties getTypeParameters(SimpleValue simpleValue) { + if (getTypeName(simpleValue) != null) { + return Optional.ofNullable(getTypeProperty(simpleValue).getMappedForm()).map(PropertyConfig::getTypeParams).orElse(null); + } + return null; + } + + /** + * @param simpleValue The Hibernate simple value + * @return The property that defines the type + */ + default GrailsHibernatePersistentProperty getTypeProperty(SimpleValue simpleValue) { + if (simpleValue instanceof DependantValue) { + return Optional.ofNullable(getHibernateOwner().getIdentity()).orElse(this); + } + return this; + } } \ No newline at end of file diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/SimpleValueBinder.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/SimpleValueBinder.java index bc03a8c84a..d9b365e587 100644 --- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/SimpleValueBinder.java +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/SimpleValueBinder.java @@ -62,23 +62,9 @@ public class SimpleValueBinder { SimpleValue simpleValue, String path) { - GrailsHibernatePersistentProperty actualTypeProperty = property; - if (simpleValue instanceof DependantValue) { - actualTypeProperty = Optional.ofNullable(property.getHibernateOwner().getIdentity()).orElse(property); - } PropertyConfig propertyConfig = property.getMappedForm(); - final String typeName = actualTypeProperty.getTypeName(); - if (typeName == null) { - if (!(actualTypeProperty instanceof org.grails.datastore.mapping.model.types.Association)) { - Class<?> type = actualTypeProperty.getType(); - if (type != null) { - simpleValue.setTypeName(type.getName()); - } - } - } else { - simpleValue.setTypeName(typeName); - simpleValue.setTypeParameters(propertyConfig.getTypeParams()); - } + simpleValue.setTypeName(property.getTypeName(simpleValue)); + simpleValue.setTypeParameters(property.getTypeParameters(simpleValue)); String generator = propertyConfig.getGenerator(); if (generator != null && simpleValue instanceof BasicValue basicValue) { diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/GrailsHibernatePersistentPropertySpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/GrailsHibernatePersistentPropertySpec.groovy index 10c5e0b5e7..f8f4160070 100644 --- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/GrailsHibernatePersistentPropertySpec.groovy +++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/GrailsHibernatePersistentPropertySpec.groovy @@ -154,6 +154,50 @@ class GrailsHibernatePersistentPropertySpec extends HibernateGormDatastoreSpec { mapProp.getMapElementName(namingStrategy) == "tags_elt" } + void "test getTypeName(SimpleValue) and getTypeParameters(SimpleValue)"() { + given: + def domainBinder = getGrailsDomainBinder() + def metadataBuildingContext = domainBinder.getMetadataBuildingContext() + def table = metadataBuildingContext.getMetadataCollector().addTable(null, null, "TEST", null, false, metadataBuildingContext) + PersistentEntity entity = createPersistentEntity(TestEntityWithTypeName) + GrailsHibernatePersistentProperty property = (GrailsHibernatePersistentProperty) entity.getPropertyByName("name") + + def sv = new org.hibernate.mapping.BasicValue(metadataBuildingContext, table) + + expect: + property.getTypeName(sv) == "string" + property.getTypeParameters(sv) == null // No type params in TestEntityWithTypeName + } + + void "test getTypeName(SimpleValue) with fallback"() { + given: + def domainBinder = getGrailsDomainBinder() + def metadataBuildingContext = domainBinder.getMetadataBuildingContext() + def table = metadataBuildingContext.getMetadataCollector().addTable(null, null, "TEST2", null, false, metadataBuildingContext) + PersistentEntity entity = createPersistentEntity(TestEntityWithEnum) + GrailsHibernatePersistentProperty property = (GrailsHibernatePersistentProperty) entity.getPropertyByName("name") + + def sv = new org.hibernate.mapping.BasicValue(metadataBuildingContext, table) + + expect: + property.getTypeName(sv) == String.name + } + + void "test getTypeName(SimpleValue) for DependantValue"() { + given: + def domainBinder = getGrailsDomainBinder() + def metadataBuildingContext = domainBinder.getMetadataBuildingContext() + def table = metadataBuildingContext.getMetadataCollector().addTable(null, null, "TEST3", null, false, metadataBuildingContext) + PersistentEntity entity = createPersistentEntity(BMTOWLMAuthor) + GrailsHibernatePersistentProperty property = (GrailsHibernatePersistentProperty) entity.getPropertyByName("books") + + // DependantValue usually represents a foreign key, it should use the identity type of the owner + def dv = new org.hibernate.mapping.DependantValue(metadataBuildingContext, table, new org.hibernate.mapping.BasicValue(metadataBuildingContext, table)) + + expect: + property.getTypeName(dv) == Long.name // Author's ID is Long + } + void "test validateAssociation throws exception for user type"() { given: PersistentEntity entity = createPersistentEntity(TestEntityWithAssociations) diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/SimpleValueBinderSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/SimpleValueBinderSpec.groovy index d5d6ceb1ed..4399d9087b 100644 --- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/SimpleValueBinderSpec.groovy +++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/SimpleValueBinderSpec.groovy @@ -59,6 +59,8 @@ class SimpleValueBinderSpec extends Specification { binder.bindSimpleValue(prop, null, sv, "p") then: + 1 * prop.getTypeName(sv) >> "custom.Type" + 1 * prop.getTypeParameters(sv) >> props 1 * sv.setTypeName("custom.Type") 1 * sv.setTypeParameters({ it.getProperty('p1') == 'v1' }) 1 * columnBinder.bindColumn(prop, null, _, null, 'p', null) >> { args -> @@ -93,6 +95,8 @@ class SimpleValueBinderSpec extends Specification { binder.bindSimpleValue(prop, null, sv, null) then: + 1 * prop.getTypeName(sv) >> Integer.name + 1 * prop.getTypeParameters(sv) >> null 1 * sv.setTypeName(Integer.name) 1 * columnBinder.bindColumn(prop, null, _, null, null, null) >> { args -> def column = args[2] as Column @@ -127,6 +131,8 @@ class SimpleValueBinderSpec extends Specification { binder.bindSimpleValue(prop, null, sv, null) then: + 1 * prop.getTypeName(sv) >> 'X' + 1 * prop.getTypeParameters(sv) >> null 1 * sv.addFormula({ it.getFormula() == 'x+y' }) 0 * columnBinder.bindColumn(_, _, _, _, _, _) @@ -134,6 +140,8 @@ class SimpleValueBinderSpec extends Specification { binder.bindSimpleValue(tenantProp, null, sv2, null) then: + 1 * tenantProp.getTypeName(sv2) >> 'X' + 1 * tenantProp.getTypeParameters(sv2) >> null 0 * sv2.addFormula(_) 1 * columnBinder.bindColumn(_, _, _, _, _, _) >> { args -> def column = args[2] as Column @@ -165,6 +173,8 @@ class SimpleValueBinderSpec extends Specification { binder.bindSimpleValue(prop, null, sv, null) then: + 1 * prop.getTypeName(sv) >> 'Y' + 1 * prop.getTypeParameters(sv) >> null 1 * columnBinder.bindColumn(prop, null, _, null, null, null) >> { args -> args[2].setName("testColumn") } @@ -197,6 +207,8 @@ class SimpleValueBinderSpec extends Specification { binder.bindSimpleValue(prop, parent, sv, 'path') then: + 1 * prop.getTypeName(sv) >> 'Z' + 1 * prop.getTypeParameters(sv) >> null 1 * columnConfigToColumnBinder.bindColumnConfigToColumn(_, cc1, pc) >> { args -> def column = args[0] as Column column.setName("testColumn")
