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 aff727bb4edbe73f9460a903ee3520274f1354d0 Author: Walter B Duque de Estrada <[email protected]> AuthorDate: Tue Jan 20 10:23:09 2026 -0600 update progress --- .../core/HIBERNATE7-UPGRADE-PROGRESS.md | 16 +++++++-- .../orm/hibernate/cfg/GrailsDomainBinder.java | 9 +++-- .../cfg/domainbinding/BasicValueIdCreator.java | 7 ++-- .../domainbinding/GrailsIncrementGenerator.java | 42 ++++++++++++++++++---- .../cfg/domainbinding/SimpleIdBinder.java | 5 +-- .../domainbinding/SequenceGeneratorsSpec.groovy | 1 + 6 files changed, 61 insertions(+), 19 deletions(-) diff --git a/grails-data-hibernate7/core/HIBERNATE7-UPGRADE-PROGRESS.md b/grails-data-hibernate7/core/HIBERNATE7-UPGRADE-PROGRESS.md index f5129c8544..e6a101609d 100644 --- a/grails-data-hibernate7/core/HIBERNATE7-UPGRADE-PROGRESS.md +++ b/grails-data-hibernate7/core/HIBERNATE7-UPGRADE-PROGRESS.md @@ -73,9 +73,19 @@ public class GrailsSequenceStyleGenerator extends SequenceStyleGenerator { | `native` | [x] PASS | | | `uuid` | [x] PASS | | | `assigned` | [x] PASS | | -| `sequence` | [ ] FAIL | `AssertionFailure: SequenceStructure not properly initialized` | -| `table` | [ ] FAIL | `NPE: this.optimizer is null` | -| `increment` | [ ] FAIL | `NPE: this.previousValueHolder is null` | +| `sequence` | [x] PASS | | +| `table` | [x] PASS | | +| `increment` | [ ] POSTPONED | `Table "org.grails.orm.hibernate.cfg.domainbinding.EntityWithIncrement" not found` | + +### GrailsIncrementGenerator Fix Strategy (Postponed) + +#### Problem +The `increment` generator fails because: +1. **Quoted Table Name:** Hibernate 7 appears to be quoting the table name which defaults to the FQN, and H2 cannot find it. +2. **Initialization:** In Hibernate 7, `IncrementGenerator` needs explicit initialization of its SQL context to avoid NPEs. + +#### Current State +Partial work was done to address initialization and table name resolution, but the test still fails with table-not-found errors in H2. Further investigation into how Hibernate 7 resolves and quotes table names for the `increment` generator is required. - [x] `SimpleIdBinder`: Orchestrates the binding of simple identifiers by coordinating `BasicValueIdCreator`, `SimpleValueBinder`, and `PropertyBinder`. - [x] `PropertyBinder`: Binds `PersistentProperty` to Hibernate `Property`, handling cascade behaviors, access strategies (including Groovy traits), and lazy loading configurations. 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 8f78bdc9be..a52bda7cec 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 @@ -68,7 +68,6 @@ import org.hibernate.mapping.ManyToOne; import org.hibernate.mapping.OneToMany; import org.hibernate.mapping.OneToOne; import org.hibernate.mapping.PersistentClass; -import org.hibernate.mapping.PrimaryKey; import org.hibernate.mapping.Property; import org.hibernate.mapping.RootClass; import org.hibernate.mapping.Selectable; @@ -1585,7 +1584,7 @@ public class GrailsDomainBinder PersistentProperty identifierProp = domainClass.getIdentity(); if (gormMapping == null) { if(identifierProp != null) { - bindSimpleId(identifierProp, root, mappings, null, sessionFactoryBeanName); + bindSimpleId(identifierProp, root, mappings, null, sessionFactoryBeanName, domainClass); } return; } @@ -1605,7 +1604,7 @@ public class GrailsDomainBinder identifierProp = namedIdentityProp; } } - bindSimpleId(identifierProp, root, mappings, identity, sessionFactoryBeanName); + bindSimpleId(identifierProp, root, mappings, identity, sessionFactoryBeanName, domainClass); } } @@ -2009,8 +2008,8 @@ public class GrailsDomainBinder @SuppressWarnings("unchecked") private void bindSimpleId(PersistentProperty identifier, RootClass entity, - InFlightMetadataCollector mappings, Identity mappedId, String sessionFactoryBeanName) { - SimpleIdBinder simpleIdBinder = new SimpleIdBinder(metadataBuildingContext,namingStrategy, getJdbcEnvironment()); + InFlightMetadataCollector mappings, Identity mappedId, String sessionFactoryBeanName, HibernatePersistentEntity domainClass) { + SimpleIdBinder simpleIdBinder = new SimpleIdBinder(metadataBuildingContext,namingStrategy, getJdbcEnvironment(), domainClass); simpleIdBinder.bindSimpleId(identifier, entity, mappedId, getJdbcEnvironment()); } diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/BasicValueIdCreator.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/BasicValueIdCreator.java index 96ac812532..50df2d6257 100644 --- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/BasicValueIdCreator.java +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/BasicValueIdCreator.java @@ -18,18 +18,21 @@ import org.hibernate.id.uuid.UuidGenerator; import org.hibernate.mapping.BasicValue; import org.hibernate.mapping.RootClass; +import org.grails.orm.hibernate.cfg.HibernatePersistentEntity; import org.grails.orm.hibernate.cfg.Identity; public class BasicValueIdCreator { private final MetadataBuildingContext metadataBuildingContext; private JdbcEnvironment jdbcEnvironment; + private HibernatePersistentEntity domainClass; private final Map<String, BiFunction<GeneratorCreationContext, Identity, Generator>> generatorFactories; - public BasicValueIdCreator(MetadataBuildingContext metadataBuildingContext, JdbcEnvironment jdbcEnvironment) { + public BasicValueIdCreator(MetadataBuildingContext metadataBuildingContext, JdbcEnvironment jdbcEnvironment, HibernatePersistentEntity domainClass) { this.metadataBuildingContext = metadataBuildingContext; this.jdbcEnvironment = jdbcEnvironment; this.generatorFactories = new HashMap<>(); + this.domainClass = domainClass; initializeGeneratorFactories(); } @@ -50,7 +53,7 @@ public class BasicValueIdCreator { generatorFactories.put("sequence", sequenceFactory); generatorFactories.put("sequence-identity", sequenceFactory); - generatorFactories.put("increment", (context, mappedId) -> new IncrementGenerator()); + generatorFactories.put("increment", (context, mappedId) -> new GrailsIncrementGenerator(context, mappedId, jdbcEnvironment, domainClass)); generatorFactories.put("uuid", (context, mappedId) -> new UuidGenerator(context.getType().getReturnedClass())); generatorFactories.put("uuid2", (context, mappedId) -> new UuidGenerator(context.getType().getReturnedClass())); generatorFactories.put("assigned", (context, mappedId) -> new Assigned()); diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/GrailsIncrementGenerator.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/GrailsIncrementGenerator.java index 6f7fbe221d..258a25deff 100644 --- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/GrailsIncrementGenerator.java +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/GrailsIncrementGenerator.java @@ -1,17 +1,45 @@ package org.grails.orm.hibernate.cfg.domainbinding; +import org.grails.orm.hibernate.cfg.HibernatePersistentEntity; +import org.grails.orm.hibernate.cfg.Identity; +import org.hibernate.boot.model.relational.Database; +import org.hibernate.boot.model.relational.SqlStringGenerationContext; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; import org.hibernate.generator.GeneratorCreationContext; import org.hibernate.id.IncrementGenerator; - -import java.util.Optional; import java.util.Properties; -import org.grails.orm.hibernate.cfg.Identity; - public class GrailsIncrementGenerator extends IncrementGenerator { - public GrailsIncrementGenerator(GeneratorCreationContext context, org.grails.orm.hibernate.cfg.Identity mappedId) { - var generatorProps = Optional.ofNullable(mappedId).map(Identity::getProperties).orElse(new Properties()); - super.configure(context, generatorProps); + public GrailsIncrementGenerator(GeneratorCreationContext context, Identity mappedId, JdbcEnvironment jdbcEnvironment, HibernatePersistentEntity domainClass) { + Properties params = new Properties(); + if (mappedId != null && mappedId.getProperties() != null) { + params.putAll(mappedId.getProperties()); + } + + // Fix the blank FROM clause: Resolve table name + String tableName = (mappedId != null && mappedId.getName() != null) + ? mappedId.getName() + : domainClass.getMappedForm().getTableName(); + + if (tableName == null || tableName.isEmpty()) { + tableName = domainClass.getJavaClass().getSimpleName(); + } + params.put("table", tableName); + + // Resolve column name + if (!params.containsKey("column")) { + params.put("column", context.getProperty().getName()); + } + + // Initialize the internal Hibernate state + this.configure(context.getType(), params, context.getServiceRegistry()); + } + + @Override + public void registerExportables(Database database) { + // Hibernate 7 IncrementGenerator tries to register table exportables + // which causes the "Unique index or primary key violation" in H2. + // Overriding this to be empty prevents the duplicate DDL. } } \ No newline at end of file diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/SimpleIdBinder.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/SimpleIdBinder.java index 48286fef28..4a1f8b5620 100644 --- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/SimpleIdBinder.java +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/SimpleIdBinder.java @@ -9,6 +9,7 @@ import org.hibernate.mapping.RootClass; import org.hibernate.mapping.Table; import org.grails.datastore.mapping.model.PersistentProperty; +import org.grails.orm.hibernate.cfg.HibernatePersistentEntity; import org.grails.orm.hibernate.cfg.Identity; import org.grails.orm.hibernate.cfg.PersistentEntityNamingStrategy; @@ -21,8 +22,8 @@ public class SimpleIdBinder { private final SimpleValueBinder simpleValueBinder; private final PropertyBinder propertyBinder; - public SimpleIdBinder(MetadataBuildingContext metadataBuildingContext, PersistentEntityNamingStrategy namingStrategy, JdbcEnvironment jdbcEnvironment) { - this.basicValueIdCreator = new BasicValueIdCreator(metadataBuildingContext, jdbcEnvironment); + public SimpleIdBinder(MetadataBuildingContext metadataBuildingContext, PersistentEntityNamingStrategy namingStrategy, JdbcEnvironment jdbcEnvironment, HibernatePersistentEntity domainClass) { + this.basicValueIdCreator = new BasicValueIdCreator(metadataBuildingContext, jdbcEnvironment, domainClass); this.hibernateEntityWrapper = new HibernateEntityWrapper(); this.simpleValueBinder =new SimpleValueBinder(namingStrategy); this.propertyBinder = new PropertyBinder(); diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/SequenceGeneratorsSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/SequenceGeneratorsSpec.groovy index 6e781b96e5..80182e86b4 100644 --- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/SequenceGeneratorsSpec.groovy +++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/SequenceGeneratorsSpec.groovy @@ -74,6 +74,7 @@ class SequenceGeneratorsSpec extends HibernateGormDatastoreSpec { } @Rollback + //TODO Still broken void "test increment generator"() { when: def entity1 = new EntityWithIncrement(name: "test1").save(flush: true)
