This is an automated email from the ASF dual-hosted git repository.

jdaugherty pushed a commit to branch feat/addHibernate7ForgeFeature
in repository https://gitbox.apache.org/repos/asf/grails-core.git


The following commit(s) were added to refs/heads/feat/addHibernate7ForgeFeature 
by this push:
     new 7e4d087e57 Add Hibernate 7 Forge Feature
7e4d087e57 is described below

commit 7e4d087e570ca43f07329061a7ddb185bb4bc685
Author: James Daugherty <[email protected]>
AuthorDate: Thu Jul 9 10:43:02 2026 -0400

    Add Hibernate 7 Forge Feature
---
 .../src/en/guide/commandLine/creatingProject.adoc  |   4 +-
 .../templates/buildSrcBuildGradle.rocker.raw       |   8 +
 .../DatabaseDriverConfigurationFeature.java        |   2 +-
 .../feature/database/DatabaseDriverFeature.java    |  12 +-
 ...ibernateGorm.java => GrailsDataHibernate5.java} |   8 +-
 ...ibernateGorm.java => GrailsDataHibernate7.java} |  18 +-
 .../database/GrailsDataHibernateValidator.java     |  45 +++++
 .../{MongoGorm.java => GrailsDataMongoDB.java}     |   6 +-
 .../grails/forge/feature/database/GraphqlGorm.java |  12 +-
 .../java/org/grails/forge/feature/database/H2.java |   3 +-
 .../org/grails/forge/feature/database/MySQL.java   |   4 +-
 .../grails/forge/feature/database/PostgreSQL.java  |   4 +-
 .../grails/forge/feature/database/SQLServer.java   |   4 +-
 .../forge/feature/database/TestContainers.java     |   2 +-
 .../grails/forge/feature/grails/GrailsBase.java    |  17 +-
 .../feature/migration/DatabaseMigrationPlugin.java |   8 +-
 .../java/org/grails/forge/options/GormImpl.java    |   1 +
 ...Spec.groovy => GrailsDataHibernate5Spec.groovy} |   2 +-
 .../database/GrailsDataHibernate7Spec.groovy       | 199 +++++++++++++++++++++
 ...ormSpec.groovy => GrailsDataMongoDBSpec.groovy} |   2 +-
 20 files changed, 314 insertions(+), 47 deletions(-)

diff --git a/grails-doc/src/en/guide/commandLine/creatingProject.adoc 
b/grails-doc/src/en/guide/commandLine/creatingProject.adoc
index 73091f24d5..7bd657235b 100644
--- a/grails-doc/src/en/guide/commandLine/creatingProject.adoc
+++ b/grails-doc/src/en/guide/commandLine/creatingProject.adoc
@@ -159,7 +159,7 @@ The "create-*" commands are used to produce a fundamental 
Grails project, allowi
 ----
 
 | -g, --gorm
-| Which GORM Implementation to configure. Possible values: hibernate, mongodb, 
neo4j.
+| Which GORM Implementation to configure. Possible values: hibernate, 
hibernate7, mongodb.
 |
 [source,shell]
 ----
@@ -175,7 +175,7 @@ The "create-*" commands are used to produce a fundamental 
Grails project, allowi
 ----
 
 | -f, --features
-| The features to use. Possible values: h2, gorm-hibernate5, 
spring-boot-starter-jetty, micronaut-http-client, cache-ehcache, 
hibernate-validator, postgres, mysql, cache, database-migration, grails-gsp, 
hamcrest, gorm-mongodb, assertj, mockito, spring-boot-starter-undertow, 
github-workflow-java-ci, jrebel, testcontainers, sqlserver, grails-console, 
views-markup, views-json, gorm-neo4j, asciidoctor, grails-web-console, 
logbackGroovy, mongo-sync, shade, properties
+| The features to use. Possible values: h2, gorm-hibernate5, gorm-hibernate7, 
spring-boot-starter-jetty, micronaut-http-client, cache-ehcache, 
hibernate-validator, postgres, mysql, cache, database-migration, grails-gsp, 
hamcrest, gorm-mongodb, assertj, mockito, spring-boot-starter-undertow, 
github-workflow-java-ci, jrebel, testcontainers, sqlserver, grails-console, 
views-markup, views-json, gorm-neo4j, asciidoctor, grails-web-console, 
logbackGroovy, mongo-sync, shade, properties
 |
 [source,shell]
 ----
diff --git 
a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/build/gradle/templates/buildSrcBuildGradle.rocker.raw
 
