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 a5f1c7035cc194d6efac33a26ef3bc9efeeb0212 Author: Walter B Duque de Estrada <[email protected]> AuthorDate: Mon Jan 12 11:48:55 2026 -0600 Refactor GrailsDomainBinder.isSaveUpdateCascade to use CascadeBehavior enum and add tests --- .../orm/hibernate/cfg/GrailsDomainBinder.java | 30 +++------- .../cfg/domainbinding/CascadeBehavior.java | 4 ++ .../hibernate/cfg/GrailsDomainBinderSpec.groovy | 65 ++++++++++++++++++++-- .../domainbinding/CascadeBehaviorEnumSpec.groovy | 51 +++++++++++++++++ 4 files changed, 122 insertions(+), 28 deletions(-) diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinder.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinder.java index 41b348dfb7..fdc4dab58f 100644 --- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinder.java +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinder.java @@ -51,11 +51,8 @@ import org.hibernate.boot.spi.AdditionalMappingContributor; import org.hibernate.boot.spi.InFlightMetadataCollector; import org.hibernate.boot.spi.MetadataBuildingContext; import org.hibernate.engine.OptimisticLockStyle; -import org.hibernate.engine.jdbc.env.spi.IdentifierHelper; import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; import org.hibernate.engine.spi.FilterDefinition; -import org.hibernate.id.PersistentIdentifierGenerator; -import org.hibernate.id.enhanced.SequenceStyleGenerator; import org.hibernate.mapping.Backref; import org.hibernate.mapping.Bag; import org.hibernate.mapping.BasicValue; @@ -88,7 +85,6 @@ import org.hibernate.type.ForeignKeyDirection; import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.Type; import org.hibernate.usertype.UserCollectionType; -import org.jboss.jandex.IndexView; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.util.StringUtils; @@ -101,7 +97,6 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Optional; -import java.util.Properties; import java.util.Set; import java.util.SortedSet; import java.util.StringTokenizer; @@ -122,22 +117,15 @@ public class GrailsDomainBinder implements AdditionalMappingContributor, TypeContributor { - private static final String CASCADE_ALL_DELETE_ORPHAN = CascadeBehavior.ALL_DELETE_ORPHAN.getValue(); public static final String FOREIGN_KEY_SUFFIX = "_id"; private static final String STRING_TYPE = "string"; private static final String EMPTY_PATH = ""; public static final char UNDERSCORE = '_'; - public static final String CASCADE_ALL = CascadeBehavior.ALL.getValue(); - public static final String CASCADE_SAVE_UPDATE = CascadeBehavior.SAVE_UPDATE.getValue(); - public static final String CASCADE_NONE = CascadeBehavior.NONE.getValue(); public static final String BACKTICK = "`"; public static final String ENUM_TYPE_CLASS = org.grails.orm.hibernate.HibernateLegacyEnumType.class.getName(); public static final String ENUM_CLASS_PROP = "enumClass"; - private static final String ENUM_TYPE_PROP = "type"; - public static final String DEFAULT_ENUM_TYPE = "default"; private static final Logger LOG = LoggerFactory.getLogger(GrailsDomainBinder.class); - public static final String SEQUENCE_KEY = "sequence"; @@ -146,7 +134,6 @@ public class GrailsDomainBinder */ private static final NamingStrategyProvider NAMING_STRATEGY_PROVIDER = new NamingStrategyProvider(); public static final String JPA_DEFAULT_DISCRIMINATOR_TYPE = "DTYPE"; - public static final String IDENTIFIER_NORMALIZER = "identifier_normalizer"; private final CollectionType CT = new CollectionType(null, this) { public Collection create(ToMany property, PersistentClass owner, String path, InFlightMetadataCollector mappings, String sessionFactoryBeanName) { @@ -1029,7 +1016,7 @@ public class GrailsDomainBinder } if (pc.getCascade() != null) { - collection.setOrphanDelete(pc.getCascade().equals(CASCADE_ALL_DELETE_ORPHAN)); + collection.setOrphanDelete(pc.getCascade().equals(CascadeBehavior.ALL_DELETE_ORPHAN.getValue())); } // if it's a one-to-many mapping if (shouldBindCollectionWithForeignKey(property)) { @@ -1170,18 +1157,17 @@ public class GrailsDomainBinder * @param cascade The string containing the cascade properties. * @return True if save-update or any other cascade property that encompasses those is present. */ - private boolean isSaveUpdateCascade(String cascade) { - if (CASCADE_SAVE_UPDATE.equals(cascade) || "save-update".equals(cascade)) { - return true; - } - + protected boolean isSaveUpdateCascade(String cascade) { String[] cascades = cascade.split(","); for (String cascadeProp : cascades) { String trimmedProp = cascadeProp.trim(); - - if (CASCADE_ALL.equals(trimmedProp) || CASCADE_ALL_DELETE_ORPHAN.equals(trimmedProp) || "save-update".equals(trimmedProp)) { - return true; + try { + if (CascadeBehavior.fromString(trimmedProp).isSaveUpdate()) { + return true; + } + } catch (MappingException e) { + // ignore } } diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/CascadeBehavior.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/CascadeBehavior.java index afba75ea74..f4a0cf70d3 100644 --- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/CascadeBehavior.java +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/CascadeBehavior.java @@ -71,6 +71,10 @@ public enum CascadeBehavior { return value; } + public boolean isSaveUpdate() { + return this == ALL || this == ALL_DELETE_ORPHAN || this == SAVE_UPDATE; + } + public static CascadeBehavior fromString(String value) { return Arrays.stream(CascadeBehavior.values()) diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinderSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinderSpec.groovy index 0c07c13bed..048eb86ae2 100644 --- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinderSpec.groovy +++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinderSpec.groovy @@ -14,11 +14,64 @@ class GrailsDomainBinderSpec extends HibernateGormDatastoreSpec { def fieldProperties = [title: String] def persistentEntity = createPersistentEntity(grailsDomainBinder,simpleName, fieldProperties, [:]) - grailsDomainBinder.bindRoot(persistentEntity, collector,"sessionFactoryName") - println("when") - then: - 1 == 1 - } + grailsDomainBinder.bindRoot(persistentEntity, collector,"sessionFactoryName") + println("when") -} \ No newline at end of file + then: + + 1 == 1 + + } + + + + void "Test isSaveUpdateCascade"() { + + given: + + def binder = getGrailsDomainBinder() + + + + expect: + + binder.isSaveUpdateCascade(cascade) == expected + + + + where: + + cascade | expected + + "all" | true + + "all-delete-orphan" | true + + "persist,merge" | true + + "save-update" | true + + "merge,persist" | true + + "merge" | false + + "persist" | false + + "none" | false + + "delete" | false + + "lock" | false + + "evict" | false + + "replicate" | false + + "all,delete" | true + + "persist,merge,lock" | true + + } + + } \ No newline at end of file diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/CascadeBehaviorEnumSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/CascadeBehaviorEnumSpec.groovy new file mode 100644 index 0000000000..4c95090b89 --- /dev/null +++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/CascadeBehaviorEnumSpec.groovy @@ -0,0 +1,51 @@ +package org.grails.orm.hibernate.cfg.domainbinding + +import org.hibernate.MappingException +import spock.lang.Specification +import spock.lang.Unroll + +class CascadeBehaviorEnumSpec extends Specification { + + @Unroll + void "test isSaveUpdate for #behavior"() { + expect: + behavior.isSaveUpdate() == expected + + where: + behavior | expected + CascadeBehavior.ALL | true + CascadeBehavior.ALL_DELETE_ORPHAN | true + CascadeBehavior.SAVE_UPDATE | true + CascadeBehavior.MERGE | false + CascadeBehavior.PERSIST | false + CascadeBehavior.DELETE | false + CascadeBehavior.LOCK | false + CascadeBehavior.EVICT | false + CascadeBehavior.REPLICATE | false + CascadeBehavior.NONE | false + } + + @Unroll + void "test fromString for #value"() { + expect: + CascadeBehavior.fromString(value) == expected + + where: + value | expected + "all" | CascadeBehavior.ALL + "all-delete-orphan" | CascadeBehavior.ALL_DELETE_ORPHAN + "save-update" | CascadeBehavior.SAVE_UPDATE + "persist,merge" | CascadeBehavior.SAVE_UPDATE + "merge" | CascadeBehavior.MERGE + "persist" | CascadeBehavior.PERSIST + "none" | CascadeBehavior.NONE + } + + void "test fromString with invalid value"() { + when: + CascadeBehavior.fromString("invalid") + + then: + thrown(MappingException) + } +}
