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 b6eec1bf942ead0fdc40827b1ce9f51fdf543fb6
Author: Walter B Duque de Estrada <[email protected]>
AuthorDate: Thu Dec 18 22:59:03 2025 -0600

    Now creating ids natively if not assigned as default
---
 grails-data-hibernate7/core/build.gradle           |  3 +
 .../orm/hibernate/HibernateGormInstanceApi.groovy  | 19 +++---
 .../orm/hibernate/cfg/GrailsDomainBinder.java      | 70 ++++++++++++++--------
 .../cfg/domainbinding/GrailsNativeGenerator.java   | 34 +++++++++++
 4 files changed, 89 insertions(+), 37 deletions(-)

diff --git a/grails-data-hibernate7/core/build.gradle 
b/grails-data-hibernate7/core/build.gradle
index 0f7a117d56..1b63057321 100644
--- a/grails-data-hibernate7/core/build.gradle
+++ b/grails-data-hibernate7/core/build.gradle
@@ -65,6 +65,9 @@ dependencies {
 
    api( 'org.jboss:jandex:3.2.3')
 
+    compileOnly "org.hibernate.orm:hibernate-core:$hibernate7Version"
+
+
     compileOnly 'org.hibernate.orm:hibernate-jcache', {
         exclude group:'commons-collections', module:'commons-collections'
         exclude group:'commons-logging', module:'commons-logging'
diff --git 
a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormInstanceApi.groovy
 
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormInstanceApi.groovy
index 94809186d1..debea37937 100644
--- 
a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormInstanceApi.groovy
+++ 
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormInstanceApi.groovy
@@ -17,6 +17,8 @@ package org.grails.orm.hibernate
 
 import org.codehaus.groovy.runtime.InvokerHelper
 
+import jakarta.persistence.GenerationType
+
 import org.hibernate.engine.spi.SessionFactoryImplementor
 import org.hibernate.generator.Assigned
 import org.hibernate.generator.Generator
@@ -151,19 +153,11 @@ class HibernateGormInstanceApi<D> extends 
GormInstanceApi<D> {
         validateable.skipValidation(true)
 
         try {
-
-            Serializable idVal = (Serializable) 
InvokerHelper.getProperty(target, "id")
-            if (!idVal) {
-                if (isAssignedId(persistentEntity)) {
-                    def id = nextId()
-                    InvokerHelper.setProperty(target, "id", id)
-                    return performPersist(target, shouldFlush)
-                } else {
-                    return performPersist(target, shouldFlush)
-                }
-            } else if (shouldInsert(arguments)) {
+            String idPropertyName = domainClass.identity?.name ?: "id"
+            Object idVal = InvokerHelper.getProperty(target, idPropertyName)
+            if (idVal == null) {
                 return performPersist(target, shouldFlush)
-            } else  {
+            } else {
                 return performMerge(target, shouldFlush)
             }
         } finally {
@@ -171,6 +165,7 @@ class HibernateGormInstanceApi<D> extends 
GormInstanceApi<D> {
         }
     }
 
+
     private boolean isAssignedId(PersistentEntity entity) {
         return ((SessionFactoryImplementor) sessionFactory)
                 .getMappingMetamodel()
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 e41962e4a4..5ff60e052e 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
@@ -2048,42 +2048,62 @@ public class GrailsDomainBinder
     private void bindSimpleId(PersistentProperty identifier, RootClass entity,
                                 InFlightMetadataCollector mappings, Identity 
mappedId, String sessionFactoryBeanName) {
 
-        Mapping mapping = new 
HibernateEntityWrapper().getMappedForm(identifier.getOwner());
-        boolean useSequence = mapping.isTablePerConcreteClass();
-
+        boolean useSequence = new 
HibernateEntityWrapper().getMappedForm(identifier.getOwner()).isTablePerConcreteClass();
         // create the id value
         BasicValue id = new BasicValue(metadataBuildingContext, 
entity.getTable());
-        Property idProperty  = new Property();
-        idProperty.setName(identifier.getName());
-        idProperty.setValue(id);
-        entity.setDeclaredIdentifierProperty(idProperty);
-        // set identifier on entity
-
-        Properties params = new Properties();
-        entity.setIdentifier(id);
 
+        String generator;
         if (mappedId == null) {
-//            id.se
-//            id.setIdentifierGeneratorStrategy(useSequence ? 
"sequence-identity" : "native");
+            generator = useSequence ? "sequence-identity" : "native";
         } else {
-            params.putAll(mappedId.getParams());
-            if(params.containsKey(SEQUENCE_KEY)) {
-                params.put(SequenceStyleGenerator.SEQUENCE_PARAM,  
params.getProperty(SEQUENCE_KEY));
-            }
-
-            if (id.getCustomIdGeneratorCreator().isAssigned()) {
-                id.setNullValue("undefined");
+            generator = mappedId.getGenerator();
+            if ("native".equals(generator) && useSequence) {
+                generator = "sequence-identity";
             }
         }
 
-        String schemaName = new 
NamespaceNameExtractor().getSchemaName(mappings);
-        String catalogName = new 
NamespaceNameExtractor().getCatalogName(mappings);
+        switch (generator) {
+            case "identity" -> id.setCustomIdGeneratorCreator(context -> {
+                // Force IdentityGenerator for databases like MySQL/H2
+                var gen = new org.hibernate.id.IdentityGenerator();
+                
context.getProperty().getValue().getColumns().get(0).setIdentity(true);
+                return gen;
+            });
 
-        IdentifierHelper identifierHelper = 
getJdbcEnvironment().getIdentifierHelper();
-        params.put(IDENTIFIER_NORMALIZER, identifierHelper);
+            case "sequence", "sequence-identity" -> 
id.setCustomIdGeneratorCreator(context -> {
+                // Use the modern SequenceStyleGenerator
+                return new org.hibernate.id.enhanced.SequenceStyleGenerator();
+            });
 
+            case "increment" -> id.setCustomIdGeneratorCreator(context -> {
+                return new org.hibernate.id.IncrementGenerator();
+            });
 
-        // bind value
+            case "uuid", "uuid2" -> id.setCustomIdGeneratorCreator(context -> {
+                return new 
org.hibernate.id.uuid.UuidGenerator(context.getType().getReturnedClass());
+            });
+
+            case "assigned" -> id.setCustomIdGeneratorCreator(context -> {
+                return new org.hibernate.id.Assigned();
+            });
+
+            case "table", "enhanced-table" -> 
id.setCustomIdGeneratorCreator(context -> {
+                return new org.hibernate.id.enhanced.TableGenerator();
+            });
+
+            case "hilo" -> id.setCustomIdGeneratorCreator(context -> {
+                // Note: Legacy Hilo is often replaced by 
SequenceStyleGenerator with optimizer
+                return new org.hibernate.id.enhanced.SequenceStyleGenerator();
+            });
+
+            default -> 
id.setCustomIdGeneratorCreator(GrailsNativeGenerator::new);
+        }
+
+        Property idProperty  = new Property();
+        idProperty.setName(identifier.getName());
+        idProperty.setValue(id);
+        entity.setDeclaredIdentifierProperty(idProperty);
+        entity.setIdentifier(id);
         // set type
         new SimpleValueBinder(namingStrategy).bindSimpleValue(identifier, 
null, id, EMPTY_PATH);
 
diff --git 
a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/GrailsNativeGenerator.java
 
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/GrailsNativeGenerator.java
new file mode 100644
index 0000000000..c03cfee2d9
--- /dev/null
+++ 
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/GrailsNativeGenerator.java
@@ -0,0 +1,34 @@
+package org.grails.orm.hibernate.cfg.domainbinding;
+
+import org.hibernate.engine.spi.SharedSessionContractImplementor;
+import org.hibernate.generator.EventType;
+import org.hibernate.generator.GeneratorCreationContext;
+import org.hibernate.id.NativeGenerator;
+import jakarta.persistence.GenerationType;
+
+public class GrailsNativeGenerator extends NativeGenerator {
+
+    public GrailsNativeGenerator(GeneratorCreationContext context) {
+        // This triggers the internal switch logic you provided earlier,
+        // which calls setIdentity(true) on the column for H2.
+        this.initialize(null, null, context);
+    }
+
+    @Override
+    public Object generate(SharedSessionContractImplementor session, Object 
entity, Object currentValue, EventType eventType) {
+        // 1. Support Grails assigned identifiers
+        if (currentValue != null) {
+            return currentValue;
+        }
+
+        // 2. Fix the Hibernate 7 ClassCastException
+        // NativeGenerator.generate() tries to cast the delegate to 
BeforeExecutionGenerator.
+        // If the dialect chose IDENTITY, that cast fails. We bypass it by 
returning null.
+        if (this.getGenerationType() == GenerationType.IDENTITY) {
+            return null;
+        }
+
+        // 3. For Sequences/UUIDs, delegate to the standard logic
+        return super.generate(session, entity, currentValue, eventType);
+    }
+}
\ No newline at end of file

Reply via email to