b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/build/gradle/templates/buildSrcBuildGradle.rocker.raw
index 19a117319d..1dff5a907c 100644
--- 
a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/build/gradle/templates/buildSrcBuildGradle.rocker.raw
+++ 
b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/build/gradle/templates/buildSrcBuildGradle.rocker.raw
@@ -51,7 +51,15 @@ repositories {
 }
 
 dependencies {
+@if (features.contains("gorm-hibernate7") && 
features.contains("grails-micronaut")) {
+    implementation 
platform("org.apache.grails:grails-hibernate7-micronaut-bom:$grailsVersion")
+} else if (features.contains("grails-micronaut")) {
+    implementation 
platform("org.apache.grails:grails-micronaut-bom:$grailsVersion")
+} else if (features.contains("gorm-hibernate7")) {
+    implementation 
platform("org.apache.grails:grails-hibernate7-bom:$grailsVersion")
+} else {
     implementation platform("org.apache.grails:grails-bom:$grailsVersion")
+}
 @for (GradleDependency dependency : gradleBuild.getBuildSrcDependencies()) {
     @dependency.toSnippet()
 }
diff --git 
a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/DatabaseDriverConfigurationFeature.java
 
b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/DatabaseDriverConfigurationFeature.java
index 4fc8641e0b..cc64745340 100644
--- 
a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/DatabaseDriverConfigurationFeature.java
+++ 
b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/DatabaseDriverConfigurationFeature.java
@@ -28,7 +28,7 @@ import static 
org.grails.forge.feature.config.ConfigurationFeature.TEST_ENVIRONM
 import static 
org.grails.forge.feature.config.ConfigurationFeature.PROD_ENVIRONMENT_KEY;
 import static 
org.grails.forge.feature.config.ConfigurationFeature.ENVIRONMENTS_KEY;
 import static 
org.grails.forge.feature.config.ConfigurationFeature.PROPERTIES_KEY;
-import static org.grails.forge.feature.database.HibernateGorm.PREFIX;
+import static org.grails.forge.feature.database.GrailsDataHibernate5.PREFIX;
 
 /**
  * A feature that configures a datasource with a driver
diff --git 
a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/DatabaseDriverFeature.java
 
b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/DatabaseDriverFeature.java
index ead67ce4ba..e2272efa67 100644
--- 
a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/DatabaseDriverFeature.java
+++ 
b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/DatabaseDriverFeature.java
@@ -29,15 +29,15 @@ import java.util.Map;
 public abstract class DatabaseDriverFeature implements OneOfFeature {
 
     private final TestContainers testContainers;
-    private final HibernateGorm hibernateGorm;
+    private final GrailsDataHibernate5 grailsDataHibernate5;
 
     public DatabaseDriverFeature() {
         this.testContainers = null;
-        this.hibernateGorm = null;
+        this.grailsDataHibernate5 = null;
     }
 
-    public DatabaseDriverFeature(HibernateGorm hibernateGorm, TestContainers 
testContainers) {
-        this.hibernateGorm = hibernateGorm;
+    public DatabaseDriverFeature(GrailsDataHibernate5 grailsDataHibernate5, 
TestContainers testContainers) {
+        this.grailsDataHibernate5 = grailsDataHibernate5;
         this.testContainers = testContainers;
     }
 
@@ -56,8 +56,8 @@ public abstract class DatabaseDriverFeature implements 
OneOfFeature {
         if (!featureContext.isPresent(TestContainers.class) && testContainers 
!= null) {
             featureContext.addFeature(testContainers);
         }
-        if (!featureContext.isPresent(HibernateGorm.class) && hibernateGorm != 
null) {
-            featureContext.addFeature(hibernateGorm);
+        if (!featureContext.isPresent(GrailsDataHibernate5.class) && 
grailsDataHibernate5 != null) {
+            featureContext.addFeature(grailsDataHibernate5);
         }
     }
 
diff --git 
a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/HibernateGorm.java
 
b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/GrailsDataHibernate5.java
similarity index 91%
copy from 
grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/HibernateGorm.java
copy to 
grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/GrailsDataHibernate5.java
index 568030e73f..280fb3d9b8 100644
--- 
a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/HibernateGorm.java
+++ 
b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/GrailsDataHibernate5.java
@@ -33,7 +33,7 @@ import java.util.Set;
 
 @Primary
 @Singleton
-public class HibernateGorm extends GormFeature implements 
DatabaseDriverConfigurationFeature {
+public class GrailsDataHibernate5 extends GormFeature implements 
DatabaseDriverConfigurationFeature {
 
     static final String PREFIX = "dataSource.";
     private static final String URL_KEY = PREFIX + "url";
@@ -44,7 +44,7 @@ public class HibernateGorm extends GormFeature implements 
DatabaseDriverConfigur
 
     private final DatabaseDriverFeature defaultDbFeature;
 
-    public HibernateGorm(DatabaseDriverFeature defaultDbFeature) {
+    public GrailsDataHibernate5(DatabaseDriverFeature defaultDbFeature) {
         this.defaultDbFeature = defaultDbFeature;
     }
 
@@ -123,6 +123,8 @@ public class HibernateGorm extends GormFeature implements 
DatabaseDriverConfigur
 
     @Override
     public boolean shouldApply(ApplicationType applicationType, Options 
options, Set<Feature> selectedFeatures) {
-        return selectedFeatures.stream().anyMatch(f -> f instanceof 
HibernateGorm) || options.getGormImpl() == GormImpl.HIBERNATE;
+        return selectedFeatures.stream().anyMatch(f -> f instanceof 
GrailsDataHibernate5)
+                || (options.getGormImpl() == GormImpl.HIBERNATE
+                        && 
selectedFeatures.stream().noneMatch(GrailsDataHibernate7.class::isInstance));
     }
 }
diff --git 
a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/HibernateGorm.java
 
b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/GrailsDataHibernate7.java
similarity index 86%
rename from 
grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/HibernateGorm.java
rename to 
grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/GrailsDataHibernate7.java
index 568030e73f..43f7c0a4b7 100644
--- 
a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/HibernateGorm.java
+++ 
b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/GrailsDataHibernate7.java
@@ -18,7 +18,6 @@
  */
 package org.grails.forge.feature.database;
 
-import io.micronaut.context.annotation.Primary;
 import jakarta.inject.Singleton;
 import org.grails.forge.application.ApplicationType;
 import org.grails.forge.application.generator.GeneratorContext;
@@ -31,9 +30,8 @@ import org.grails.forge.options.Options;
 import java.util.Map;
 import java.util.Set;
 
-@Primary
 @Singleton
-public class HibernateGorm extends GormFeature implements 
DatabaseDriverConfigurationFeature {
+public class GrailsDataHibernate7 extends GormFeature implements 
DatabaseDriverConfigurationFeature {
 
     static final String PREFIX = "dataSource.";
     private static final String URL_KEY = PREFIX + "url";
@@ -44,23 +42,23 @@ public class HibernateGorm extends GormFeature implements 
DatabaseDriverConfigur
 
     private final DatabaseDriverFeature defaultDbFeature;
 
-    public HibernateGorm(DatabaseDriverFeature defaultDbFeature) {
+    public GrailsDataHibernate7(DatabaseDriverFeature defaultDbFeature) {
         this.defaultDbFeature = defaultDbFeature;
     }
 
     @Override
     public String getName() {
-        return "gorm-hibernate5";
+        return "gorm-hibernate7";
     }
 
     @Override
     public String getTitle() {
-        return "GORM for Hibernate 5";
+        return "GORM for Hibernate 7";
     }
 
     @Override
     public String getDescription() {
-        return "Configure GORM for using Hibernate 5.";
+        return "Configure GORM for using Hibernate 7.";
     }
 
     @Override
@@ -84,11 +82,11 @@ public class HibernateGorm extends GormFeature implements 
DatabaseDriverConfigur
 
         generatorContext.addBuildscriptDependency(Dependency.builder()
                 .groupId("org.apache.grails")
-                .artifactId("grails-data-hibernate5")
+                .artifactId("grails-data-hibernate7")
                 .buildSrc());
         generatorContext.addDependency(Dependency.builder()
                 .groupId("org.apache.grails")
-                .artifactId("grails-data-hibernate5")
+                .artifactId("grails-data-hibernate7")
                 .implementation());
         generatorContext.addDependency(Dependency.builder()
                 .groupId("com.zaxxer")
@@ -123,6 +121,6 @@ public class HibernateGorm extends GormFeature implements 
DatabaseDriverConfigur
 
     @Override
     public boolean shouldApply(ApplicationType applicationType, Options 
options, Set<Feature> selectedFeatures) {
-        return selectedFeatures.stream().anyMatch(f -> f instanceof 
HibernateGorm) || options.getGormImpl() == GormImpl.HIBERNATE;
+        return 
selectedFeatures.stream().anyMatch(GrailsDataHibernate7.class::isInstance) || 
options.getGormImpl() == GormImpl.HIBERNATE7;
     }
 }
diff --git 
a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/GrailsDataHibernateValidator.java
 
b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/GrailsDataHibernateValidator.java
new file mode 100644
index 0000000000..912e163c49
--- /dev/null
+++ 
b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/GrailsDataHibernateValidator.java
@@ -0,0 +1,45 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    https://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.grails.forge.feature.database;
+
+import java.util.Set;
+
+import jakarta.inject.Singleton;
+
+import org.grails.forge.application.ApplicationType;
+import org.grails.forge.feature.Feature;
+import org.grails.forge.feature.validation.FeatureValidator;
+import org.grails.forge.options.Options;
+
+@Singleton
+public class GrailsDataHibernateValidator implements FeatureValidator {
+
+    @Override
+    public void validatePreProcessing(Options options, ApplicationType 
applicationType, Set<Feature> features) {
+        if (features.stream().anyMatch(GrailsDataHibernate5.class::isInstance)
+                && 
features.stream().anyMatch(GrailsDataHibernate7.class::isInstance)) {
+            throw new IllegalArgumentException("Only one GORM for Hibernate 
implementation can be selected: gorm-hibernate5 or gorm-hibernate7");
+        }
+    }
+
+    @Override
+    public void validatePostProcessing(Options options, ApplicationType 
applicationType, Set<Feature> features) {
+
+    }
+}
diff --git 
a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/MongoGorm.java
 
b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/GrailsDataMongoDB.java
similarity index 93%
rename from 
grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/MongoGorm.java
rename to 
grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/GrailsDataMongoDB.java
index d81b0e1523..94df495e9f 100644
--- 
a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/MongoGorm.java
+++ 
b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/GrailsDataMongoDB.java
@@ -32,11 +32,11 @@ import java.util.Map;
 import java.util.Set;
 
 @Singleton
-public class MongoGorm extends GormOneOfFeature {
+public class GrailsDataMongoDB extends GormOneOfFeature {
 
     private final TestContainers testContainers;
 
-    public MongoGorm(TestContainers testContainers) {
+    public GrailsDataMongoDB(TestContainers testContainers) {
         this.testContainers = testContainers;
     }
 
@@ -76,7 +76,7 @@ public class MongoGorm extends GormOneOfFeature {
 
     @Override
     public boolean shouldApply(ApplicationType applicationType, Options 
options, Set<Feature> selectedFeatures) {
-        return selectedFeatures.stream().anyMatch(f -> f instanceof MongoGorm) 
|| options.getGormImpl() == GormImpl.MONGODB;
+        return selectedFeatures.stream().anyMatch(f -> f instanceof 
GrailsDataMongoDB) || options.getGormImpl() == GormImpl.MONGODB;
     }
 
     @Nullable
diff --git 
a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/GraphqlGorm.java
 
b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/GraphqlGorm.java
index fb95865920..1e06d0975f 100644
--- 
a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/GraphqlGorm.java
+++ 
b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/GraphqlGorm.java
@@ -31,18 +31,18 @@ import org.grails.forge.feature.FeatureContext;
  * Adds the {@code grails-data-graphql} plugin to the generated application.
  *
  * <p>GraphQL is a layer on top of GORM rather than a GORM implementation, so
- * this feature is selectable in addition to (not instead of) {@link 
HibernateGorm}
- * or {@link MongoGorm}. If the user opts into GraphQL without explicitly
+ * this feature is selectable in addition to (not instead of) {@link 
GrailsDataHibernate5}
+ * or {@link GrailsDataMongoDB}. If the user opts into GraphQL without 
explicitly
  * selecting a GORM persistence layer, Hibernate is added as a sensible default
  * via {@link #processSelectedFeatures(FeatureContext)}.</p>
  */
 @Singleton
 public class GraphqlGorm implements Feature {
 
-    private final HibernateGorm hibernateGorm;
+    private final GrailsDataHibernate5 grailsDataHibernate5;
 
-    public GraphqlGorm(HibernateGorm hibernateGorm) {
-        this.hibernateGorm = hibernateGorm;
+    public GraphqlGorm(GrailsDataHibernate5 grailsDataHibernate5) {
+        this.grailsDataHibernate5 = grailsDataHibernate5;
     }
 
     @Override
@@ -75,7 +75,7 @@ public class GraphqlGorm implements Feature {
         // GraphQL needs a GORM implementation to introspect; default to 
Hibernate
         // when the user has not explicitly chosen a GORM provider.
         if (!featureContext.isPresent(GormFeature.class) && 
!featureContext.isPresent(GormOneOfFeature.class)) {
-            featureContext.addFeature(hibernateGorm);
+            featureContext.addFeature(grailsDataHibernate5);
         }
     }
 
diff --git 
a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/H2.java
 
b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/H2.java
index 93e924e9d7..19be11c6bd 100644
--- 
a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/H2.java
+++ 
b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/H2.java
@@ -25,6 +25,7 @@ import 
org.grails.forge.application.generator.GeneratorContext;
 import org.grails.forge.build.dependencies.Dependency;
 import org.grails.forge.feature.DefaultFeature;
 import org.grails.forge.feature.Feature;
+import org.grails.forge.options.GormImpl;
 import org.grails.forge.options.Options;
 
 import java.util.Set;
@@ -99,7 +100,7 @@ public class H2 extends DatabaseDriverFeature implements 
DefaultFeature {
 
     @Override
     public boolean shouldApply(ApplicationType applicationType, Options 
options, Set<Feature> selectedFeatures) {
-        return options.getGormImpl().getName().equals("gorm-hibernate5") &&
+        return (options.getGormImpl() == GormImpl.HIBERNATE || 
options.getGormImpl() == GormImpl.HIBERNATE7) &&
                 selectedFeatures.stream().noneMatch(f -> f instanceof 
DatabaseDriverFeature);
     }
 }
diff --git 
a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/MySQL.java
 
b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/MySQL.java
index 6518bc3ae0..88fef13f8f 100644
--- 
a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/MySQL.java
+++ 
b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/MySQL.java
@@ -26,8 +26,8 @@ import org.grails.forge.build.dependencies.Dependency;
 @Singleton
 public class MySQL extends DatabaseDriverFeature {
 
-    public MySQL(HibernateGorm hibernateGorm, TestContainers testContainers) {
-        super(hibernateGorm, testContainers);
+    public MySQL(GrailsDataHibernate5 grailsDataHibernate5, TestContainers 
testContainers) {
+        super(grailsDataHibernate5, testContainers);
     }
 
     @Override
diff --git 
a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/PostgreSQL.java
 
b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/PostgreSQL.java
index 7c06dd46f9..0858a412b7 100644
--- 
a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/PostgreSQL.java
+++ 
b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/PostgreSQL.java
@@ -26,8 +26,8 @@ import org.grails.forge.build.dependencies.Dependency;
 @Singleton
 public class PostgreSQL extends DatabaseDriverFeature {
 
-    public PostgreSQL(HibernateGorm hibernateGorm, TestContainers 
testContainers) {
-        super(hibernateGorm, testContainers);
+    public PostgreSQL(GrailsDataHibernate5 grailsDataHibernate5, 
TestContainers testContainers) {
+        super(grailsDataHibernate5, testContainers);
     }
 
     @Override
diff --git 
a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/SQLServer.java
 
b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/SQLServer.java
index 040905a790..242c6a0cf0 100644
--- 
a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/SQLServer.java
+++ 
b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/SQLServer.java
@@ -26,8 +26,8 @@ import org.grails.forge.build.dependencies.Dependency;
 @Singleton
 public class SQLServer extends DatabaseDriverFeature {
 
-    public SQLServer(HibernateGorm hibernateGorm, TestContainers 
testContainers) {
-        super(hibernateGorm, testContainers);
+    public SQLServer(GrailsDataHibernate5 grailsDataHibernate5, TestContainers 
testContainers) {
+        super(grailsDataHibernate5, testContainers);
     }
 
     @Override
diff --git 
a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/TestContainers.java
 
b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/TestContainers.java
index 10b4b6e8d5..0e545766c3 100644
--- 
a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/TestContainers.java
+++ 
b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/database/TestContainers.java
@@ -82,7 +82,7 @@ public class TestContainers implements Feature {
             
generatorContext.addDependency(testContainerTestDependency("testcontainers-spock"));
         }
 
-        if (generatorContext.isFeaturePresent(MongoFeature.class) || 
generatorContext.isFeaturePresent(MongoGorm.class)) {
+        if (generatorContext.isFeaturePresent(MongoFeature.class) || 
generatorContext.isFeaturePresent(GrailsDataMongoDB.class)) {
             
generatorContext.addDependency(testContainerTestDependency("testcontainers-mongodb"));
         }
     }
diff --git 
a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/grails/GrailsBase.java
 
b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/grails/GrailsBase.java
index a784fc573a..ae4df33112 100644
--- 
a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/grails/GrailsBase.java
+++ 
b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/grails/GrailsBase.java
@@ -24,6 +24,7 @@ import 
org.grails.forge.application.generator.GeneratorContext;
 import org.grails.forge.build.dependencies.Dependency;
 import org.grails.forge.feature.DefaultFeature;
 import org.grails.forge.feature.Feature;
+import org.grails.forge.feature.database.GrailsDataHibernate7;
 import org.grails.forge.feature.micronaut.GrailsMicronaut;
 import org.grails.forge.options.Options;
 import org.grails.forge.template.URLTemplate;
@@ -56,10 +57,18 @@ public class GrailsBase implements DefaultFeature {
     @Override
     public void apply(GeneratorContext generatorContext) {
 
-        // When Micronaut is used, the application must consume 
grails-micronaut-bom as an
-        // enforcedPlatform so the Micronaut platform cannot override 
grails-bom
+        // When Micronaut is used, the application must consume the Micronaut 
BOM variant as an
+        // enforcedPlatform so the Micronaut platform cannot override the 
Grails BOM. The
+        // Hibernate 7 BOM variants pin the Hibernate 7 dependency versions 
(e.g. jandex) that
+        // conflict with the default (Hibernate 5) grails-bom - see 
grails-core issue #15942.
         boolean useMicronautBom = 
generatorContext.isFeaturePresent(GrailsMicronaut.class);
-        String bomArtifactId = useMicronautBom ? "grails-micronaut-bom" : 
"grails-bom";
+        boolean useHibernate7Bom = 
generatorContext.isFeaturePresent(GrailsDataHibernate7.class);
+        String bomArtifactId;
+        if (useMicronautBom) {
+            bomArtifactId = useHibernate7Bom ? 
"grails-hibernate7-micronaut-bom" : "grails-micronaut-bom";
+        } else {
+            bomArtifactId = useHibernate7Bom ? "grails-hibernate7-bom" : 
"grails-bom";
+        }
 
         generatorContext.addDependency(Dependency.builder()
                 .groupId("org.apache.grails")
@@ -71,7 +80,7 @@ public class GrailsBase implements DefaultFeature {
 
         generatorContext.addBuildscriptDependency(Dependency.builder()
                 .groupId("org.apache.grails")
-                .artifactId("grails-bom")
+                .artifactId(bomArtifactId)
                 .pom(true)
                 .version("$grailsVersion")
                 .classpath());
diff --git 
a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/migration/DatabaseMigrationPlugin.java
 
b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/migration/DatabaseMigrationPlugin.java
index 413d849cba..70155a58e1 100644
--- 
a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/migration/DatabaseMigrationPlugin.java
+++ 
b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/feature/migration/DatabaseMigrationPlugin.java
@@ -21,6 +21,7 @@ package org.grails.forge.feature.migration;
 import jakarta.inject.Singleton;
 import org.grails.forge.application.generator.GeneratorContext;
 import org.grails.forge.build.dependencies.Dependency;
+import org.grails.forge.feature.database.GrailsDataHibernate7;
 import org.grails.forge.feature.migration.templates.dbMigrationGradle;
 import org.grails.forge.template.RockerWritable;
 import org.grails.forge.template.URLTemplate;
@@ -57,14 +58,17 @@ public class DatabaseMigrationPlugin implements 
MigrationFeature {
     @Override
     public void apply(GeneratorContext generatorContext) {
         final String srcDirPath = getSrcDirPath();
+        final String dbMigrationArtifactId = 
generatorContext.isFeaturePresent(GrailsDataHibernate7.class)
+                ? "grails-data-hibernate7-dbmigration"
+                : "grails-data-hibernate5-dbmigration";
         generatorContext.addBuildscriptDependency(Dependency.builder()
                 .groupId("org.apache.grails")
-                .artifactId("grails-data-hibernate5-dbmigration")
+                .artifactId(dbMigrationArtifactId)
                 .buildSrc()
                 .extension(new 
RockerWritable(dbMigrationGradle.template(srcDirPath))));
         generatorContext.addDependency(Dependency.builder()
                 .groupId("org.apache.grails")
-                .artifactId("grails-data-hibernate5-dbmigration")
+                .artifactId(dbMigrationArtifactId)
                 .implementation());
 
         final ClassLoader classLoader = 
Thread.currentThread().getContextClassLoader();
diff --git 
a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/options/GormImpl.java
 
b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/options/GormImpl.java
index 3bfc9ac5d2..1c53118c8e 100644
--- 
a/grails-forge/grails-forge-core/src/main/java/org/grails/forge/options/GormImpl.java
+++ 
b/grails-forge/grails-forge-core/src/main/java/org/grails/forge/options/GormImpl.java
@@ -23,6 +23,7 @@ import io.micronaut.core.annotation.NonNull;
 public enum GormImpl {
 
     HIBERNATE("gorm-hibernate5", "Hibernate 5"),
+    HIBERNATE7("gorm-hibernate7", "Hibernate 7"),
     MONGODB("gorm-mongodb", "MongoDB");
 
     public static final GormImpl DEFAULT_OPTION = HIBERNATE;
diff --git 
a/grails-forge/grails-forge-core/src/test/groovy/org/grails/forge/feature/database/HibernateGormSpec.groovy
 
b/grails-forge/grails-forge-core/src/test/groovy/org/grails/forge/feature/database/GrailsDataHibernate5Spec.groovy
similarity index 97%
rename from 
grails-forge/grails-forge-core/src/test/groovy/org/grails/forge/feature/database/HibernateGormSpec.groovy
rename to 
grails-forge/grails-forge-core/src/test/groovy/org/grails/forge/feature/database/GrailsDataHibernate5Spec.groovy
index d24c6c7936..7aae8c4a2d 100644
--- 
a/grails-forge/grails-forge-core/src/test/groovy/org/grails/forge/feature/database/HibernateGormSpec.groovy
+++ 
b/grails-forge/grails-forge-core/src/test/groovy/org/grails/forge/feature/database/GrailsDataHibernate5Spec.groovy
@@ -31,7 +31,7 @@ import org.grails.forge.options.JdkVersion
 import org.grails.forge.options.Options
 import org.grails.forge.options.TestFramework
 
-class HibernateGormSpec extends ApplicationContextSpec implements 
CommandOutputFixture{
+class GrailsDataHibernate5Spec extends ApplicationContextSpec implements 
CommandOutputFixture{
 
     void "test hibernate gorm features"() {
         when:
diff --git 
a/grails-forge/grails-forge-core/src/test/groovy/org/grails/forge/feature/database/GrailsDataHibernate7Spec.groovy
 
b/grails-forge/grails-forge-core/src/test/groovy/org/grails/forge/feature/database/GrailsDataHibernate7Spec.groovy
new file mode 100644
index 0000000000..c795b6e039
--- /dev/null
+++ 
b/grails-forge/grails-forge-core/src/test/groovy/org/grails/forge/feature/database/GrailsDataHibernate7Spec.groovy
@@ -0,0 +1,199 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    https://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.grails.forge.feature.database
+
+import groovy.yaml.YamlSlurper
+import org.grails.forge.ApplicationContextSpec
+import org.grails.forge.BuildBuilder
+import org.grails.forge.application.ApplicationType
+import org.grails.forge.application.generator.GeneratorContext
+import org.grails.forge.feature.Features
+import org.grails.forge.fixture.CommandOutputFixture
+import org.grails.forge.options.DevelopmentReloading
+import org.grails.forge.options.GormImpl
+import org.grails.forge.options.JdkVersion
+import org.grails.forge.options.Options
+import org.grails.forge.options.ServletImpl
+
+class GrailsDataHibernate7Spec extends ApplicationContextSpec implements 
CommandOutputFixture {
+
+    private static Options hibernate7Options() {
+        new Options(DevelopmentReloading.DEVTOOLS, GormImpl.HIBERNATE7, 
ServletImpl.DEFAULT_OPTION, JdkVersion.DEFAULT_OPTION)
+    }
+
+    void "test hibernate 7 gorm features"() {
+        when:
+        Features features = getFeatures(['gorm-hibernate7'])
+
+        then:
+        features.contains("h2")
+        features.contains("gorm-hibernate7")
+        !features.contains("gorm-hibernate5")
+    }
+
+    void "test dependencies are present for gradle"() {
+        when:
+        final String template = new BuildBuilder(beanContext)
+                .features(["gorm-hibernate7"])
+                .render()
+
+        then:
+        template.contains('implementation 
"org.apache.grails:grails-data-hibernate7"')
+        template.contains('runtimeOnly "com.zaxxer:HikariCP"')
+        template.contains('runtimeOnly "com.h2database:h2"')
+        !template.contains('grails-data-hibernate5')
+    }
+
+    void "test hibernate 7 bom is used for gradle"() {
+        when:
+        final String template = new BuildBuilder(beanContext)
+                .features(["gorm-hibernate7"])
+                .render()
+
+        then:
+        template.contains('org.apache.grails:grails-hibernate7-bom')
+        !template.contains('org.apache.grails:grails-bom')
+    }
+
+    void "test hibernate 7 micronaut bom is used when micronaut is added"() {
+        when:
+        final String template = new BuildBuilder(beanContext)
+                .features(["gorm-hibernate7", "grails-micronaut"])
+                .jdkVersion(JdkVersion.JDK_25)
+                .render()
+
+        then: 'the application consumes the Hibernate 7 Micronaut BOM variant 
as an enforced platform'
+        template.contains('implementation 
enforcedPlatform("org.apache.grails:grails-hibernate7-micronaut-bom:$grailsVersion")')
+        !template.contains('org.apache.grails:grails-micronaut-bom')
+
+        and: 'the buildscript classpath uses the Hibernate 7 Micronaut BOM 
variant'
+        template.contains('classpath 
platform("org.apache.grails:grails-hibernate7-micronaut-bom:$grailsVersion")')
+        !template.contains('org.apache.grails:grails-hibernate7-bom:')
+    }
+
+    void "test buildSrc uses the hibernate 7 micronaut bom when micronaut is 
added"() {
+        when:
+        final String template = new BuildBuilder(beanContext)
+                .features(["gorm-hibernate7", "grails-micronaut"])
+                .jdkVersion(JdkVersion.JDK_25)
+                .renderBuildSrc()
+
+        then:
+        template.contains('implementation 
platform("org.apache.grails:grails-hibernate7-micronaut-bom:$grailsVersion")')
+        !template.contains('org.apache.grails:grails-hibernate7-bom:')
+        !template.contains('org.apache.grails:grails-bom:')
+    }
+
+    void "test buildSrc uses the micronaut bom when micronaut is added without 
hibernate 7"() {
+        when:
+        final String template = new BuildBuilder(beanContext)
+                .features(["gorm-hibernate5", "grails-micronaut"])
+                .jdkVersion(JdkVersion.JDK_25)
+                .renderBuildSrc()
+
+        then:
+        template.contains('implementation 
platform("org.apache.grails:grails-micronaut-bom:$grailsVersion")')
+        !template.contains('grails-hibernate7-micronaut-bom')
+        !template.contains('org.apache.grails:grails-bom:')
+    }
+
+    void "test hibernate 5 micronaut bom is used when micronaut is added 
without hibernate 7"() {
+        when:
+        final String template = new BuildBuilder(beanContext)
+                .features(["gorm-hibernate5", "grails-micronaut"])
+                .jdkVersion(JdkVersion.JDK_25)
+                .render()
+
+        then:
+        template.contains('org.apache.grails:grails-micronaut-bom')
+        !template.contains('grails-hibernate7-micronaut-bom')
+    }
+
+    void "test dependencies are present for buildSrc"() {
+        when:
+        final String template = new BuildBuilder(beanContext)
+                .features(["gorm-hibernate7"])
+                .renderBuildSrc()
+
+        then:
+        template.contains('implementation 
platform("org.apache.grails:grails-hibernate7-bom:$grailsVersion")')
+        template.contains('implementation 
"org.apache.grails:grails-data-hibernate7"')
+        !template.contains('org.apache.grails:grails-bom')
+        !template.contains('grails-data-hibernate5')
+    }
+
+    void "test buildSrc is present for buildscript dependencies"() {
+        given:
+        final def output = generate(ApplicationType.WEB, hibernate7Options())
+        final def buildGradle = output["build.gradle"]
+
+        expect:
+        buildGradle != null
+        buildGradle.contains("classpath 
\"org.apache.grails:grails-data-hibernate7\"")
+        !buildGradle.contains("grails-data-hibernate5")
+    }
+
+    void "test database migration uses the hibernate 7 artifact"() {
+        when:
+        final String template = new BuildBuilder(beanContext)
+                .features(["gorm-hibernate7", "database-migration"])
+                .render()
+
+        then:
+        template.contains('grails-data-hibernate7-dbmigration')
+        !template.contains('grails-data-hibernate5-dbmigration')
+    }
+
+    void "test selecting both hibernate implementations is rejected"() {
+        when:
+        getFeatures(['gorm-hibernate5', 'gorm-hibernate7'])
+
+        then:
+        IllegalArgumentException e = thrown()
+        e.message.contains('Only one GORM for Hibernate implementation can be 
selected')
+    }
+
+    void "test config"() {
+        when:
+        GeneratorContext ctx = buildGeneratorContext(['gorm-hibernate7'])
+
+        then:
+        ctx.configuration.containsKey("dataSource.pooled")
+        ctx.configuration.containsKey("dataSource.jmxExport")
+        ctx.configuration.containsKey("hibernate.cache.queries")
+        ctx.configuration.containsKey("hibernate.cache.use_second_level_cache")
+        ctx.configuration.containsKey("hibernate.cache.use_query_cache")
+    }
+
+    void "test match values of datasource config"() {
+        when:
+        final def output = generate(ApplicationType.WEB, hibernate7Options())
+        final String applicationYaml = 
output["grails-app/conf/application.yml"]
+        def config = new YamlSlurper().parseText(applicationYaml)
+
+        then:
+        config.environments.development.dataSource.dbCreate == 'create-drop'
+        config.environments.test.dataSource.dbCreate == 'update'
+        config.environments.production.dataSource.dbCreate == 'none'
+        config.environments.development.dataSource.url == 
'jdbc:h2:mem:devDb;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE'
+        config.environments.test.dataSource.url == 
'jdbc:h2:mem:testDb;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE'
+        config.environments.production.dataSource.url == 
'jdbc:h2:./prodDb;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE'
+    }
+}
diff --git 
a/grails-forge/grails-forge-core/src/test/groovy/org/grails/forge/feature/database/MongoGormSpec.groovy
 
b/grails-forge/grails-forge-core/src/test/groovy/org/grails/forge/feature/database/GrailsDataMongoDBSpec.groovy
similarity index 95%
rename from 
grails-forge/grails-forge-core/src/test/groovy/org/grails/forge/feature/database/MongoGormSpec.groovy
rename to 
grails-forge/grails-forge-core/src/test/groovy/org/grails/forge/feature/database/GrailsDataMongoDBSpec.groovy
index c8a0eda408..cd516d0134 100644
--- 
a/grails-forge/grails-forge-core/src/test/groovy/org/grails/forge/feature/database/MongoGormSpec.groovy
+++ 
b/grails-forge/grails-forge-core/src/test/groovy/org/grails/forge/feature/database/GrailsDataMongoDBSpec.groovy
@@ -25,7 +25,7 @@ import org.grails.forge.application.generator.GeneratorContext
 import org.grails.forge.feature.Features
 import org.grails.forge.fixture.CommandOutputFixture
 
-class MongoGormSpec extends ApplicationContextSpec implements 
CommandOutputFixture {
+class GrailsDataMongoDBSpec extends ApplicationContextSpec implements 
CommandOutputFixture {
 
     void "test Mongo gorm features"() {
         when:


Reply via email to