You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@grails.apache.org by bo...@apache.org on 2026/03/09 18:04:32 UTC

(grails-core) branch 8.0.x-hibernate7-dev updated (3fee034f15 -> 91b95a39da)

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

borinquenkid pushed a change to branch 8.0.x-hibernate7-dev
in repository https://gitbox.apache.org/repos/asf/grails-core.git


    from 3fee034f15 cleanup(hibernate7):  use Hibernate-specific types in ForeignKeyColumnCountCalculator and related specs
     new 92865b44c4 BRANCHES.md
     new 217121b3c4 hibernate7: CloseSuppressingInvocationHandler
     new 4bc5c19e75 hibernate7: clean up GrailsHibernateTemplate
     new 52e55831a0 hibernate7: spec for HibernateDatastoreConnectionSourcesRegistrar
     new 2b4b3b4edc hibernate7: spec for GrailsSessionContext and InstanceApiHelper
     new 32d3c5c314 hibernate7: cleanup ListSecondPassBinder
     new 769a062fcd hibernate7: cleanup GrailsHibernateUtil
     new 958812ad8d hibernate7: cleanup update MapSecondPassBinderSpec
     new dace182920 hibernate7: cleanup update MapSecondPassBinderSpec
     new f25e8b8716 hibernate7: cleanup update GrailsHibernateQueryUtils
     new f44737e51c hibernate7: PredicateGenerator now uses ConversionService to coerce accidental String to Number
     new d5de3307bf hibernate7: Refactoring GrailsHibernateQueryUtils and HibernateGormStaticApi
     new 45b9743bf4 hibernate7: Refactoring HibernateGormStaticApi
     new 2544aea26e hibernate7: removing GrailsHibernateQueryUtils.java
     new 845862793a hibernate7: cleanup HibernateHqlQuery
     new 798bd1059e hibernate7: add Positional Parameters support
     new c4fbe5f085 hibernate7: codenarc
     new 97d831e219 hibernate7: more Codenarc
     new ada4f05255 hibernate7: more Codenarc
     new 03aaad8813 hibernate7: more Codenarc
     new 117af70c0c hibernate7: more Codenarc
     new 5243c05169 hibernate7: more Codenarc
     new 0d8ad400fd hibernate7: more Codenarc
     new afd4c177af hibernate7: removed deprecated code from HibernateGormInstanceApi
     new 2334ce725b hibernate7: more CodeNarc
     new ad31671b7b hibernate7: more CodeNarc
     new d2f1d42738 hibernate7: more CodeNarc
     new 613b2d8964 hibernate7: more CodeNarc
     new a4617c9106 hibernate7: HibernateGormValidationApi bug fix
     new a33dcf010d hibernate7: - Fix alias resolution architecture: - Fix scroll(): - Fix countDistinct/groupProperty - Add eq(Map, String, Object) overload for Groovy named-params form,
     new 45f49cb9f5 hibernate7: PMD fixes
     new 3b830d07d0 hibernate7: raw fixes
     new cd5579f94b hibernate7: added cache and readOnly support to CriteriaMethodInvoker
     new 91b95a39da hibernate7: added lock and fetchMode support to CriteriaMethodInvoker

The 34 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 BRANCHES.md                                        | 237 +++++++++
 gradle/code-style-config.gradle                    |   8 +-
 grails-data-hibernate7/core/COVERAGE.md            | 255 ++++++++++
 grails-data-hibernate7/core/build.gradle           |   1 +
 .../{orm => gorm}/hibernate/HibernateEntity.groovy |  31 +-
 .../hibernate/annotation/ManagedEntity.java        |   0
 .../hibernate/mapping/MappingBuilder.groovy        |   2 +-
 .../groovy/grails/orm/CriteriaMethodInvoker.java   | 545 +++++++++++----------
 .../main/groovy/grails/orm/CriteriaMethods.java    |   6 +-
 .../grails/orm/HibernateCriteriaBuilder.java       | 281 ++++++-----
 .../CloseSuppressingInvocationHandler.java         |  79 +++
 .../orm/hibernate/GrailsHibernateTemplate.java     | 140 ++----
 .../GrailsHibernateTransactionManager.groovy       |  24 +-
 .../grails/orm/hibernate/GrailsSessionContext.java |   9 +-
 .../grails/orm/hibernate/HibernateDatastore.java   |  27 +-
 .../orm/hibernate/HibernateGormEnhancer.groovy     |   1 +
 .../orm/hibernate/HibernateGormInstanceApi.groovy  | 207 +++-----
 .../orm/hibernate/HibernateGormStaticApi.groovy    | 347 +++++--------
 .../hibernate/HibernateGormValidationApi.groovy    |  18 +-
 .../org/grails/orm/hibernate/HibernateSession.java |  35 +-
 .../grails/orm/hibernate/cfg/CacheConfig.groovy    |   7 +-
 .../grails/orm/hibernate/cfg/ColumnConfig.groovy   |   1 +
 .../orm/hibernate/cfg/CompositeIdentity.groovy     |   1 +
 .../orm/hibernate/cfg/DiscriminatorConfig.groovy   |   1 +
 .../orm/hibernate/cfg/GrailsHibernateUtil.java     |  16 +-
 .../cfg/HibernateMappingContextConfiguration.java  |  38 +-
 .../org/grails/orm/hibernate/cfg/Identity.groovy   |   1 +
 .../grails/orm/hibernate/cfg/IdentityEnumType.java |  19 +-
 .../grails/orm/hibernate/cfg/InstanceProxy.groovy  |   5 +-
 .../org/grails/orm/hibernate/cfg/JoinTable.groovy  |   1 +
 .../org/grails/orm/hibernate/cfg/Mapping.groovy    |  97 ++--
 .../org/grails/orm/hibernate/cfg/NaturalId.groovy  |   2 +-
 .../grails/orm/hibernate/cfg/PropertyConfig.groovy |  82 ++--
 .../cfg/PropertyDefinitionDelegate.groovy          |  23 +-
 .../org/grails/orm/hibernate/cfg/SortConfig.groovy |   1 +
 .../org/grails/orm/hibernate/cfg/Table.groovy      |   1 +
 .../generator/GrailsSequenceGeneratorEnum.groovy   |  25 +-
 .../hibernate/HibernateAssociation.java            |   4 +
 .../hibernate/HibernateManyToOneProperty.java      |   5 +
 .../hibernate/HibernateMappingBuilder.groovy       |  36 +-
 .../hibernate/HibernateMappingKeyword.groovy       |  76 +++
 .../hibernate/HibernateOneToManyProperty.java      |   4 +
 .../secondpass/ListSecondPassBinder.java           |  12 +-
 .../compiler/HibernateEntityTransformation.groovy  |  98 ++--
 .../HibernateConnectionSourceSettings.groovy       |  56 +--
 ...HibernateConnectionSourceSettingsBuilder.groovy |  17 +-
 .../dirty/GrailsEntityDirtinessStrategy.groovy     |   8 +-
 .../hibernate/query/GrailsHibernateQueryUtils.java | 369 --------------
 .../orm/hibernate/query/HibernateHqlQuery.java     | 112 ++++-
 .../grails/orm/hibernate/query/HibernateQuery.java |  97 ++--
 .../orm/hibernate/query/HqlListQueryBuilder.java   | 154 ++++++
 .../orm/hibernate/query/HqlQueryContext.java       |  67 ++-
 .../orm/hibernate/query/HqlQueryDelegate.java      |   2 +
 .../hibernate/query/JpaCriteriaQueryCreator.java   |   9 +-
 .../orm/hibernate/query/PagedResultList.java       |  67 ++-
 .../orm/hibernate/query/PredicateGenerator.java    |  15 +
 .../orm/hibernate/query/SelectQueryDelegate.java   |   6 +
 .../hibernate/support/DataSourceFactoryBean.groovy |  42 --
 ...rnateDatastoreConnectionSourcesRegistrar.groovy |   9 +-
 .../support/HibernateDatastoreFactoryBean.groovy   |  62 ---
 .../HibernateDialectDetectorFactoryBean.java       | 204 --------
 .../hibernate/support/HibernateRuntimeUtils.groovy |  95 ++--
 .../mapping/HibernateMappingBuilderTests.groovy    |  31 +-
 .../JpaCriteriaQueryCreatorSpec.groovy             |  19 +-
 .../hibernatequery/PredicateGeneratorSpec.groovy   |  23 +-
 .../sessioncontext/GrailsSessionContextSpec.groovy | 126 ++++-
 .../grails/orm/CriteriaMethodInvokerSpec.groovy    |  73 +--
 .../orm/HibernateCriteriaBuilderDirectSpec.groovy  |  50 ++
 .../grails/orm/HibernateCriteriaBuilderSpec.groovy |  51 ++
 .../CloseSuppressingInvocationHandlerSpec.groovy   |  93 ++++
 .../hibernate/HibernateGormInstanceApiSpec.groovy  | 309 ++++--------
 .../HibernateGormValidationApiSpec.groovy          | 121 +++++
 .../orm/hibernate/InstanceApiHelperSpec.groovy     |  71 +++
 .../hibernate/cfg/GrailsHibernateUtilSpec.groovy   | 114 +++++
 .../HibernateManyToOnePropertySpec.groovy}         |  59 +--
 .../HibernateOneToManyPropertySpec.groovy}         |  58 +--
 .../secondpass/ListSecondPassBinderSpec.groovy     | 100 +++-
 .../secondpass/MapSecondPassBinderSpec.groovy      | 120 ++++-
 .../HibernateConnectionSourceSettingsSpec.groovy   |   2 +-
 .../query/GrailsHibernateQueryUtilsSpec.groovy     |  20 +-
 .../hibernate/query/HibernateHqlQuerySpec.groovy   |  30 +-
 .../orm/hibernate/query/HqlQueryContextSpec.groovy |  51 +-
 ...eDatastoreConnectionSourcesRegistrarSpec.groovy |  76 +++
 .../mapping/query/api/BuildableCriteria.java       |  10 +-
 .../datastore/mapping/query/api/Criteria.java      |  24 +-
 .../src/en/ref/Domain Classes/createCriteria.adoc  |   6 +-
 86 files changed, 3416 insertions(+), 2421 deletions(-)
 create mode 100644 BRANCHES.md
 create mode 100644 grails-data-hibernate7/core/COVERAGE.md
 rename grails-data-hibernate7/core/src/main/groovy/grails/{orm => gorm}/hibernate/HibernateEntity.groovy (70%)
 rename grails-data-hibernate7/core/src/main/groovy/grails/{orm => gorm}/hibernate/annotation/ManagedEntity.java (100%)
 rename grails-data-hibernate7/core/src/main/groovy/grails/{orm => gorm}/hibernate/mapping/MappingBuilder.groovy (97%)
 create mode 100644 grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/CloseSuppressingInvocationHandler.java
 create mode 100644 grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateMappingKeyword.groovy
 delete mode 100644 grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/GrailsHibernateQueryUtils.java
 create mode 100644 grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HqlListQueryBuilder.java
 delete mode 100644 grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/support/DataSourceFactoryBean.groovy
 delete mode 100644 grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/support/HibernateDatastoreFactoryBean.groovy
 delete mode 100644 grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/support/HibernateDialectDetectorFactoryBean.java
 create mode 100644 grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/CloseSuppressingInvocationHandlerSpec.groovy
 create mode 100644 grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/HibernateGormValidationApiSpec.groovy
 create mode 100644 grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/InstanceApiHelperSpec.groovy
 create mode 100644 grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/GrailsHibernateUtilSpec.groovy
 copy grails-data-hibernate7/core/src/test/groovy/{grails/gorm/specs/validation/UniqueWithHasOneSpec.groovy => org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateManyToOnePropertySpec.groovy} (53%)
 copy grails-data-hibernate7/core/src/test/groovy/{grails/gorm/specs/validation/UniqueWithHasOneSpec.groovy => org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateOneToManyPropertySpec.groovy} (53%)
 copy grails-datastore-core/src/test/groovy/org/grails/datastore/mapping/reflect/NameUtilsSpec.groovy => grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/query/GrailsHibernateQueryUtilsSpec.groovy (58%)
 create mode 100644 grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/support/HibernateDatastoreConnectionSourcesRegistrarSpec.groovy


(grails-core) 10/34: hibernate7: cleanup update GrailsHibernateQueryUtils

Posted by bo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

borinquenkid pushed a commit to branch 8.0.x-hibernate7-dev
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit f25e8b8716ce1dcd3183abf3a712df5e05e5a38e
Author: Walter Duque de Estrada <wb...@mac.com>
AuthorDate: Fri Mar 6 06:45:19 2026 -0600

    hibernate7: cleanup update GrailsHibernateQueryUtils
---
 .../orm/hibernate/HibernateGormStaticApi.groovy    |   8 +-
 .../hibernate/query/GrailsHibernateQueryUtils.java | 139 +++++++++++----------
 .../query/GrailsHibernateQueryUtilsSpec.groovy     | 117 +++++++++++++++++
 3 files changed, 192 insertions(+), 72 deletions(-)

diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy
index e4b923d5e0..d37bba3881 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy
@@ -482,8 +482,8 @@ class HibernateGormStaticApi<D> extends GormStaticApi<D> {
                     criteriaQuery,
                     queryRoot,
                     criteriaBuilder,
-                    params,
-                    datastore.mappingContext.conversionService,
+                    params
+                    ,
                     true
             )
             Query query = session.createQuery(criteriaQuery)
@@ -492,8 +492,8 @@ class HibernateGormStaticApi<D> extends GormStaticApi<D> {
                     persistentEntity,
                     query,
                     params,
-                    datastore.mappingContext.conversionService,
-                    true
+                    datastore.mappingContext.conversionService
+
             )
 
             HibernateHqlQuery hibernateQuery = new HibernateHqlQuery(
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/GrailsHibernateQueryUtils.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/GrailsHibernateQueryUtils.java
index 0cc2f785e8..2e89a017e1 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/GrailsHibernateQueryUtils.java
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/GrailsHibernateQueryUtils.java
@@ -53,22 +53,19 @@ public class GrailsHibernateQueryUtils {
   /**
    * Populates criteria arguments for the given target class and arguments map
    *
-   * @param entity The {@link org.grails.datastore.mapping.model.PersistentEntity} instance
-   * @param query The criteria instance
+   * @param entity The {@link PersistentEntity} instance
+   * @param query  The criteria instance
    * @param argMap The arguments map
    */
-  @SuppressWarnings("rawtypes")
   public static void populateArgumentsForCriteria(
       PersistentEntity entity,
-      CriteriaQuery query,
-      Root queryRoot,
+      CriteriaQuery<?> query,
+      Root<?> queryRoot,
       CriteriaBuilder criteriaBuilder,
-      Map argMap,
-      ConversionService conversionService,
+      Map<String, Object> argMap,
       boolean useDefaultMapping) {
     Object fetchObj = argMap.get(HibernateQueryArgument.FETCH.value());
-    if (fetchObj instanceof Map) {
-      Map fetch = (Map) fetchObj;
+    if (fetchObj instanceof Map<?, ?> fetch) {
       for (Object o : fetch.keySet()) {
         String associationName = (String) o;
 
@@ -83,8 +80,7 @@ public class GrailsHibernateQueryUtils {
     if (sortObj != null) {
       final boolean ignoreCase =
           !(argMap.get(HibernateQueryArgument.IGNORE_CASE.value()) instanceof Boolean b) || b;
-      if (sortObj instanceof Map) {
-        Map sortMap = (Map) sortObj;
+      if (sortObj instanceof Map<?, ?> sortMap) {
         for (Object sort : sortMap.keySet()) {
           final String order =
               HibernateQueryArgument.ORDER_DESC.value().equalsIgnoreCase((String) sortMap.get(sort))
@@ -106,14 +102,15 @@ public class GrailsHibernateQueryUtils {
       Class<?> theClass = entity.getJavaClass();
       Mapping m = MappingCacheHolder.getInstance().getMapping(theClass);
       if (m != null) {
-        Map sortMap = m.getSort().getNamesAndDirections();
-        for (Object sort : sortMap.keySet()) {
+        Map<String, String> sortMap = m.getSort().getNamesAndDirections();
+        for (Map.Entry<String, String> entry : sortMap.entrySet()) {
+          String sort = entry.getKey();
           final String order =
-              HibernateQueryArgument.ORDER_DESC.value().equalsIgnoreCase((String) sortMap.get(sort))
+              HibernateQueryArgument.ORDER_DESC.value().equalsIgnoreCase(entry.getValue())
                   ? HibernateQueryArgument.ORDER_DESC.value()
                   : HibernateQueryArgument.ORDER_ASC.value();
           addOrderPossiblyNested(
-              query, queryRoot, criteriaBuilder, entity, (String) sort, order, true);
+              query, queryRoot, criteriaBuilder, entity, sort, order, true);
         }
       }
     }
@@ -122,17 +119,15 @@ public class GrailsHibernateQueryUtils {
   /**
    * Populates criteria arguments for the given target class and arguments map
    *
-   * @param entity The {@link org.grails.datastore.mapping.model.PersistentEntity} instance
-   * @param query The criteria instance
+   * @param entity The {@link PersistentEntity} instance
+   * @param query  The criteria instance
    * @param argMap The arguments map
    */
-  @SuppressWarnings("rawtypes")
   public static void populateArgumentsForCriteria(
       PersistentEntity entity,
-      Query query,
-      Map argMap,
-      ConversionService conversionService,
-      boolean useDefaultMapping) {
+      Query<?> query,
+      Map<String, Object> argMap,
+      ConversionService conversionService) {
     final Integer maxParam =
         argMap.containsKey(HibernateQueryArgument.MAX.value())
             ? conversionService.convert(argMap.get(HibernateQueryArgument.MAX.value()), Integer.class)
@@ -142,12 +137,16 @@ public class GrailsHibernateQueryUtils {
             ? conversionService.convert(argMap.get(HibernateQueryArgument.OFFSET.value()), Integer.class)
             : null;
     if (argMap.containsKey(HibernateQueryArgument.FETCH_SIZE.value())) {
-      query.setFetchSize(
-          conversionService.convert(argMap.get(HibernateQueryArgument.FETCH_SIZE.value()), Integer.class));
+      Integer fetchSize = conversionService.convert(argMap.get(HibernateQueryArgument.FETCH_SIZE.value()), Integer.class);
+      if (fetchSize != null) {
+        query.setFetchSize(fetchSize);
+      }
     }
     if (argMap.containsKey(HibernateQueryArgument.TIMEOUT.value())) {
-      query.setTimeout(
-          conversionService.convert(argMap.get(HibernateQueryArgument.TIMEOUT.value()), Integer.class));
+      Integer timeout = conversionService.convert(argMap.get(HibernateQueryArgument.TIMEOUT.value()), Integer.class);
+      if (timeout != null) {
+        query.setTimeout(timeout);
+      }
     }
     if (argMap.containsKey(HibernateQueryArgument.FLUSH_MODE.value())) {
       query.setQueryFlushMode(convertQueryFlushMode(argMap.get(HibernateQueryArgument.FLUSH_MODE.value())));
@@ -181,8 +180,8 @@ public class GrailsHibernateQueryUtils {
    * sort:'nested.property').
    */
   protected static void addOrderPossiblyNested(
-      CriteriaQuery query,
-      From queryRoot,
+      CriteriaQuery<?> query,
+      From<?, ?> queryRoot,
       CriteriaBuilder criteriaBuilder,
       PersistentEntity entity,
       String sort,
@@ -190,26 +189,27 @@ public class GrailsHibernateQueryUtils {
       boolean ignoreCase) {
     int firstDotPos = sort.indexOf(".");
     if (firstDotPos == -1) {
-      final PersistentProperty<? extends Property> property = entity.getPropertyByName(sort);
+      final PersistentProperty<? extends Property> property =
+          (PersistentProperty<? extends Property>) entity.getPropertyByName(sort);
       ignoreCase = isIgnoreCaseProperty(ignoreCase, property);
       addOrder(entity, query, queryRoot, criteriaBuilder, sort, order, ignoreCase);
     } else { // nested property
       String sortHead = sort.substring(0, firstDotPos);
       String sortTail = sort.substring(firstDotPos + 1);
-      final PersistentProperty<? extends Property> property = entity.getPropertyByName(sortHead);
+      final PersistentProperty<? extends Property> property =
+          (PersistentProperty<? extends Property>) entity.getPropertyByName(sortHead);
       if (property instanceof Embedded) {
         // embedded objects cannot reference entities (at time of writing), so no more recursion
         // needed
         final PersistentProperty<? extends Property> associatedProperty =
-            ((Embedded<?>) property).getAssociatedEntity().getPropertyByName(sortTail);
+            (PersistentProperty<? extends Property>)
+                ((Embedded<?>) property).getAssociatedEntity().getPropertyByName(sortTail);
         ignoreCase = isIgnoreCaseProperty(ignoreCase, associatedProperty);
         addOrder(entity, query, queryRoot, criteriaBuilder, sort, order, ignoreCase);
-      } else if (property instanceof Association) {
-        final Association<? extends Property> a = (Association<? extends Property>) property;
-        final Join join = queryRoot.join(sortHead);
+      } else if (property instanceof Association<? extends Property> a) {
+          final Join join = queryRoot.join(sortHead);
         PersistentEntity associatedEntity = a.getAssociatedEntity();
-        Class<?> propertyTargetClass = associatedEntity.getJavaClass();
-        addOrderPossiblyNested(
+          addOrderPossiblyNested(
             query,
             join,
             criteriaBuilder,
@@ -232,8 +232,8 @@ public class GrailsHibernateQueryUtils {
   /** Add order directly to criteria. */
   protected static void addOrder(
       PersistentEntity entity,
-      CriteriaQuery query,
-      From queryRoot,
+      CriteriaQuery<?> query,
+      From<?, ?> queryRoot,
       CriteriaBuilder criteriaBuilder,
       String sort,
       String order,
@@ -247,37 +247,40 @@ public class GrailsHibernateQueryUtils {
 
     if (compositeIdSortOptional.isPresent()) {
       Comparator<Order> orderComparator =
-          new Comparator<Order>() {
-            @Override
-            public int compare(Order o1, Order o2) {
-              String name1 = getOrderName(o1);
-              String name2 = getOrderName(o2);
+              new Comparator<>() {
+                  @Override
+                  public int compare(Order o1, Order o2) {
+                      String name1 = getOrderName(o1);
+                      String name2 = getOrderName(o2);
 
-              boolean name1IsSort = name1.equalsIgnoreCase(sort);
-              boolean name2IsSort = name2.equalsIgnoreCase(sort);
+                      boolean name1IsSort = name1.equalsIgnoreCase(sort);
+                      boolean name2IsSort = name2.equalsIgnoreCase(sort);
 
-              if (name1IsSort && !name2IsSort) {
-                return -1; // o1 (the sort property) comes first
-              }
-              if (!name1IsSort && name2IsSort) {
-                return 1; // o2 (the sort property) comes first
-              }
-              return 0; // Maintain original order for other properties
-            }
+                      if (name1IsSort && !name2IsSort) {
+                          return -1; // o1 (the sort property) comes first
+                      }
+                      if (!name1IsSort && name2IsSort) {
+                          return 1; // o2 (the sort property) comes first
+                      }
+                      return 0; // Maintain original order for other properties
+                  }
 
-            private static String getOrderName(Order o1) {
-              return ((SqmBasicValuedSimplePath)
-                      ((SqmFunction) o1.getExpression()).getArguments().get(0))
-                  .getNavigablePath()
-                  .getLocalName();
-            }
-          };
+                  private static String getOrderName(Order o1) {
+                      return ((SqmBasicValuedSimplePath<?>)
+                              ((SqmFunction<?>) o1.getExpression()).getArguments().get(0))
+                              .getNavigablePath()
+                              .getLocalName();
+                  }
+              };
       Order[] orders =
           Arrays.stream(entity.getCompositeIdentity())
               .map(PersistentProperty::getName)
               .map(
                   name ->
-                      ignoreCase ? criteriaBuilder.upper(queryRoot.get(name)) : queryRoot.get(name))
+                  {
+                    Path x = queryRoot.get(name);
+                    return ignoreCase ? criteriaBuilder.upper(x) : queryRoot.get(name);
+                  })
               .map(
                   path ->
                       HibernateQueryArgument.ORDER_DESC.value().equals(order)
@@ -289,10 +292,10 @@ public class GrailsHibernateQueryUtils {
 
     } else if (entity.getIdentity() != null
         && sort.equalsIgnoreCase(entity.getIdentity().getName())) {
-      Expression path = queryRoot;
+      Expression<?> path = queryRoot;
 
       if (ignoreCase) {
-        path = criteriaBuilder.upper(path);
+        path = criteriaBuilder.upper((Expression<String>) path);
       }
       if (HibernateQueryArgument.ORDER_DESC.value().equals(order)) {
         query.orderBy(criteriaBuilder.desc(path));
@@ -300,10 +303,10 @@ public class GrailsHibernateQueryUtils {
         query.orderBy(criteriaBuilder.asc(path));
       }
     } else {
-      Expression path = queryRoot.get(sort);
+      Expression<?> path = queryRoot.get(sort);
 
       if (ignoreCase) {
-        path = criteriaBuilder.upper(path);
+        path = criteriaBuilder.upper((Expression<String>) path);
       }
       if (HibernateQueryArgument.ORDER_DESC.value().equals(order)) {
         query.orderBy(criteriaBuilder.desc(path));
@@ -319,7 +322,7 @@ public class GrailsHibernateQueryUtils {
    * @param targetClass The target class
    * @param criteria The criteria
    */
-  protected static void cacheCriteriaByMapping(Class<?> targetClass, Query criteria) {
+  protected static void cacheCriteriaByMapping(Class<?> targetClass, Query<?> criteria) {
     Mapping m = MappingCacheHolder.getInstance().getMapping(targetClass);
     if (m != null && m.getCache() != null && m.getCache().getEnabled()) {
       criteria.setCacheable(true);
@@ -330,8 +333,8 @@ public class GrailsHibernateQueryUtils {
     if (object == null) {
       return null;
     }
-    if (object instanceof FlushMode) {
-      return (FlushMode) object;
+    if (object instanceof FlushMode flushMode) {
+      return flushMode;
     }
     try {
       return FlushMode.valueOf(object.toString());
diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/query/GrailsHibernateQueryUtilsSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/query/GrailsHibernateQueryUtilsSpec.groovy
new file mode 100644
index 0000000000..4dc55d1cd1
--- /dev/null
+++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/query/GrailsHibernateQueryUtilsSpec.groovy
@@ -0,0 +1,117 @@
+/*
+ *  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.orm.hibernate.query
+
+import org.grails.datastore.mapping.model.PersistentEntity
+import org.hibernate.FetchMode
+import org.hibernate.query.Query
+import org.hibernate.query.QueryFlushMode
+import org.springframework.core.convert.ConversionService
+import spock.lang.Specification
+import spock.lang.Unroll
+
+class GrailsHibernateQueryUtilsSpec extends Specification {
+
+    @Unroll
+    def "test convertQueryFlushMode for #input"() {
+        expect:
+        GrailsHibernateQueryUtils.convertQueryFlushMode(input) == expected
+
+        where:
+        input               | expected
+        "ALWAYS"            | QueryFlushMode.FLUSH
+        "MANUAL"            | QueryFlushMode.NO_FLUSH
+        "COMMIT"            | QueryFlushMode.NO_FLUSH
+        "AUTO"              | QueryFlushMode.DEFAULT
+        null                | QueryFlushMode.DEFAULT
+        "INVALID"           | QueryFlushMode.NO_FLUSH // defaults to COMMIT which is NO_FLUSH
+    }
+
+    @Unroll
+    def "test getFetchMode for #input"() {
+        expect:
+        GrailsHibernateQueryUtils.getFetchMode(input) == expected
+
+        where:
+        input               | expected
+        "JOIN"              | FetchMode.JOIN
+        "eager"             | FetchMode.JOIN
+        "SELECT"            | FetchMode.SELECT
+        "lazy"              | FetchMode.SELECT
+        "default"           | FetchMode.DEFAULT
+        null                | FetchMode.DEFAULT
+    }
+
+    def "test populateArgumentsForCriteria for Query"() {
+        given:
+        PersistentEntity entity = Mock(PersistentEntity)
+        Query query = Mock(Query)
+        ConversionService conversionService = Mock(ConversionService)
+        
+        Map argMap = [
+            max: 10,
+            offset: 20,
+            fetchSize: 50,
+            timeout: 30,
+            readOnly: true,
+            cache: true
+        ]
+
+        entity.getJavaClass() >> Object.class
+        conversionService.convert(10, Integer.class) >> 10
+        conversionService.convert(20, Integer.class) >> 20
+        conversionService.convert(50, Integer.class) >> 50
+        conversionService.convert(30, Integer.class) >> 30
+
+        when:
+        GrailsHibernateQueryUtils.populateArgumentsForCriteria(entity, query, argMap, conversionService)
+
+        then:
+        1 * query.setMaxResults(10)
+        1 * query.setFirstResult(20)
+        1 * query.setFetchSize(50)
+        1 * query.setTimeout(30)
+        1 * query.setReadOnly(true)
+        1 * query.setCacheable(true)
+    }
+
+    def "test populateArgumentsForCriteria for Query with null conversion results"() {
+        given:
+        PersistentEntity entity = Mock(PersistentEntity)
+        Query query = Mock(Query)
+        ConversionService conversionService = Mock(ConversionService)
+        
+        Map argMap = [
+            fetchSize: 50,
+            timeout: 30
+        ]
+
+        entity.getJavaClass() >> Object.class
+        // Simulate conversion returning null
+        conversionService.convert(50, Integer.class) >> null
+        conversionService.convert(30, Integer.class) >> null
+
+        when:
+        GrailsHibernateQueryUtils.populateArgumentsForCriteria(entity, query, argMap, conversionService)
+
+        then:
+        0 * query.setFetchSize(_)
+        0 * query.setTimeout(_)
+    }
+}


(grails-core) 04/34: hibernate7: spec for HibernateDatastoreConnectionSourcesRegistrar

Posted by bo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

borinquenkid pushed a commit to branch 8.0.x-hibernate7-dev
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit 52e55831a008702ed33335cb52a9e64159ce5c77
Author: Walter Duque de Estrada <wb...@mac.com>
AuthorDate: Thu Mar 5 16:40:49 2026 -0600

    hibernate7: spec for HibernateDatastoreConnectionSourcesRegistrar
---
 ...eDatastoreConnectionSourcesRegistrarSpec.groovy | 76 ++++++++++++++++++++++
 1 file changed, 76 insertions(+)

diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/support/HibernateDatastoreConnectionSourcesRegistrarSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/support/HibernateDatastoreConnectionSourcesRegistrarSpec.groovy
new file mode 100644
index 0000000000..d5e7debc1b
--- /dev/null
+++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/support/HibernateDatastoreConnectionSourcesRegistrarSpec.groovy
@@ -0,0 +1,76 @@
+/*
+ *  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.orm.hibernate.support
+
+import grails.gorm.specs.HibernateGormDatastoreSpec
+import org.grails.datastore.gorm.bootstrap.support.InstanceFactoryBean
+import org.grails.datastore.mapping.config.Settings
+import org.grails.datastore.mapping.core.connections.ConnectionSource
+import org.hibernate.SessionFactory
+import org.springframework.beans.factory.support.DefaultListableBeanFactory
+import org.springframework.transaction.PlatformTransactionManager
+
+import javax.sql.DataSource
+
+class HibernateDatastoreConnectionSourcesRegistrarSpec extends HibernateGormDatastoreSpec {
+
+    def "test postProcessBeanDefinitionRegistry registers expected beans"() {
+        given:
+        def registry = new DefaultListableBeanFactory()
+        def dataSourceNames = [Settings.SETTING_DATASOURCE, 'readOnly']
+        def registrar = new HibernateDatastoreConnectionSourcesRegistrar(dataSourceNames)
+
+        when:
+        registrar.postProcessBeanDefinitionRegistry(registry)
+
+        then:
+        // Default dataSource bean
+        registry.containsBeanDefinition(Settings.SETTING_DATASOURCE)
+        def defaultDs = registry.getBeanDefinition(Settings.SETTING_DATASOURCE)
+        defaultDs.beanClass == InstanceFactoryBean
+        defaultDs.targetType == DataSource
+        defaultDs.constructorArgumentValues.genericArgumentValues[0].value == "#{dataSourceConnectionSourceFactory.create('dataSource', environment).source}"
+
+        // Secondary dataSource bean
+        registry.containsBeanDefinition("${Settings.SETTING_DATASOURCE}_readOnly")
+        def readOnlyDs = registry.getBeanDefinition("${Settings.SETTING_DATASOURCE}_readOnly")
+        readOnlyDs.beanClass == InstanceFactoryBean
+        readOnlyDs.targetType == DataSource
+        readOnlyDs.constructorArgumentValues.genericArgumentValues[0].value == "#{dataSourceConnectionSourceFactory.create('readOnly', environment).source}"
+
+        // Secondary sessionFactory bean
+        registry.containsBeanDefinition("sessionFactory_readOnly")
+        def readOnlySf = registry.getBeanDefinition("sessionFactory_readOnly")
+        readOnlySf.beanClass == InstanceFactoryBean
+        readOnlySf.targetType == SessionFactory
+        readOnlySf.constructorArgumentValues.genericArgumentValues[0].value == "#{hibernateDatastore.getDatastoreForConnection('readOnly').sessionFactory}"
+
+        // Secondary transactionManager bean
+        registry.containsBeanDefinition("transactionManager_readOnly")
+        def readOnlyTm = registry.getBeanDefinition("transactionManager_readOnly")
+        readOnlyTm.beanClass == InstanceFactoryBean
+        readOnlyTm.targetType == PlatformTransactionManager
+        readOnlyTm.constructorArgumentValues.genericArgumentValues[0].value == "#{hibernateDatastore.getDatastoreForConnection('readOnly').transactionManager}"
+
+        // Default sessionFactory and transactionManager should NOT be registered by this registrar
+        // (they are usually registered elsewhere for the default connection)
+        !registry.containsBeanDefinition("sessionFactory_dataSource")
+        !registry.containsBeanDefinition("transactionManager_dataSource")
+    }
+}


(grails-core) 26/34: hibernate7: more CodeNarc

Posted by bo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

borinquenkid pushed a commit to branch 8.0.x-hibernate7-dev
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit ad31671b7b8228806da80010a89b8f0a98b8e240
Author: Walter Duque de Estrada <wb...@mac.com>
AuthorDate: Sat Mar 7 18:47:21 2026 -0600

    hibernate7: more CodeNarc
---
 .../grails/gorm/hibernate/HibernateEntity.groovy   | 29 ++++++++++++----------
 .../GrailsHibernateTransactionManager.groovy       | 24 +++---------------
 .../generator/GrailsSequenceGeneratorEnum.groovy   | 25 ++++++++++---------
 .../dirty/GrailsEntityDirtinessStrategy.groovy     |  8 +++---
 .../HibernateConnectionSourceSettingsSpec.groovy   |  2 +-
 5 files changed, 37 insertions(+), 51 deletions(-)

diff --git a/grails-data-hibernate7/core/src/main/groovy/grails/gorm/hibernate/HibernateEntity.groovy b/grails-data-hibernate7/core/src/main/groovy/grails/gorm/hibernate/HibernateEntity.groovy
index 76dc35c1ed..59864c3d12 100644
--- a/grails-data-hibernate7/core/src/main/groovy/grails/gorm/hibernate/HibernateEntity.groovy
+++ b/grails-data-hibernate7/core/src/main/groovy/grails/gorm/hibernate/HibernateEntity.groovy
@@ -24,7 +24,8 @@ trait HibernateEntity<D> extends GormEntity<D> {
      */
     @Generated
     static List<D> findAllWithNativeSql(CharSequence sql) {
-        HibernateEntity.currentHibernateStaticApi().findAllWithNativeSql sql, Collections.emptyMap()
+        HibernateGormStaticApi<D> api = (HibernateGormStaticApi<D>) GormEnhancer.findStaticApi(this)
+        return (List<D>) api.findAllWithNativeSql(sql, Collections.emptyMap())
     }
 
     /**
@@ -36,7 +37,8 @@ trait HibernateEntity<D> extends GormEntity<D> {
      */
     @Generated
     static D findWithNativeSql(CharSequence sql) {
-        HibernateEntity.currentHibernateStaticApi().findWithNativeSql(sql, Collections.emptyMap())
+        HibernateGormStaticApi<D> api = (HibernateGormStaticApi<D>) GormEnhancer.findStaticApi(this)
+        return (D) api.findWithNativeSql(sql, Collections.emptyMap())
     }
 
     /**
@@ -49,7 +51,8 @@ trait HibernateEntity<D> extends GormEntity<D> {
      */
     @Generated
     static List<D> findAllWithNativeSql(CharSequence sql, Map args) {
-        HibernateEntity.currentHibernateStaticApi().findAllWithNativeSql sql, args
+        HibernateGormStaticApi<D> api = (HibernateGormStaticApi<D>) GormEnhancer.findStaticApi(this)
+        return (List<D>) api.findAllWithNativeSql(sql, args)
     }
 
     /**
@@ -62,7 +65,8 @@ trait HibernateEntity<D> extends GormEntity<D> {
      */
     @Generated
     static D findWithNativeSql(CharSequence sql, Map args) {
-        HibernateEntity.currentHibernateStaticApi().findWithNativeSql(sql, args)
+        HibernateGormStaticApi<D> api = (HibernateGormStaticApi<D>) GormEnhancer.findStaticApi(this)
+        return (D) api.findWithNativeSql(sql, args)
     }
 
     /**
@@ -71,7 +75,8 @@ trait HibernateEntity<D> extends GormEntity<D> {
     @Deprecated
     @Generated
     static List<D> findAllWithSql(CharSequence sql) {
-        HibernateEntity.currentHibernateStaticApi().findAllWithNativeSql sql, Collections.emptyMap()
+        HibernateGormStaticApi<D> api = (HibernateGormStaticApi<D>) GormEnhancer.findStaticApi(this)
+        return (List<D>) api.findAllWithNativeSql(sql, Collections.emptyMap())
     }
 
     /**
@@ -80,7 +85,8 @@ trait HibernateEntity<D> extends GormEntity<D> {
     @Deprecated
     @Generated
     static D findWithSql(CharSequence sql) {
-        HibernateEntity.currentHibernateStaticApi().findWithNativeSql(sql, Collections.emptyMap())
+        HibernateGormStaticApi<D> api = (HibernateGormStaticApi<D>) GormEnhancer.findStaticApi(this)
+        return (D) api.findWithNativeSql(sql, Collections.emptyMap())
     }
 
     /**
@@ -89,7 +95,8 @@ trait HibernateEntity<D> extends GormEntity<D> {
     @Deprecated
     @Generated
     static List<D> findAllWithSql(CharSequence sql, Map args) {
-        HibernateEntity.currentHibernateStaticApi().findAllWithNativeSql sql, args
+        HibernateGormStaticApi<D> api = (HibernateGormStaticApi<D>) GormEnhancer.findStaticApi(this)
+        return (List<D>) api.findAllWithNativeSql(sql, args)
     }
 
     /**
@@ -98,11 +105,7 @@ trait HibernateEntity<D> extends GormEntity<D> {
     @Deprecated
     @Generated
     static D findWithSql(CharSequence sql, Map args) {
-        HibernateEntity.currentHibernateStaticApi().findWithNativeSql(sql, args)
-    }
-
-    @Generated
-    private static HibernateGormStaticApi currentHibernateStaticApi() {
-        (HibernateGormStaticApi) GormEnhancer.findStaticApi(this)
+        HibernateGormStaticApi<D> api = (HibernateGormStaticApi<D>) GormEnhancer.findStaticApi(this)
+        return (D) api.findWithNativeSql(sql, args)
     }
 }
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/GrailsHibernateTransactionManager.groovy b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/GrailsHibernateTransactionManager.groovy
index 17b9b5aa1c..f0575c24cf 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/GrailsHibernateTransactionManager.groovy
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/GrailsHibernateTransactionManager.groovy
@@ -18,16 +18,11 @@ package org.grails.orm.hibernate
 import groovy.transform.CompileStatic
 import groovy.util.logging.Slf4j
 import org.hibernate.FlushMode
-import org.hibernate.Session
 import org.hibernate.SessionFactory
-import org.hibernate.engine.jdbc.spi.JdbcCoordinator
-import org.hibernate.engine.spi.SessionImplementor
 import org.springframework.orm.hibernate5.HibernateTransactionManager
 import org.springframework.orm.hibernate5.SessionHolder
 import org.springframework.transaction.TransactionDefinition
-import org.springframework.transaction.support.DefaultTransactionStatus
 import org.springframework.transaction.support.TransactionSynchronizationManager
-import org.springframework.util.Assert
 
 import javax.sql.DataSource
 
@@ -42,15 +37,6 @@ class GrailsHibernateTransactionManager extends HibernateTransactionManager {
 
     final FlushMode defaultFlushMode
 
-    GrailsHibernateTransactionManager(FlushMode defaultFlushMode = FlushMode.AUTO) {
-        this.defaultFlushMode = defaultFlushMode
-    }
-
-    GrailsHibernateTransactionManager(SessionFactory sessionFactory, FlushMode defaultFlushMode = FlushMode.AUTO) {
-        super(sessionFactory)
-        this.defaultFlushMode = defaultFlushMode
-    }
-
     GrailsHibernateTransactionManager(SessionFactory sessionFactory, DataSource dataSource, FlushMode defaultFlushMode = FlushMode.AUTO) {
         super(sessionFactory)
         setDataSource(dataSource)
@@ -65,16 +51,12 @@ class GrailsHibernateTransactionManager extends HibernateTransactionManager {
             // transaction is HibernateTransactionManager.HibernateTransactionObject private class instance
             // always set to manual; the base class doesn't because the OSIV has already registered a session
 
-            SessionHolder holder = (SessionHolder)TransactionSynchronizationManager.getResource(sessionFactory)
+            SessionHolder holder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory)
             holder.session.setHibernateFlushMode(FlushMode.MANUAL)
         }
-        else if(defaultFlushMode != FlushMode.AUTO) {
-            SessionHolder holder = (SessionHolder)TransactionSynchronizationManager.getResource(sessionFactory)
+        else if (defaultFlushMode != FlushMode.AUTO) {
+            SessionHolder holder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory)
             holder.session.setHibernateFlushMode(defaultFlushMode)
         }
     }
-
-
-
-
 }
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/generator/GrailsSequenceGeneratorEnum.groovy b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/generator/GrailsSequenceGeneratorEnum.groovy
index 04e1f4dc44..69f1477672 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/generator/GrailsSequenceGeneratorEnum.groovy
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/generator/GrailsSequenceGeneratorEnum.groovy
@@ -16,17 +16,18 @@ import org.grails.orm.hibernate.cfg.Identity
  */
 @CompileStatic
 enum GrailsSequenceGeneratorEnum {
-    IDENTITY("identity"),
-    SEQUENCE("sequence"),
-    SEQUENCE_IDENTITY("sequence-identity"),
-    INCREMENT("increment"),
-    UUID("uuid"),
-    UUID2("uuid2"),
-    ASSIGNED("assigned"),
-    TABLE("table"),
-    ENHANCED_TABLE("enhanced-table"),
-    HILO("hilo"),
-    NATIVE("native")
+
+    IDENTITY('identity'),
+    SEQUENCE('sequence'),
+    SEQUENCE_IDENTITY('sequence-identity'),
+    INCREMENT('increment'),
+    UUID('uuid'),
+    UUID2('uuid2'),
+    ASSIGNED('assigned'),
+    TABLE('table'),
+    ENHANCED_TABLE('enhanced-table'),
+    HILO('hilo'),
+    NATIVE('native')
 
     private final String name
 
@@ -83,4 +84,4 @@ enum GrailsSequenceGeneratorEnum {
                 return new GrailsNativeGenerator(context)
         }
     }
-}
\ No newline at end of file
+}
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/dirty/GrailsEntityDirtinessStrategy.groovy b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/dirty/GrailsEntityDirtinessStrategy.groovy
index d6684f9a6a..621573b5c9 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/dirty/GrailsEntityDirtinessStrategy.groovy
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/dirty/GrailsEntityDirtinessStrategy.groovy
@@ -44,7 +44,7 @@ import org.slf4j.LoggerFactory
 @CompileStatic
 class GrailsEntityDirtinessStrategy implements CustomEntityDirtinessStrategy {
 
-    protected static final Logger LOG = LoggerFactory.getLogger(GrailsEntityDirtinessStrategy.class)
+    protected static final Logger LOG = LoggerFactory.getLogger(GrailsEntityDirtinessStrategy)
 
     @Override
     boolean canDirtyCheck(Object entity, EntityPersister persister, Session session) {
@@ -111,13 +111,13 @@ class GrailsEntityDirtinessStrategy implements CustomEntityDirtinessStrategy {
         } as AttributeChecker)
     }
 
-    Status getStatus(Session session, Object entity) {
+    static Status getStatus(Session session, Object entity) {
         SessionImplementor si = (SessionImplementor) session
         EntityEntry entry = si.getPersistenceContext().getEntry(entity)
         return entry != null ? entry.getStatus() : null
     }
 
-    private DirtyCheckable cast(Object entity) {
-        return DirtyCheckable.class.cast(entity)
+    private static DirtyCheckable cast(Object entity) {
+        return DirtyCheckable.cast(entity)
     }
 }
diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceSettingsSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceSettingsSpec.groovy
index 443f208ac5..b233ce8464 100644
--- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceSettingsSpec.groovy
+++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceSettingsSpec.groovy
@@ -79,7 +79,7 @@ class HibernateConnectionSourceSettingsSpec extends Specification {
         hibernateProperties['hibernate.hbm2ddl.auto'] == 'create'
         hibernateProperties['hibernate.cache.queries'] == 'true'
         hibernateProperties['hibernate.flush.mode'] == 'commit'
-        hibernateProperties['hibernate.naming_strategy'] == 'org.hibernate.boot.model.naming.CamelCaseToUnderscoresNamingStrategy'
+        hibernateProperties['hibernate.naming_strategy'] == 'org.hibernate.boot.model.naming.PhysicalNamingStrategySnakeCaseImpl'
         hibernateProperties['hibernate.entity_dirtiness_strategy'] == 'org.grails.orm.hibernate.dirty.GrailsEntityDirtinessStrategy'
         hibernateProperties['hibernate.configLocations'] == 'file:hibernate.cfg.xml'
         hibernateProperties['hibernate.use_query_cache'] == 'true'


(grails-core) 06/34: hibernate7: cleanup ListSecondPassBinder

Posted by bo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

borinquenkid pushed a commit to branch 8.0.x-hibernate7-dev
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit 32d3c5c3147a2630eaa110183c79ecb65777a6a5
Author: Walter Duque de Estrada <wb...@mac.com>
AuthorDate: Thu Mar 5 19:28:54 2026 -0600

    hibernate7: cleanup ListSecondPassBinder
---
 .../hibernate/HibernateAssociation.java            |  4 ++
 .../hibernate/HibernateManyToOneProperty.java      |  5 ++
 .../hibernate/HibernateOneToManyProperty.java      |  4 ++
 .../secondpass/ListSecondPassBinder.java           | 12 ++---
 .../HibernateManyToOnePropertySpec.groovy          | 57 ++++++++++++++++++++++
 .../HibernateOneToManyPropertySpec.groovy          | 56 +++++++++++++++++++++
 6 files changed, 132 insertions(+), 6 deletions(-)

diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateAssociation.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateAssociation.java
index d5cb2885fc..313315066e 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateAssociation.java
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateAssociation.java
@@ -72,6 +72,10 @@ public interface HibernateAssociation extends HibernatePersistentProperty {
     return (GrailsHibernatePersistentEntity) getAssociatedEntity();
   }
 
+  default String getReferencedEntityName() {
+    return getHibernateAssociatedEntity().getName();
+  }
+
   @Override
   default void validateAssociation() {
     if (getUserType() != null) {
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateManyToOneProperty.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateManyToOneProperty.java
index 97cfb69171..8c50511729 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateManyToOneProperty.java
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateManyToOneProperty.java
@@ -40,7 +40,12 @@ public class HibernateManyToOneProperty extends ManyToOneWithMapping<PropertyCon
 
 
 
+ public String getReferencedEntityName() {
+   return getHibernateAssociatedEntity().getName();
+ }
+
  public  boolean isValidHibernateManyToOne() {
+
     validateAssociation();
      return true;
   }
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateOneToManyProperty.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateOneToManyProperty.java
index ec0f6e6338..74400d0dfe 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateOneToManyProperty.java
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateOneToManyProperty.java
@@ -36,4 +36,8 @@ public class HibernateOneToManyProperty extends OneToManyWithMapping<PropertyCon
   public GrailsHibernatePersistentEntity getHibernateAssociatedEntity() {
     return (GrailsHibernatePersistentEntity) super.getAssociatedEntity();
   }
+
+  public String getReferencedEntityName() {
+    return getHibernateAssociatedEntity().getName();
+  }
 }
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/ListSecondPassBinder.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/ListSecondPassBinder.java
index 4fd1d67c30..ed4dfa0862 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/ListSecondPassBinder.java
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/ListSecondPassBinder.java
@@ -25,7 +25,9 @@ import java.util.Map;
 import org.grails.datastore.mapping.model.PersistentEntity;
 import org.grails.orm.hibernate.cfg.PersistentEntityNamingStrategy;
 import org.grails.orm.hibernate.cfg.domainbinding.binder.SimpleValueColumnBinder;
+import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateAssociation;
 import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateManyToManyProperty;
+import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateManyToOneProperty;
 import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateToManyProperty;
 import org.grails.orm.hibernate.cfg.domainbinding.util.BackticksRemover;
 import org.hibernate.MappingException;
@@ -36,8 +38,6 @@ import org.hibernate.mapping.BasicValue;
 import org.hibernate.mapping.DependantValue;
 import org.hibernate.mapping.IndexBackref;
 import org.hibernate.mapping.List;
-import org.hibernate.mapping.ManyToOne;
-import org.hibernate.mapping.OneToMany;
 import org.hibernate.mapping.PersistentClass;
 import org.hibernate.mapping.Table;
 import org.hibernate.mapping.Value;
@@ -95,11 +95,11 @@ public class ListSecondPassBinder {
     if (property.isBidirectional()) {
 
       String entityName;
-      Value element = list.getElement();
-      if (element instanceof ManyToOne manyToOne) {
-          entityName = manyToOne.getReferencedEntityName();
+      HibernateAssociation inverseSide = property.getHibernateInverseSide();
+      if (inverseSide instanceof HibernateManyToOneProperty manyToOne) {
+        entityName = manyToOne.getReferencedEntityName();
       } else {
-        entityName = ((OneToMany) element).getReferencedEntityName();
+        entityName = inverseSide.getReferencedEntityName();
       }
 
       PersistentClass referenced = mappings.getEntityBinding(entityName);
diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateManyToOnePropertySpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateManyToOnePropertySpec.groovy
new file mode 100644
index 0000000000..3fe6bafc3f
--- /dev/null
+++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateManyToOnePropertySpec.groovy
@@ -0,0 +1,57 @@
+/*
+ *  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.orm.hibernate.cfg.domainbinding.hibernate
+
+import grails.gorm.annotation.Entity
+import grails.gorm.specs.HibernateGormDatastoreSpec
+import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateManyToOneProperty
+
+class HibernateManyToOnePropertySpec extends HibernateGormDatastoreSpec {
+
+    def setupSpec() {
+        manager.addAllDomainClasses([HMTOPBook, HMTOPAuthor])
+    }
+
+    void "test getReferencedEntityName returns the correct entity name"() {
+        given:
+        def bookEntity = mappingContext.getPersistentEntity(HMTOPBook.name)
+        HibernateManyToOneProperty property = (HibernateManyToOneProperty) bookEntity.getPropertyByName("author")
+
+        when:
+        String entityName = property.getReferencedEntityName()
+
+        then:
+        entityName == HMTOPAuthor.name
+    }
+}
+
+@Entity
+class HMTOPBook {
+    Long id
+    String title
+    HMTOPAuthor author
+}
+
+@Entity
+class HMTOPAuthor {
+    Long id
+    String name
+    Set<HMTOPBook> books
+    static hasMany = [books: HMTOPBook]
+}
diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateOneToManyPropertySpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateOneToManyPropertySpec.groovy
new file mode 100644
index 0000000000..8884fefdbd
--- /dev/null
+++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateOneToManyPropertySpec.groovy
@@ -0,0 +1,56 @@
+/*
+ *  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.orm.hibernate.cfg.domainbinding.hibernate
+
+import grails.gorm.annotation.Entity
+import grails.gorm.specs.HibernateGormDatastoreSpec
+import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateOneToManyProperty
+
+class HibernateOneToManyPropertySpec extends HibernateGormDatastoreSpec {
+
+    def setupSpec() {
+        manager.addAllDomainClasses([HOTMPBook, HOTMPAuthor])
+    }
+
+    void "test getReferencedEntityName returns the correct entity name"() {
+        given:
+        def authorEntity = mappingContext.getPersistentEntity(HOTMPAuthor.name)
+        HibernateOneToManyProperty property = (HibernateOneToManyProperty) authorEntity.getPropertyByName("books")
+
+        when:
+        String entityName = property.getReferencedEntityName()
+
+        then:
+        entityName == HOTMPBook.name
+    }
+}
+
+@Entity
+class HOTMPBook {
+    Long id
+    String title
+}
+
+@Entity
+class HOTMPAuthor {
+    Long id
+    String name
+    Set<HOTMPBook> books
+    static hasMany = [books: HOTMPBook]
+}


(grails-core) 16/34: hibernate7: add Positional Parameters support

Posted by bo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

borinquenkid pushed a commit to branch 8.0.x-hibernate7-dev
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit 798bd1059ea85d239202eda764eafb14d8836833
Author: Walter Duque de Estrada <wb...@mac.com>
AuthorDate: Fri Mar 6 17:30:59 2026 -0600

    hibernate7: add Positional Parameters support
---
 .../orm/hibernate/HibernateGormStaticApi.groovy    | 18 +++---
 .../orm/hibernate/query/HibernateHqlQuery.java     | 48 ++++------------
 .../orm/hibernate/query/HqlListQueryBuilder.java   |  6 +-
 .../orm/hibernate/query/HqlQueryContext.java       | 67 +++++++++++++++++++---
 .../hibernate/query/HibernateHqlQuerySpec.groovy   | 28 ++++++++-
 .../orm/hibernate/query/HqlQueryContextSpec.groovy | 51 ++++++++++++----
 6 files changed, 147 insertions(+), 71 deletions(-)

diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy
index 81fd409907..f4f49f10cb 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy
@@ -34,11 +34,11 @@ import org.grails.datastore.mapping.query.event.PreQueryEvent
 import org.grails.datastore.mapping.proxy.ProxyHandler
 import org.grails.orm.hibernate.query.HibernateHqlQuery
 import org.grails.orm.hibernate.query.HibernateQuery
+import org.grails.orm.hibernate.query.HqlListQueryBuilder
 import org.grails.orm.hibernate.query.HqlQueryContext
 import org.grails.orm.hibernate.query.PagedResultList
 import org.grails.orm.hibernate.support.HibernateRuntimeUtils
 
-import org.hibernate.LockMode
 import org.hibernate.Session
 import org.hibernate.SessionFactory
 import org.hibernate.query.Query
@@ -388,15 +388,14 @@ class HibernateGormStaticApi<D> extends GormStaticApi<D> {
 
     @SuppressWarnings('GroovyAssignabilityCheck')
     private HibernateHqlQuery prepareHqlQuery(CharSequence hql, boolean isNative, boolean isUpdate,
-                                              Map namedParams, Collection positionalParams, Map args) {
-        def ctx = HqlQueryContext.prepare(hql, isNative, isUpdate, namedParams, persistentEntity)
+                                              Map namedParams, Collection positionalParams, Map querySettings) {
+        def ctx = HqlQueryContext.prepare(persistentEntity, hql, namedParams, positionalParams,querySettings, isNative, isUpdate,)
         return HibernateHqlQuery.createHqlQuery(
                 (HibernateDatastore) datastore,
                 sessionFactory,
                 persistentEntity,
-                ctx,
-                args,
-                positionalParams,
+                ctx
+                ,
                 getHibernateTemplate(),
                 conversionService
         )
@@ -432,11 +431,14 @@ class HibernateGormStaticApi<D> extends GormStaticApi<D> {
     @Override
     List<D> list(Map params = Collections.emptyMap()) {
         firePreQueryEvent()
-        HibernateHqlQuery hqlQuery = HibernateHqlQuery.forList(
+        HqlListQueryBuilder builder = new HqlListQueryBuilder(persistentEntity, params);
+        String hql = builder.buildListHql();
+        HqlQueryContext ctx = HqlQueryContext.prepare(persistentEntity, hql, Collections.emptyMap(), Collections.emptyList(), params , false, false );
+        HibernateHqlQuery hqlQuery = HibernateHqlQuery.createHqlQuery(
                 (HibernateDatastore) datastore,
                 sessionFactory,
                 persistentEntity,
-                params,
+                ctx,
                 getHibernateTemplate(),
                 datastore.mappingContext.conversionService
         )
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateHqlQuery.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateHqlQuery.java
index b7120a501f..dadaffdeb4 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateHqlQuery.java
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateHqlQuery.java
@@ -136,14 +136,11 @@ public class HibernateHqlQuery extends Query {
    * Full factory — opens a session via the {@link GrailsHibernateTemplate}, builds the query from
    * the prepared {@link HqlQueryContext}, then applies settings and parameters.
    */
-  @SuppressWarnings({"unchecked", "rawtypes"})
-  private static HibernateHqlQuery create(
+  protected static HibernateHqlQuery create(
       HibernateDatastore dataStore,
       SessionFactory sessionFactory,
       PersistentEntity entity,
       HqlQueryContext ctx,
-      Map args,
-      Collection positionalParams,
       GrailsHibernateTemplate template,
       ConversionService conversionService) {
     HibernateHqlQuery hqlQuery =
@@ -153,47 +150,26 @@ public class HibernateHqlQuery extends Query {
       template.applySettings(selectQuery);
     }
     hqlQuery.populateQuerySettings(
-        MapUtils.isNotEmpty(args) ? new HashMap<>(args) : Collections.emptyMap(),
+        MapUtils.isNotEmpty(ctx.querySettings()) ? new HashMap<>(ctx.querySettings()) : Collections.emptyMap(),
         conversionService);
     if (MapUtils.isNotEmpty(ctx.namedParams())) {
       hqlQuery.populateQueryWithNamedArguments(ctx.namedParams());
-    } else if (CollectionUtils.isNotEmpty(positionalParams)) {
-      hqlQuery.populateQueryWithIndexedArguments(List.copyOf(positionalParams));
+    } else if (CollectionUtils.isNotEmpty(ctx.positionalParams())) {
+      hqlQuery.populateQueryWithIndexedArguments(List.copyOf(ctx.positionalParams()));
     }
     return hqlQuery;
   }
 
-  @SuppressWarnings({"unchecked", "rawtypes"})
   public static HibernateHqlQuery createHqlQuery(
       HibernateDatastore dataStore,
       SessionFactory sessionFactory,
       PersistentEntity entity,
       HqlQueryContext ctx,
-      Map args,
-      Collection positionalParams,
       GrailsHibernateTemplate template,
       ConversionService conversionService) {
-    return create(dataStore, sessionFactory, entity, ctx, args, positionalParams, template, conversionService);
+    return create(dataStore, sessionFactory, entity, ctx, template, conversionService);
   }
 
-  /**
-   * Factory for {@code list(Map params)} — builds HQL with ORDER BY / JOIN FETCH from the params
-   * map, applies pagination settings, and wraps in a ready-to-execute {@link HibernateHqlQuery}.
-   */
-  @SuppressWarnings({"unchecked", "rawtypes"})
-  public static HibernateHqlQuery forList(
-      HibernateDatastore dataStore,
-      SessionFactory sessionFactory,
-      PersistentEntity entity,
-      Map<?, ?> params,
-      GrailsHibernateTemplate template,
-      ConversionService conversionService) {
-    HqlListQueryBuilder builder = new HqlListQueryBuilder(entity, params);
-    String hql = builder.buildListHql();
-    HqlQueryContext ctx = HqlQueryContext.prepare(hql, false, false, Collections.emptyMap(), entity);
-    Map<String, Object> mutableParams = params instanceof Map ? new HashMap<>((Map<String, Object>) params) : Collections.emptyMap();
-    return create(dataStore, sessionFactory, entity, ctx, mutableParams, Collections.emptyList(), template, conversionService);
-  }
 
   /**
    * Builds the count HQL string used by {@link PagedResultList} when paging is requested.
@@ -204,14 +180,14 @@ public class HibernateHqlQuery extends Query {
 
   // ─── Query configuration ─────────────────────────────────────────────────
 
-  public void setFlushMode(FlushMode flushMode) {
+  protected void setFlushMode(FlushMode flushMode) {
     session.setFlushMode(
         flushMode == FlushMode.AUTO || flushMode == FlushMode.ALWAYS
             ? FlushModeType.AUTO
             : FlushModeType.COMMIT);
   }
 
-  public void populateQuerySettings(Map<?, ?> args, ConversionService conversionService) {
+  protected void populateQuerySettings(Map<?, ?> args, ConversionService conversionService) {
     ifPresent(args, HibernateQueryArgument.MAX.value(), v -> delegate.setMaxResults(toInt(v, conversionService)));
     ifPresent(args, HibernateQueryArgument.OFFSET.value(), v -> delegate.setFirstResult(toInt(v, conversionService)));
     ifPresent(args, HibernateQueryArgument.CACHE.value(), v -> delegate.setCacheable(toBool(v)));
@@ -244,7 +220,7 @@ public class HibernateHqlQuery extends Query {
     };
   }
 
-  private static FlushMode convertFlushMode(Object object) {
+  public static FlushMode convertFlushMode(Object object) {
     if (object == null) return null;
     if (object instanceof FlushMode flushMode) return flushMode;
     try {
@@ -254,7 +230,7 @@ public class HibernateHqlQuery extends Query {
     }
   }
 
-  public void populateQueryWithNamedArguments(Map<?, ?> namedArgs) {
+  protected void populateQueryWithNamedArguments(Map<?, ?> namedArgs) {
     if (namedArgs == null) return;
     namedArgs.forEach(
         (key, value) -> {
@@ -276,7 +252,7 @@ public class HibernateHqlQuery extends Query {
         });
   }
 
-  public void populateQueryWithIndexedArguments(List<?> params) {
+  protected void populateQueryWithIndexedArguments(List<?> params) {
     if (params == null) return;
     for (int i = 0; i < params.size(); i++) {
       Object val = params.get(i);
@@ -307,9 +283,7 @@ public class HibernateHqlQuery extends Query {
 
   // ─── Private utilities ────────────────────────────────────────────────────
 
-  private static int toInt(Object v) {
-    return Integer.parseInt(v.toString());
-  }
+
 
   private static int toInt(Object v, ConversionService cs) {
     if (v instanceof Integer i) return i;
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HqlListQueryBuilder.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HqlListQueryBuilder.java
index aaf3ce740b..3516b4d657 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HqlListQueryBuilder.java
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HqlListQueryBuilder.java
@@ -37,18 +37,18 @@ import org.grails.orm.hibernate.cfg.MappingCacheHolder;
  * string so it passes through {@link HqlQueryContext} without GString interpolation.
  */
 @SuppressWarnings("PMD.DataflowAnomalyAnalysis")
-class HqlListQueryBuilder {
+public class HqlListQueryBuilder {
 
   private final PersistentEntity entity;
   private final Map<?, ?> params;
 
-  HqlListQueryBuilder(PersistentEntity entity, Map<?, ?> params) {
+  public HqlListQueryBuilder(PersistentEntity entity, Map<?, ?> params) {
     this.entity = entity;
     this.params = params;
   }
 
   /** Builds the SELECT HQL for the list query (no count). */
-  String buildListHql() {
+  public String buildListHql() {
     String alias = "e";
     StringBuilder hql = new StringBuilder("from ").append(entity.getName()).append(" ").append(alias);
     appendJoinFetch(hql, alias);
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HqlQueryContext.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HqlQueryContext.java
index 9588665b61..0368f7e238 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HqlQueryContext.java
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HqlQueryContext.java
@@ -19,6 +19,9 @@
 package org.grails.orm.hibernate.query;
 
 import groovy.lang.GString;
+
+import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.Locale;
 import java.util.Map;
@@ -44,6 +47,8 @@ public record HqlQueryContext(
     String hql,
     Class<?> targetClass,
     Map<String, Object> namedParams,
+    Collection positionalParams,
+    Map<String, Object> querySettings,
     boolean isUpdate,
     boolean isNative) {
 
@@ -55,16 +60,30 @@ public record HqlQueryContext(
    */
   @SuppressWarnings("unchecked")
   public static HqlQueryContext prepare(
-      CharSequence queryCharseq,
-      boolean isNative,
-      boolean isUpdate,
-      Map<?, ?> namedParams,
-      PersistentEntity entity) {
-    Map<String, Object> params =
+          PersistentEntity entity
+          , CharSequence queryCharseq
+          , Map<?, ?> namedParams
+          , Collection positionalParams
+          , Map querySettings
+          , boolean isNative
+          , boolean isUpdate) {
+    Map<String, Object> _namedParams =
         namedParams != null ? new HashMap<>((Map<String, Object>) namedParams) : new HashMap<>();
-    String hql = resolveHql(queryCharseq, isNative, params);
-    return new HqlQueryContext(
-        hql, getTarget(hql, entity.getJavaClass()), params, isUpdate, isNative);
+    Collection positionalParamsCopy = positionalParams != null ? new ArrayList<>(positionalParams) : null;
+    Map<String, Object> querySettingsCopy = querySettings != null ? new HashMap<>(querySettings) : null;
+
+    String hql;
+    // Prefer positional resolution only if positional parameters are explicitly provided (not null)
+    // and named parameters are empty. This preserves legacy GString->named parameter behavior
+    // while allowing opt-in to positional parameters via methods that pass them.
+    if (positionalParamsCopy != null && _namedParams.isEmpty()) {
+      hql = resolveHql(queryCharseq, isNative, positionalParamsCopy);
+    } else {
+      hql = resolveHql(queryCharseq, isNative, _namedParams);
+    }
+
+    Class<?> target = getTarget(hql, entity.getJavaClass());
+    return new HqlQueryContext(hql, target, _namedParams, positionalParamsCopy, querySettingsCopy, isUpdate, isNative);
   }
 
   // ─── HQL resolution ──────────────────────────────────────────────────────
@@ -79,6 +98,16 @@ public record HqlQueryContext(
     return isNative ? normalized : normalizeNonAliasedSelect(normalized);
   }
 
+  public static @Nullable String resolveHql(
+      CharSequence queryCharseq, boolean isNative, Collection positionalParams) {
+    String raw =
+        queryCharseq instanceof GString gstr
+            ? buildPositionalParameterQueryFromGString(gstr, positionalParams, isNative)
+            : queryCharseq != null ? queryCharseq.toString() : "";
+    String normalized = normalizeMultiLineQueryString(raw);
+    return isNative ? normalized : normalizeNonAliasedSelect(normalized);
+  }
+
   // ─── Projection analysis ─────────────────────────────────────────────────
 
   /**
@@ -255,4 +284,24 @@ public record HqlQueryContext(
     }
     return sql.toString();
   }
+
+  @SuppressWarnings("unchecked")
+  private static String buildPositionalParameterQueryFromGString(
+      GString query, Collection positionalParams, boolean isNative) {
+    StringBuilder sql = new StringBuilder();
+    Object[] values = query.getValues();
+    String[] strings = query.getStrings();
+    for (int i = 0; i < strings.length; i++) {
+      sql.append(strings[i]);
+      if (i < values.length) {
+        if (isNative) {
+          sql.append('?');
+        } else {
+          sql.append('?').append(positionalParams.size() + 1);
+        }
+        positionalParams.add(values[i]);
+      }
+    }
+    return sql.toString();
+  }
 }
diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/query/HibernateHqlQuerySpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/query/HibernateHqlQuerySpec.groovy
index f992d69659..ab4377f974 100644
--- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/query/HibernateHqlQuerySpec.groovy
+++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/query/HibernateHqlQuerySpec.groovy
@@ -20,12 +20,12 @@ class HibernateHqlQuerySpec extends HibernateGormDatastoreSpec {
 
     private HibernateHqlQuery buildHqlQuery(String hql, Map namedParams = [:], List positionalParams = null, Map args = [:], boolean isUpdate = false) {
         def entity = mappingContext.getPersistentEntity(HibernateHqlQuerySpecBook.name)
-        def ctx = HqlQueryContext.prepare(hql, false, isUpdate, namedParams, entity)
+        def ctx = HqlQueryContext.prepare(entity, hql, namedParams, positionalParams, args, false, isUpdate)
         def session = sessionFactory.currentSession
         def hqlQuery = HibernateHqlQuery.buildQuery(session, datastore, sessionFactory, entity, ctx)
         if (args) hqlQuery.populateQuerySettings(new HashMap(args), mappingContext.conversionService)
         if (ctx.namedParams()) hqlQuery.populateQueryWithNamedArguments(new HashMap(ctx.namedParams()))
-        else if (positionalParams) hqlQuery.populateQueryWithIndexedArguments(positionalParams)
+        else if (ctx.positionalParams()) hqlQuery.populateQueryWithIndexedArguments(List.copyOf(ctx.positionalParams()))
         hqlQuery
     }
 
@@ -145,15 +145,37 @@ class HibernateHqlQuerySpec extends HibernateGormDatastoreSpec {
         GString gq = "from HibernateHqlQuerySpecBook b where b.title = ${titleVal}"
         when:
         def entity = mappingContext.getPersistentEntity(HibernateHqlQuerySpecBook.name)
-        def ctx = HqlQueryContext.prepare(gq, false, false, [:], entity)
+        def ctx = HqlQueryContext.prepare(entity, gq, [:], null, [:], false, false)
         def hqlQuery = HibernateHqlQuery.buildQuery(sessionFactory.currentSession, datastore, sessionFactory, entity, ctx)
         if (ctx.namedParams()) hqlQuery.populateQueryWithNamedArguments(new HashMap(ctx.namedParams()))
+        else if (ctx.positionalParams()) hqlQuery.populateQueryWithIndexedArguments(List.copyOf(ctx.positionalParams()))
         def results = hqlQuery.list()
         then:
         results.size() == 1
         results[0].title == "The Two Towers"
     }
 
+    void "createHqlQuery with GString can build positional parameters if explicitly requested"() {
+        given:
+        String titleVal = "The Two Towers"
+        GString gq = "from HibernateHqlQuerySpecBook b where b.title = ${titleVal}"
+        when: "positionalParams is provided as non-null (triggering positional branch in prepare)"
+        def entity = mappingContext.getPersistentEntity(HibernateHqlQuerySpecBook.name)
+        // We pass an empty but non-null list to trigger the positional branch
+        def positionalParams = []
+        def ctx = HqlQueryContext.prepare(entity, gq, [:], positionalParams, [:], false, false)
+        // The GString should have appended the value as ?1
+        def hqlQuery = HibernateHqlQuery.buildQuery(sessionFactory.currentSession, datastore, sessionFactory, entity, ctx)
+
+        if (ctx.positionalParams()) hqlQuery.populateQueryWithIndexedArguments(List.copyOf(ctx.positionalParams()))
+        def results = hqlQuery.list()
+
+        then:
+        ctx.hql().contains("?1")
+        results.size() == 1
+        results[0].title == "The Two Towers"
+    }
+
     void "createHqlQuery with multiline query normalizes whitespace"() {
         when:
         def results = buildHqlQuery("from HibernateHqlQuerySpecBook b\nwhere b.pages > :p", [p: 350]).list()
diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/query/HqlQueryContextSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/query/HqlQueryContextSpec.groovy
index b80fc6a085..5c13d2334a 100644
--- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/query/HqlQueryContextSpec.groovy
+++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/query/HqlQueryContextSpec.groovy
@@ -29,7 +29,7 @@ class HqlQueryContextSpec extends Specification {
     void "record accessors return constructor values"() {
         given:
         def params = [name: "Alice"]
-        def ctx = new HqlQueryContext("from Person", String, params, false, false)
+        def ctx = new HqlQueryContext("from Person", String, params, null, [:], false, false)
 
         expect:
         ctx.hql()         == "from Person"
@@ -41,7 +41,7 @@ class HqlQueryContextSpec extends Specification {
 
     void "record isUpdate and isNative flags are set correctly"() {
         given:
-        def ctx = new HqlQueryContext("update Foo set x=1", Object, [:], true, true)
+        def ctx = new HqlQueryContext("update Foo set x=1", Object, [:], null, [:], true, true)
 
         expect:
         ctx.isUpdate()
@@ -55,7 +55,7 @@ class HqlQueryContextSpec extends Specification {
         def entity = Mock(PersistentEntity) { getJavaClass() >> String }
 
         when:
-        def ctx = HqlQueryContext.prepare("from Foo", false, false, null, entity)
+        def ctx = HqlQueryContext.prepare(entity, "from Foo", null, null, [:], false, false)
 
         then:
         ctx.hql()              == "from Foo"
@@ -65,18 +65,47 @@ class HqlQueryContextSpec extends Specification {
         !ctx.isNative()
     }
 
-    void "prepare with GString expands interpolations into named parameters"() {
+    void "prepare with GString and positionalParams expands interpolations into positional parameters"() {
         given:
         def entity = Mock(PersistentEntity) { getJavaClass() >> String }
         String val = "bar"
         GString gq = "from Foo where name = ${val}"
 
         when:
-        def ctx = HqlQueryContext.prepare(gq, false, false, null, entity)
+        def ctx = HqlQueryContext.prepare(entity, gq, [:], [], [:], false, false)
 
         then:
-        ctx.hql()         == "from Foo where name = :p0"
-        ctx.namedParams() == [p0: "bar"]
+        ctx.hql()              == "from Foo where name = ?1"
+        ctx.positionalParams() == ["bar"]
+        ctx.namedParams().isEmpty()
+    }
+
+    void "reproduce HibernateHqlQuerySpec failure"() {
+        given:
+        def entity = Mock(PersistentEntity) { getJavaClass() >> String; getName() >> "Book" }
+        String titleVal = "The Two Towers"
+        GString gq = "from HibernateHqlQuerySpecBook b where b.title = ${titleVal}"
+
+        when:
+        def ctx = HqlQueryContext.prepare(entity, gq, [:], [], [:], false, false)
+
+        then:
+        ctx.hql() == "from HibernateHqlQuerySpecBook b where b.title = ?1"
+        ctx.positionalParams() == ["The Two Towers"]
+    }
+
+    void "prepare with GString and non-empty positionalParams appends to existing parameters"() {
+        given:
+        def entity = Mock(PersistentEntity) { getJavaClass() >> String }
+        String val = "bar"
+        GString gq = "from Foo where name = ${val}"
+
+        when:
+        def ctx = HqlQueryContext.prepare(entity, gq, [:], ["first"], [:], false, false)
+
+        then:
+        ctx.hql()              == "from Foo where name = ?2"
+        ctx.positionalParams() == ["first", "bar"]
     }
 
     void "prepare merges caller-supplied namedParams with GString params"() {
@@ -86,7 +115,7 @@ class HqlQueryContextSpec extends Specification {
         GString gq = "from Foo where name = ${val} and status = :status"
 
         when:
-        def ctx = HqlQueryContext.prepare(gq, false, false, [status: "active"], entity)
+        def ctx = HqlQueryContext.prepare(entity, gq, [status: "active"], null, [:], false, false)
 
         then:
         ctx.namedParams().p0     == "bar"
@@ -98,7 +127,7 @@ class HqlQueryContextSpec extends Specification {
         def entity = Mock(PersistentEntity) { getJavaClass() >> String }
 
         when:
-        def ctx = HqlQueryContext.prepare("select name from foo", true, false, null, entity)
+        def ctx = HqlQueryContext.prepare(entity, "select name from foo", null, null, [:], true, false)
 
         then:
         ctx.hql()      == "select name from foo"  // alias injection skipped for native SQL
@@ -110,7 +139,7 @@ class HqlQueryContextSpec extends Specification {
         def entity = Mock(PersistentEntity) { getJavaClass() >> String }
 
         when:
-        def ctx = HqlQueryContext.prepare("update Foo set x=1", false, true, null, entity)
+        def ctx = HqlQueryContext.prepare(entity, "update Foo set x=1", null, null, [:], false, true)
 
         then:
         ctx.isUpdate()
@@ -121,7 +150,7 @@ class HqlQueryContextSpec extends Specification {
         def entity = Mock(PersistentEntity) { getJavaClass() >> String }
 
         when:
-        def ctx = HqlQueryContext.prepare("from Foo", false, false, null, entity)
+        def ctx = HqlQueryContext.prepare(entity, "from Foo", null, null, [:], false, false)
 
         then:
         noExceptionThrown()


(grails-core) 22/34: hibernate7: more Codenarc

Posted by bo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

borinquenkid pushed a commit to branch 8.0.x-hibernate7-dev
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit 5243c05169f482952e731a5a306b41634fe873d6
Author: Walter Duque de Estrada <wb...@mac.com>
AuthorDate: Sat Mar 7 13:56:11 2026 -0600

    hibernate7: more Codenarc
---
 .../hibernate/annotation/ManagedEntity.java        |  0
 .../orm/hibernate/HibernateGormEnhancer.groovy     |  1 +
 .../orm/hibernate/HibernateGormInstanceApi.groovy  | 80 ++++++++----------
 .../compiler/HibernateEntityTransformation.groovy  | 98 +++++++++++++---------
 4 files changed, 95 insertions(+), 84 deletions(-)

diff --git a/grails-data-hibernate7/core/src/main/groovy/grails/orm/hibernate/annotation/ManagedEntity.java b/grails-data-hibernate7/core/src/main/groovy/grails/gorm/hibernate/annotation/ManagedEntity.java
similarity index 100%
rename from grails-data-hibernate7/core/src/main/groovy/grails/orm/hibernate/annotation/ManagedEntity.java
rename to grails-data-hibernate7/core/src/main/groovy/grails/gorm/hibernate/annotation/ManagedEntity.java
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormEnhancer.groovy b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormEnhancer.groovy
index 1140a54019..e2799ea68b 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormEnhancer.groovy
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormEnhancer.groovy
@@ -22,6 +22,7 @@ import org.grails.datastore.gorm.GormValidationApi
 import org.grails.datastore.mapping.core.Datastore
 import org.grails.datastore.mapping.core.connections.ConnectionSourceSettings
 import org.springframework.transaction.PlatformTransactionManager
+
 /**
  * Extended GORM Enhancer that fills out the remaining GORM for Hibernate methods
  * and implements string-based query support via HQL.
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 0bd4b3e2df..a450402d00 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
@@ -57,23 +57,22 @@ import org.springframework.validation.Validator
 @CompileStatic
 class HibernateGormInstanceApi<D> extends GormInstanceApi<D> {
 
-    private static final String ARGUMENT_VALIDATE = "validate"
-    private static final String ARGUMENT_DEEP_VALIDATE = "deepValidate"
-    private static final String ARGUMENT_FLUSH = "flush"
-    private static final String ARGUMENT_INSERT = "insert"
-    private static final String ARGUMENT_MERGE = "merge"
-    private static final String ARGUMENT_FAIL_ON_ERROR = "failOnError"
+    private static final String ARGUMENT_VALIDATE = 'validate'
+    private static final String ARGUMENT_DEEP_VALIDATE = 'deepValidate'
+    private static final String ARGUMENT_FLUSH = 'flush'
+    private static final String ARGUMENT_INSERT = 'insert'
+    private static final String ARGUMENT_MERGE = 'merge'
+    private static final String ARGUMENT_FAIL_ON_ERROR = 'failOnError'
     private static final Class DEFERRED_BINDING
 
     static {
         try {
             DEFERRED_BINDING = Class.forName('grails.validation.DeferredBindingActions')
-        } catch (Throwable e) {
+        } catch (Throwable ignored) {
             DEFERRED_BINDING = null
         }
     }
 
-    protected static final Object[] EMPTY_ARRAY = []
     static final ThreadLocal<Boolean> insertActiveThreadLocal = new ThreadLocal<Boolean>()
 
     protected SessionFactory sessionFactory
@@ -118,7 +117,7 @@ class HibernateGormInstanceApi<D> extends GormInstanceApi<D> {
                 datastore.applicationEventPublisher?.publishEvent new ValidationEvent(datastore, target)
 
                 if (validator instanceof CascadingValidator) {
-                    ((CascadingValidator)validator).validate target, errors, deepValidate
+                    ((CascadingValidator) validator).validate target, errors, deepValidate
                 } else if (validator instanceof org.grails.datastore.gorm.validation.CascadingValidator) {
                     ((org.grails.datastore.gorm.validation.CascadingValidator) validator).validate target, errors, deepValidate
                 } else {
@@ -126,9 +125,9 @@ class HibernateGormInstanceApi<D> extends GormInstanceApi<D> {
                 }
 
                 if (errors.hasErrors()) {
-                    handleValidationError(domainClass,target,errors)
+                    handleValidationError(domainClass, target, errors)
                     if (shouldFail(arguments)) {
-                        throw validationException.newInstance("Validation Error(s) occurred during save()", errors)
+                        throw validationException.newInstance('Validation Error(s) occurred during save()', errors)
                     }
                     return null
                 }
@@ -143,7 +142,7 @@ class HibernateGormInstanceApi<D> extends GormInstanceApi<D> {
         validateable.skipValidation(true)
 
         try {
-            String idPropertyName = domainClass.identity?.name ?: "id"
+            String idPropertyName = domainClass.identity?.name ?: 'id'
             Object idVal = InvokerHelper.getProperty(target, idPropertyName)
             if (idVal == null) {
                 return performPersist(target, shouldFlush)
@@ -155,11 +154,7 @@ class HibernateGormInstanceApi<D> extends GormInstanceApi<D> {
         }
     }
 
-
-
-
-
-    private void runDeferredBinding() {
+    private static void runDeferredBinding() {
         if (DEFERRED_BINDING != null) {
             // DeferredBindingActions is from grails-data-binding (optional dep); invoked via reflection
             // because it belongs to the migration plugin, which runs once per deployment and need not be on the compile classpath
@@ -192,7 +187,7 @@ class HibernateGormInstanceApi<D> extends GormInstanceApi<D> {
         try {
             hibernateTemplate.execute { Session session ->
                 session.remove instance
-                if(flush) {
+                if (flush) {
                     session.flush()
                 }
             }
@@ -233,7 +228,6 @@ class HibernateGormInstanceApi<D> extends GormInstanceApi<D> {
         return instance
     }
 
-
     protected D performMerge(final D target, final boolean flush) {
         hibernateTemplate.execute { Session session ->
             Object merged = session.merge(target)
@@ -241,7 +235,7 @@ class HibernateGormInstanceApi<D> extends GormInstanceApi<D> {
             if (flush) {
                 flushSession session
             }
-            return (D)merged
+            return (D) merged
         }
     }
 
@@ -257,11 +251,10 @@ class HibernateGormInstanceApi<D> extends GormInstanceApi<D> {
             } finally {
                 resetInsertActive()
             }
-
         }
     }
 
-    protected void flushSession(Session session) throws HibernateException {
+    protected static void flushSession(Session session) throws HibernateException {
         try {
             session.flush()
         } catch (HibernateException e) {
@@ -270,13 +263,13 @@ class HibernateGormInstanceApi<D> extends GormInstanceApi<D> {
         }
     }
 
-    @SuppressWarnings("unchecked")
+    @SuppressWarnings('unchecked')
     private void autoRetrieveAssociations(Datastore datastore, PersistentEntity entity, Object target) {
         EntityReflector reflector = datastore.mappingContext.getEntityReflector(entity)
         IHibernateTemplate t = this.hibernateTemplate
         for (PersistentProperty prop in entity.associations) {
-            if(prop instanceof ToOne && !(prop instanceof Embedded)) {
-                ToOne toOne = (ToOne)prop
+            if (prop instanceof ToOne && !(prop instanceof Embedded)) {
+                ToOne toOne = (ToOne) prop
 
                 def propertyName = prop.name
                 def propValue = reflector.getProperty(target, propertyName)
@@ -290,13 +283,13 @@ class HibernateGormInstanceApi<D> extends GormInstanceApi<D> {
                 }
 
                 def identity = otherSide.identity
-                if(identity == null) {
+                if (identity == null) {
                     continue
                 }
 
                 def otherSideReflector = datastore.mappingContext.getEntityReflector(otherSide)
                 try {
-                    def id = (Serializable)otherSideReflector.getProperty(propValue, identity.name);
+                    def id = (Serializable) otherSideReflector.getProperty(propValue, identity.name)
                     if (id) {
                         final Object associatedInstance = t.get(prop.type, id)
                         if (associatedInstance) {
@@ -304,15 +297,14 @@ class HibernateGormInstanceApi<D> extends GormInstanceApi<D> {
                         }
                     }
                 }
-                catch (InvalidPropertyException ipe) {
+                catch (InvalidPropertyException ignored) {
                     // property is not accessable
                 }
             }
-
         }
     }
 
-    private boolean shouldValidate(Map arguments, PersistentEntity entity) {
+    private static boolean shouldValidate(Map arguments, PersistentEntity entity) {
         if (!entity) {
             return false
         }
@@ -341,11 +333,11 @@ class HibernateGormInstanceApi<D> extends GormInstanceApi<D> {
         if (entity) {
             for (Association association in entity.associations) {
                 if (association instanceof ToOne && !association instanceof Embedded) {
-                        def bean = new BeanWrapperImpl(target)
-                        def propertyValue = bean.getPropertyValue(association.name)
-                        if (propertyValue != null) {
-                            setObjectToReadOnly propertyValue
-                        }
+                    def bean = new BeanWrapperImpl(target)
+                    def propertyValue = bean.getPropertyValue(association.name)
+                    if (propertyValue != null) {
+                        setObjectToReadOnly propertyValue
+                    }
                 }
             }
         }
@@ -362,11 +354,11 @@ class HibernateGormInstanceApi<D> extends GormInstanceApi<D> {
     }
 
     static void markInsertActive() {
-        insertActiveThreadLocal.set(Boolean.TRUE);
+        insertActiveThreadLocal.set(Boolean.TRUE)
     }
 
     static void resetInsertActive() {
-        insertActiveThreadLocal.remove();
+        insertActiveThreadLocal.remove()
     }
 
     /**
@@ -377,9 +369,8 @@ class HibernateGormInstanceApi<D> extends GormInstanceApi<D> {
      *
      * @return true if the field is dirty
      */
-
     boolean isDirty(D instance, String fieldName) {
-        SessionImplementor session = (SessionImplementor)sessionFactory.currentSession
+        SessionImplementor session = (SessionImplementor) sessionFactory.currentSession
         EntityEntry entry = findEntityEntry(instance, session)
         if (!entry || !entry.loadedState) {
             return false
@@ -399,7 +390,7 @@ class HibernateGormInstanceApi<D> extends GormInstanceApi<D> {
         return fieldIndex in dirtyProperties
     }
 
-    private int[] findDirty(EntityPersister persister, Object[] values, EntityEntry entry, D instance, SessionImplementor session) {
+    private static int[] findDirty(EntityPersister persister, Object[] values, EntityEntry entry, D instance, SessionImplementor session) {
         persister.findDirty(values, entry.loadedState, instance, session)
     }
 
@@ -410,7 +401,7 @@ class HibernateGormInstanceApi<D> extends GormInstanceApi<D> {
      * @return true if it is dirty
      */
     boolean isDirty(D instance) {
-        SessionImplementor session = (SessionImplementor)sessionFactory.currentSession
+        SessionImplementor session = (SessionImplementor) sessionFactory.currentSession
         EntityEntry entry = findEntityEntry(instance, session)
         if (!entry || !entry.loadedState) {
             return false
@@ -428,7 +419,7 @@ class HibernateGormInstanceApi<D> extends GormInstanceApi<D> {
      * @return A list of property names that are dirty
      */
     List<String> getDirtyPropertyNames(D instance) {
-        SessionImplementor session = (SessionImplementor)sessionFactory.currentSession
+        SessionImplementor session = (SessionImplementor) sessionFactory.currentSession
         EntityEntry entry = findEntityEntry(instance, session)
         if (!entry || !entry.loadedState) {
             return []
@@ -454,7 +445,7 @@ class HibernateGormInstanceApi<D> extends GormInstanceApi<D> {
      * @return The original persisted value
      */
     Object getPersistentValue(D instance, String fieldName) {
-        SessionImplementor session = (SessionImplementor)sessionFactory.currentSession
+        SessionImplementor session = (SessionImplementor) sessionFactory.currentSession
         def entry = findEntityEntry(instance, session, false)
         if (!entry || !entry.loadedState) {
             return null
@@ -467,8 +458,7 @@ class HibernateGormInstanceApi<D> extends GormInstanceApi<D> {
         return fieldIndex == -1 ? null : entry.loadedState[fieldIndex]
     }
 
-
-    protected EntityEntry findEntityEntry(D instance, SessionImplementor session, boolean forDirtyCheck = true) {
+    protected static EntityEntry findEntityEntry(D instance, SessionImplementor session, boolean forDirtyCheck = true) {
         def entry = session.persistenceContext.getEntry(instance)
         if (!entry) {
             return null
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/compiler/HibernateEntityTransformation.groovy b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/compiler/HibernateEntityTransformation.groovy
index d4a606534c..a358fec8ad 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/compiler/HibernateEntityTransformation.groovy
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/compiler/HibernateEntityTransformation.groovy
@@ -4,7 +4,16 @@ import grails.gorm.dirty.checking.DirtyCheckedProperty
 import groovy.transform.CompilationUnitAware
 import groovy.transform.CompileStatic
 import org.apache.groovy.ast.tools.AnnotatedNodeUtils
-import org.codehaus.groovy.ast.*
+import org.codehaus.groovy.ast.ASTNode
+import org.codehaus.groovy.ast.AnnotatedNode
+import org.codehaus.groovy.ast.AnnotationNode
+import org.codehaus.groovy.ast.ClassHelper
+import org.codehaus.groovy.ast.ClassNode
+import org.codehaus.groovy.ast.FieldNode
+import org.codehaus.groovy.ast.InnerClassNode
+import org.codehaus.groovy.ast.MethodNode
+import org.codehaus.groovy.ast.Parameter
+import org.codehaus.groovy.ast.ClassCodeVisitorSupport
 import org.codehaus.groovy.ast.stmt.BlockStatement
 import org.codehaus.groovy.ast.stmt.IfStatement
 import org.codehaus.groovy.ast.stmt.ReturnStatement
@@ -27,7 +36,20 @@ import org.hibernate.engine.spi.PersistentAttributeInterceptor
 import jakarta.persistence.Transient
 import java.lang.reflect.Modifier
 
-import static org.codehaus.groovy.ast.tools.GeneralUtils.*
+import static org.codehaus.groovy.ast.tools.GeneralUtils.args
+import static org.codehaus.groovy.ast.tools.GeneralUtils.assignS
+import static org.codehaus.groovy.ast.tools.GeneralUtils.callX
+import static org.codehaus.groovy.ast.tools.GeneralUtils.constX
+import static org.codehaus.groovy.ast.tools.GeneralUtils.equalsNullX
+import static org.codehaus.groovy.ast.tools.GeneralUtils.fieldX
+import static org.codehaus.groovy.ast.tools.GeneralUtils.ifS
+import static org.codehaus.groovy.ast.tools.GeneralUtils.neX
+import static org.codehaus.groovy.ast.tools.GeneralUtils.param
+import static org.codehaus.groovy.ast.tools.GeneralUtils.params
+import static org.codehaus.groovy.ast.tools.GeneralUtils.propX
+import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS
+import static org.codehaus.groovy.ast.tools.GeneralUtils.ternaryX
+import static org.codehaus.groovy.ast.tools.GeneralUtils.varX
 
 /**
  * A transformation that transforms entities that implement the {@link grails.gorm.hibernate.annotation.ManagedEntity} trait,
@@ -39,26 +61,27 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.*
 @CompileStatic
 @GroovyASTTransformation(phase = CompilePhase.CANONICALIZATION)
 class HibernateEntityTransformation implements ASTTransformation, CompilationUnitAware {
-    private static final ClassNode MY_TYPE = new ClassNode(grails.gorm.hibernate.annotation.ManagedEntity.class);
-    private static final Object APPLIED_MARKER = new Object();
+
+    private static final ClassNode MY_TYPE = new ClassNode(grails.gorm.hibernate.annotation.ManagedEntity)
+    private static final Object APPLIED_MARKER = new Object()
 
 //    final boolean available = ClassUtils.isPresent("org.hibernate.SessionFactory") && Boolean.valueOf(System.getProperty("hibernate.enhance", "true"))
     CompilationUnit compilationUnit
 
     @Override
     void visit(ASTNode[] astNodes, SourceUnit sourceUnit) {
-        AnnotatedNode parent = (AnnotatedNode) astNodes[1];
-        AnnotationNode node = (AnnotationNode) astNodes[0];
+        AnnotatedNode parent = (AnnotatedNode) astNodes[1]
+        AnnotationNode node = (AnnotationNode) astNodes[0]
 
         if (!(astNodes[0] instanceof AnnotationNode) || !(astNodes[1] instanceof AnnotatedNode)) {
-            throw new RuntimeException("Internal error: wrong types: ${node.getClass()} / ${parent.getClass()}");
+            throw new RuntimeException("Internal error: wrong types: ${node.getClass()} / ${parent.getClass()}")
         }
 
         if (!MY_TYPE.equals(node.getClassNode()) || !(parent instanceof ClassNode)) {
-            return;
+            return
         }
 
-        ClassNode cNode = (ClassNode) parent;
+        ClassNode cNode = (ClassNode) parent
 
         visit(cNode, sourceUnit)
     }
@@ -76,12 +99,12 @@ class HibernateEntityTransformation implements ASTTransformation, CompilationUni
         def mapWith = AstUtils.getPropertyFromHierarchy(classNode, GormProperties.MAPPING_STRATEGY)
         String mapWithValue = mapWith?.initialExpression?.text
 
-        if(mapWithValue != null && (mapWithValue != ('hibernate') || mapWithValue != GormProperties.DEFAULT_MAPPING_STRATEGY)) {
+        if (mapWithValue != null && (mapWithValue != ('hibernate') || mapWithValue != GormProperties.DEFAULT_MAPPING_STRATEGY)) {
             return
         }
 
         new GormEntityTransformation(compilationUnit: compilationUnit).visit(classNode, sourceUnit)
-        
+
         ClassNode managedEntityClassNode = ClassHelper.make(ManagedEntity)
         ClassNode attributeInterceptableClassNode = ClassHelper.make(PersistentAttributeInterceptable)
         ClassNode entityEntryClassNode = ClassHelper.make(EntityEntry)
@@ -97,7 +120,7 @@ class HibernateEntityTransformation implements ASTTransformation, CompilationUni
 
         def staticCompilationVisitor = new StaticCompilationVisitor(sourceUnit, classNode)
 
-        AnnotationNode transientAnnotationNode = new AnnotationNode(ClassHelper.make(Transient.class))
+        AnnotationNode transientAnnotationNode = new AnnotationNode(ClassHelper.make(Transient))
         FieldNode entityEntryHolderField = classNode.addField(entryHolderFieldName, Modifier.PRIVATE | Modifier.TRANSIENT, entityEntryClassNode, null)
         entityEntryHolderField
                  .addAnnotation(transientAnnotationNode)
@@ -118,8 +141,6 @@ class HibernateEntityTransformation implements ASTTransformation, CompilationUni
         interceptorField
                  .addAnnotation(transientAnnotationNode)
 
-
-
         // add method: PersistentAttributeInterceptor $$_hibernate_getInterceptor()
         def getInterceptorMethod = new MethodNode(
                 '$$_hibernate_getInterceptor',
@@ -134,14 +155,14 @@ class HibernateEntityTransformation implements ASTTransformation, CompilationUni
         staticCompilationVisitor.visitMethod(getInterceptorMethod)
 
         // add method: void $$_hibernate_setInterceptor(PersistentAttributeInterceptor interceptor)
-        def p1 = param(persistentAttributeInterceptorClassNode, "interceptor")
+        def p1 = param(persistentAttributeInterceptorClassNode, 'interceptor')
         def setInterceptorMethod = new MethodNode(
                 '$$_hibernate_setInterceptor',
                 Modifier.PUBLIC,
                 ClassHelper.VOID_TYPE,
                 params(p1),
                 null,
-                assignS( varX(interceptorField), varX(p1) )
+                assignS(varX(interceptorField), varX(p1))
         )
         classNode.addMethod(setInterceptorMethod)
         AnnotatedNodeUtils.markAsGenerated(classNode, setInterceptorMethod)
@@ -154,13 +175,12 @@ class HibernateEntityTransformation implements ASTTransformation, CompilationUni
                 ClassHelper.OBJECT_TYPE,
                 AstUtils.ZERO_PARAMETERS,
                 null,
-                returnS(varX("this"))
+                returnS(varX('this'))
         )
         classNode.addMethod(getEntityInstanceMethod)
         AnnotatedNodeUtils.markAsGenerated(classNode, getEntityInstanceMethod)
         staticCompilationVisitor.visitMethod(getEntityInstanceMethod)
 
-
         // add method: EntityEntry $$_hibernate_getEntityEntry()
         def getEntityEntryMethod = new MethodNode(
                 '$$_hibernate_getEntityEntry',
@@ -175,14 +195,14 @@ class HibernateEntityTransformation implements ASTTransformation, CompilationUni
         staticCompilationVisitor.visitMethod(getEntityEntryMethod)
 
         // add method: void $$_hibernate_setEntityEntry(EntityEntry entityEntry)
-        def entityEntryParam = param(entityEntryClassNode, "entityEntry")
+        def entityEntryParam = param(entityEntryClassNode, 'entityEntry')
         def setEntityEntryMethod = new MethodNode(
                 '$$_hibernate_setEntityEntry',
                 Modifier.PUBLIC,
                 ClassHelper.VOID_TYPE,
                 params(entityEntryParam),
                 null,
-                assignS( varX(entityEntryHolderField), varX(entityEntryParam) )
+                assignS(varX(entityEntryHolderField), varX(entityEntryParam))
         )
         classNode.addMethod(setEntityEntryMethod)
         AnnotatedNodeUtils.markAsGenerated(classNode, setEntityEntryMethod)
@@ -215,28 +235,28 @@ class HibernateEntityTransformation implements ASTTransformation, CompilationUni
         staticCompilationVisitor.visitMethod(getNextManagedEntityMethod)
 
         // add method: void $$_hibernate_setPreviousManagedEntity(ManagedEntity previous)
-        def previousParam = param(managedEntityClassNode, "previous")
+        def previousParam = param(managedEntityClassNode, 'previous')
         def setPreviousManagedEntityMethod = new MethodNode(
                 '$$_hibernate_setPreviousManagedEntity',
                 Modifier.PUBLIC,
                 ClassHelper.VOID_TYPE,
                 params(previousParam),
                 null,
-                assignS( varX(previousManagedEntityField), varX(previousParam) )
+                assignS(varX(previousManagedEntityField), varX(previousParam))
         )
         classNode.addMethod(setPreviousManagedEntityMethod)
         AnnotatedNodeUtils.markAsGenerated(classNode, setPreviousManagedEntityMethod)
         staticCompilationVisitor.visitMethod(setPreviousManagedEntityMethod)
 
         // add method: void $$_hibernate_setNextManagedEntity(ManagedEntity next)
-        def nextParam = param(managedEntityClassNode, "next")
+        def nextParam = param(managedEntityClassNode, 'next')
         def setNextManagedEntityMethod = new MethodNode(
                 '$$_hibernate_setNextManagedEntity',
                 Modifier.PUBLIC,
                 ClassHelper.VOID_TYPE,
                 params(nextParam),
                 null,
-                assignS( varX(nextManagedEntityField), varX(nextParam) )
+                assignS(varX(nextManagedEntityField), varX(nextParam))
         )
         classNode.addMethod(setNextManagedEntityMethod)
         AnnotatedNodeUtils.markAsGenerated(classNode, setNextManagedEntityMethod)
@@ -256,14 +276,14 @@ class HibernateEntityTransformation implements ASTTransformation, CompilationUni
         staticCompilationVisitor.visitMethod(getInstanceIdMethod)
 
         // add method: void $$_hibernate_setInstanceId(int instanceId)
-        def instanceIdParam = param(ClassHelper.int_TYPE, "instanceId")
+        def instanceIdParam = param(ClassHelper.int_TYPE, 'instanceId')
         def setInstanceIdMethod = new MethodNode(
                 '$$_hibernate_setInstanceId',
                 Modifier.PUBLIC,
                 ClassHelper.VOID_TYPE,
                 params(instanceIdParam),
                 null,
-                assignS( varX(instanceIdField), varX(instanceIdParam) )
+                assignS(varX(instanceIdField), varX(instanceIdParam))
         )
         classNode.addMethod(setInstanceIdMethod)
         AnnotatedNodeUtils.markAsGenerated(classNode, setInstanceIdMethod)
@@ -303,9 +323,9 @@ class HibernateEntityTransformation implements ASTTransformation, CompilationUni
         staticCompilationVisitor.visitMethod(useTrackerSetter)
 
         List<MethodNode> allMethods = classNode.getMethods()
-        for(MethodNode methodNode in allMethods) {
-            if(methodNode.getAnnotations(ClassHelper.make(DirtyCheckedProperty))) {
-                if(AstUtils.isGetter(methodNode)) {
+        for (MethodNode methodNode in allMethods) {
+            if (methodNode.getAnnotations(ClassHelper.make(DirtyCheckedProperty))) {
+                if (AstUtils.isGetter(methodNode)) {
                     def codeVisitor = new ClassCodeVisitorSupport() {
                         @Override
                         protected SourceUnit getSourceUnit() {
@@ -314,14 +334,14 @@ class HibernateEntityTransformation implements ASTTransformation, CompilationUni
 
                         @Override
                         void visitReturnStatement(ReturnStatement statement) {
-                            ReturnStatement rs = (ReturnStatement)statement
+                            ReturnStatement rs = (ReturnStatement) statement
                             def i = varX(interceptorField)
                             def propertyName = NameUtils.getPropertyNameForGetterOrSetter(methodNode.getName())
 
                             def returnType = methodNode.getReturnType()
                             final boolean isPrimitive = ClassHelper.isPrimitiveType(returnType)
-                            String readMethodName = isPrimitive ? "read${NameUtils.capitalize(returnType.getName())}" : "readObject"
-                            def readObjectCall = callX(i, readMethodName, args(varX("this"), constX(propertyName), rs.getExpression()))
+                            String readMethodName = isPrimitive ? "read${NameUtils.capitalize(returnType.getName())}" : 'readObject'
+                            def readObjectCall = callX(i, readMethodName, args(varX('this'), constX(propertyName), rs.getExpression()))
                             def ternaryExpr = ternaryX(
                                     equalsNullX(varX(interceptorField)),
                                     rs.getExpression(),
@@ -336,21 +356,21 @@ class HibernateEntityTransformation implements ASTTransformation, CompilationUni
                 }
                 else {
                     Statement code = methodNode.code
-                    if(code instanceof BlockStatement) {
-                        BlockStatement bs = (BlockStatement)code
+                    if (code instanceof BlockStatement) {
+                        BlockStatement bs = (BlockStatement) code
                         Parameter parameter = methodNode.getParameters()[0]
                         ClassNode parameterType = parameter.type
                         final boolean isPrimitive = ClassHelper.isPrimitiveType(parameterType)
-                        String writeMethodName = isPrimitive ? "write${NameUtils.capitalize(parameterType.getName())}" : "writeObject"
+                        String writeMethodName = isPrimitive ? "write${NameUtils.capitalize(parameterType.getName())}" : 'writeObject'
                         String propertyName = NameUtils.getPropertyNameForGetterOrSetter(methodNode.getName())
                         def interceptorFieldExpr = fieldX(interceptorField)
-                        def ifStatement = ifS( neX(interceptorFieldExpr, constX(null) ),
+                        def ifStatement = ifS(neX(interceptorFieldExpr, constX(null)),
                             assignS(
                                 varX(parameter),
-                                callX( interceptorFieldExpr, writeMethodName, args( varX("this"), constX(propertyName), propX(varX("this"), propertyName), varX(parameter)))
+                                callX(interceptorFieldExpr, writeMethodName, args(varX('this'), constX(propertyName), propX(varX('this'), propertyName), varX(parameter)))
                             )
                         )
-                        staticCompilationVisitor.visitIfElse((IfStatement)ifStatement)
+                        staticCompilationVisitor.visitIfElse((IfStatement) ifStatement)
                         bs.getStatements().add(0, ifStatement)
                     }
                 }
@@ -360,4 +380,4 @@ class HibernateEntityTransformation implements ASTTransformation, CompilationUni
 
         classNode.putNodeMetaData(AstUtils.TRANSFORM_APPLIED_MARKER, APPLIED_MARKER)
     }
-}
\ No newline at end of file
+}


(grails-core) 15/34: hibernate7: cleanup HibernateHqlQuery

Posted by bo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

borinquenkid pushed a commit to branch 8.0.x-hibernate7-dev
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit 845862793a2048cbdab9d206266732cfcd90a963
Author: Walter Duque de Estrada <wb...@mac.com>
AuthorDate: Fri Mar 6 13:39:09 2026 -0600

    hibernate7: cleanup HibernateHqlQuery
---
 .../orm/hibernate/HibernateGormStaticApi.groovy    |  3 +-
 .../orm/hibernate/query/HibernateHqlQuery.java     | 90 +++++++++++-----------
 .../hibernate/query/HibernateHqlQuerySpec.groovy   |  2 +-
 3 files changed, 47 insertions(+), 48 deletions(-)

diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy
index d6cad39943..81fd409907 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy
@@ -397,7 +397,8 @@ class HibernateGormStaticApi<D> extends GormStaticApi<D> {
                 ctx,
                 args,
                 positionalParams,
-                getHibernateTemplate()
+                getHibernateTemplate(),
+                conversionService
         )
     }
 
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateHqlQuery.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateHqlQuery.java
index 116715fa02..b7120a501f 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateHqlQuery.java
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateHqlQuery.java
@@ -137,14 +137,15 @@ public class HibernateHqlQuery extends Query {
    * the prepared {@link HqlQueryContext}, then applies settings and parameters.
    */
   @SuppressWarnings({"unchecked", "rawtypes"})
-  public static HibernateHqlQuery createHqlQuery(
+  private static HibernateHqlQuery create(
       HibernateDatastore dataStore,
       SessionFactory sessionFactory,
       PersistentEntity entity,
       HqlQueryContext ctx,
       Map args,
       Collection positionalParams,
-      GrailsHibernateTemplate template) {
+      GrailsHibernateTemplate template,
+      ConversionService conversionService) {
     HibernateHqlQuery hqlQuery =
         template.execute(session -> buildQuery(session, dataStore, sessionFactory, entity, ctx));
     var selectQuery = hqlQuery.selectQuery();
@@ -152,7 +153,8 @@ public class HibernateHqlQuery extends Query {
       template.applySettings(selectQuery);
     }
     hqlQuery.populateQuerySettings(
-        MapUtils.isNotEmpty(args) ? new HashMap<>(args) : Collections.emptyMap());
+        MapUtils.isNotEmpty(args) ? new HashMap<>(args) : Collections.emptyMap(),
+        conversionService);
     if (MapUtils.isNotEmpty(ctx.namedParams())) {
       hqlQuery.populateQueryWithNamedArguments(ctx.namedParams());
     } else if (CollectionUtils.isNotEmpty(positionalParams)) {
@@ -161,6 +163,45 @@ public class HibernateHqlQuery extends Query {
     return hqlQuery;
   }
 
+  @SuppressWarnings({"unchecked", "rawtypes"})
+  public static HibernateHqlQuery createHqlQuery(
+      HibernateDatastore dataStore,
+      SessionFactory sessionFactory,
+      PersistentEntity entity,
+      HqlQueryContext ctx,
+      Map args,
+      Collection positionalParams,
+      GrailsHibernateTemplate template,
+      ConversionService conversionService) {
+    return create(dataStore, sessionFactory, entity, ctx, args, positionalParams, template, conversionService);
+  }
+
+  /**
+   * Factory for {@code list(Map params)} — builds HQL with ORDER BY / JOIN FETCH from the params
+   * map, applies pagination settings, and wraps in a ready-to-execute {@link HibernateHqlQuery}.
+   */
+  @SuppressWarnings({"unchecked", "rawtypes"})
+  public static HibernateHqlQuery forList(
+      HibernateDatastore dataStore,
+      SessionFactory sessionFactory,
+      PersistentEntity entity,
+      Map<?, ?> params,
+      GrailsHibernateTemplate template,
+      ConversionService conversionService) {
+    HqlListQueryBuilder builder = new HqlListQueryBuilder(entity, params);
+    String hql = builder.buildListHql();
+    HqlQueryContext ctx = HqlQueryContext.prepare(hql, false, false, Collections.emptyMap(), entity);
+    Map<String, Object> mutableParams = params instanceof Map ? new HashMap<>((Map<String, Object>) params) : Collections.emptyMap();
+    return create(dataStore, sessionFactory, entity, ctx, mutableParams, Collections.emptyList(), template, conversionService);
+  }
+
+  /**
+   * Builds the count HQL string used by {@link PagedResultList} when paging is requested.
+   */
+  public static String buildCountHql(PersistentEntity entity) {
+    return new HqlListQueryBuilder(entity, Collections.emptyMap()).buildCountHql();
+  }
+
   // ─── Query configuration ─────────────────────────────────────────────────
 
   public void setFlushMode(FlushMode flushMode) {
@@ -193,49 +234,6 @@ public class HibernateHqlQuery extends Query {
     }
   }
 
-  /** @deprecated Use {@link #populateQuerySettings(Map, ConversionService)} */
-  @Deprecated
-  public void populateQuerySettings(Map<?, ?> args) {
-    ifPresent(args, HibernateQueryArgument.MAX.value(), v -> delegate.setMaxResults(toInt(v)));
-    ifPresent(args, HibernateQueryArgument.OFFSET.value(), v -> delegate.setFirstResult(toInt(v)));
-    ifPresent(args, HibernateQueryArgument.CACHE.value(), v -> delegate.setCacheable(toBool(v)));
-    ifPresent(args, HibernateQueryArgument.FETCH_SIZE.value(), v -> delegate.setFetchSize(toInt(v)));
-    ifPresent(args, HibernateQueryArgument.TIMEOUT.value(), v -> delegate.setTimeout(toInt(v)));
-    ifPresent(args, HibernateQueryArgument.READ_ONLY.value(), v -> delegate.setReadOnly(toBool(v)));
-    ifPresent(args, HibernateQueryArgument.FLUSH_MODE.value(), v -> delegate.setQueryFlushMode(convertQueryFlushMode(v)));
-  }
-
-  /**
-   * Factory for {@code list(Map params)} — builds HQL with ORDER BY / JOIN FETCH from the params
-   * map, applies pagination settings, and wraps in a ready-to-execute {@link HibernateHqlQuery}.
-   */
-  @SuppressWarnings({"unchecked", "rawtypes"})
-  public static HibernateHqlQuery forList(
-      HibernateDatastore dataStore,
-      SessionFactory sessionFactory,
-      PersistentEntity entity,
-      Map<?, ?> params,
-      GrailsHibernateTemplate template,
-      ConversionService conversionService) {
-    HqlListQueryBuilder builder = new HqlListQueryBuilder(entity, params);
-    String hql = builder.buildListHql();
-    HqlQueryContext ctx = HqlQueryContext.prepare(hql, false, false, Collections.emptyMap(), entity);
-    HibernateHqlQuery hqlQuery =
-        template.execute(session -> buildQuery(session, dataStore, sessionFactory, entity, ctx));
-    org.hibernate.query.Query<?> q = hqlQuery.selectQuery();
-    if (q != null) template.applySettings(q);
-    Map<String, Object> mutableParams = params instanceof Map ? new HashMap<>((Map<String, Object>) params) : Collections.emptyMap();
-    hqlQuery.populateQuerySettings(mutableParams, conversionService);
-    return hqlQuery;
-  }
-
-  /**
-   * Builds the count HQL string used by {@link PagedResultList} when paging is requested.
-   */
-  public static String buildCountHql(PersistentEntity entity) {
-    return new HqlListQueryBuilder(entity, Collections.emptyMap()).buildCountHql();
-  }
-
   public static QueryFlushMode convertQueryFlushMode(Object object) {
     FlushMode fm = convertFlushMode(object);
     if (fm == null) return QueryFlushMode.DEFAULT;
diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/query/HibernateHqlQuerySpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/query/HibernateHqlQuerySpec.groovy
index ab22d31c14..f992d69659 100644
--- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/query/HibernateHqlQuerySpec.groovy
+++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/query/HibernateHqlQuerySpec.groovy
@@ -23,7 +23,7 @@ class HibernateHqlQuerySpec extends HibernateGormDatastoreSpec {
         def ctx = HqlQueryContext.prepare(hql, false, isUpdate, namedParams, entity)
         def session = sessionFactory.currentSession
         def hqlQuery = HibernateHqlQuery.buildQuery(session, datastore, sessionFactory, entity, ctx)
-        if (args) hqlQuery.populateQuerySettings(new HashMap(args))
+        if (args) hqlQuery.populateQuerySettings(new HashMap(args), mappingContext.conversionService)
         if (ctx.namedParams()) hqlQuery.populateQueryWithNamedArguments(new HashMap(ctx.namedParams()))
         else if (positionalParams) hqlQuery.populateQueryWithIndexedArguments(positionalParams)
         hqlQuery


(grails-core) 08/34: hibernate7: cleanup update MapSecondPassBinderSpec

Posted by bo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

borinquenkid pushed a commit to branch 8.0.x-hibernate7-dev
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit 958812ad8d5e8292ebe772a6e6a68bcccdbf9e7a
Author: Walter Duque de Estrada <wb...@mac.com>
AuthorDate: Thu Mar 5 21:49:24 2026 -0600

    hibernate7: cleanup update MapSecondPassBinderSpec
---
 .../secondpass/MapSecondPassBinderSpec.groovy      | 100 ++++++++++++++++++---
 1 file changed, 87 insertions(+), 13 deletions(-)

diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/MapSecondPassBinderSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/MapSecondPassBinderSpec.groovy
index 8e9c9e65f6..17c37ff7d5 100644
--- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/MapSecondPassBinderSpec.groovy
+++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/MapSecondPassBinderSpec.groovy
@@ -3,6 +3,7 @@ package org.grails.orm.hibernate.cfg.domainbinding.secondpass
 import grails.gorm.specs.HibernateGormDatastoreSpec
 import org.grails.orm.hibernate.cfg.domainbinding.hibernate.GrailsHibernatePersistentEntity
 import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernatePersistentProperty
+import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateToManyProperty
 import org.hibernate.mapping.OneToMany
 import org.hibernate.mapping.RootClass
 import org.hibernate.boot.spi.MetadataBuildingContext
@@ -154,31 +155,104 @@ class MapSecondPassBinderSpec extends HibernateGormDatastoreSpec {
         manager.addAllDomainClasses([
             org.apache.grails.data.testing.tck.domains.Pet,
             org.apache.grails.data.testing.tck.domains.Person,
-            org.apache.grails.data.testing.tck.domains.PetType
+            org.apache.grails.data.testing.tck.domains.PetType,
+            MSBAuthor,
+            MSBBook
         ])
     }
 
-    void "Test bind collection"() {
+    void "Test bind map"() {
         given:
         def binder = getGrailsDomainBinder()
-        def collectionBinder = getBinders(binder).collectionBinder
         def collector = getCollector()
+        def metadataBuildingContext = binder.getMetadataBuildingContext()
+        def namingStrategy = binder.getNamingStrategy()
+        def binders = getBinders(binder)
+        def collectionBinder = binders.collectionBinder
+        def mapBinder = collectionBinder.mapSecondPassBinder
+
+        def authorEntity = getPersistentEntity(MSBAuthor) as GrailsHibernatePersistentEntity
+        def booksProp = authorEntity.getPropertyByName("books") as HibernateToManyProperty
+
+        def rootClass = new RootClass(metadataBuildingContext)
+        rootClass.setEntityName(authorEntity.name)
+        rootClass.setTable(collector.addTable(null, null, "MSB_AUTHOR", null, false, metadataBuildingContext))
+        collector.addEntityBinding(rootClass)
+
+        def map = new org.hibernate.mapping.Map(metadataBuildingContext, rootClass)
+        map.setRole("${authorEntity.name}.books".toString())
+        map.setCollectionTable(rootClass.getTable())
+
+        when:
+        mapBinder.bindMapSecondPass(booksProp, collector, [:], map)
+
+        then:
+        noExceptionThrown()
+        map.index != null
+        map.index.isTypeSpecified()
+        map.element != null
+        !map.inverse
+    }
+
+    void "Test bind map with custom index column"() {
+        given:
+        def binder = getGrailsDomainBinder()
+        def collector = getCollector()
+        def metadataBuildingContext = binder.getMetadataBuildingContext()
+        def namingStrategy = binder.getNamingStrategy()
+        def binders = getBinders(binder)
+        def collectionBinder = binders.collectionBinder
+        def mapBinder = collectionBinder.mapSecondPassBinder
 
-        def personEntity = getPersistentEntity(org.apache.grails.data.testing.tck.domains.Person) as GrailsHibernatePersistentEntity
-        def petEntity = getPersistentEntity(org.apache.grails.data.testing.tck.domains.Pet) as GrailsHibernatePersistentEntity
+        def authorEntity = getPersistentEntity(MSBAuthor) as GrailsHibernatePersistentEntity
+        def booksProp = authorEntity.getPropertyByName("books") as HibernateToManyProperty
 
-        def rootClass = new RootClass(binder.getMetadataBuildingContext())
-        rootClass.setEntityName(personEntity.name)
-        rootClass.setTable(collector.addTable(null, null, "PERSON", null, false, binder.getMetadataBuildingContext()))
+        def rootClass = new RootClass(metadataBuildingContext)
+        rootClass.setEntityName(authorEntity.name)
+        rootClass.setTable(collector.addTable(null, null, "MSB_AUTHOR", null, false, metadataBuildingContext))
+        collector.addEntityBinding(rootClass)
+
+        def bookRootClass = new RootClass(metadataBuildingContext)
+        bookRootClass.setEntityName(MSBBook.name)
+        bookRootClass.setTable(collector.addTable(null, null, "MSB_BOOK", null, false, metadataBuildingContext))
+        collector.addEntityBinding(bookRootClass)
+
+        def persistentClasses = [
+            (authorEntity.name): rootClass,
+            (MSBBook.name): bookRootClass
+        ]
 
-        def petsProp = personEntity.getPropertyByName("pets") as HibernatePersistentProperty
+        def map = new org.hibernate.mapping.Map(metadataBuildingContext, rootClass)
+        map.setRole("${authorEntity.name}.books".toString())
+        map.setCollectionTable(rootClass.getTable())
+        
+        def element = new org.hibernate.mapping.ManyToOne(metadataBuildingContext, map.getCollectionTable())
+        element.setReferencedEntityName(MSBBook.name)
+        map.setElement(element)
 
         when:
-        def collection = collectionBinder.bindCollection(petsProp, rootClass, "")
+        mapBinder.bindMapSecondPass(booksProp, collector, persistentClasses, map)
 
         then:
-        collection.role == "${personEntity.name}.pets".toString()
-        collection.element instanceof OneToMany
-        (collection.element as OneToMany).referencedEntityName == petEntity.name
+        noExceptionThrown()
+        map.index != null
+        map.index.isTypeSpecified()
+        map.index.getColumnIterator().next().name == "BOOK_TITLE"
     }
 }
+
+@grails.gorm.annotation.Entity
+class MSBAuthor {
+    Long id
+    Map<String, MSBBook> books
+    static hasMany = [books: MSBBook]
+    static mapping = {
+        books index: 'BOOK_TITLE'
+    }
+}
+
+@grails.gorm.annotation.Entity
+class MSBBook {
+    Long id
+    String title
+}


(grails-core) 30/34: hibernate7: - Fix alias resolution architecture: - Fix scroll(): - Fix countDistinct/groupProperty - Add eq(Map, String, Object) overload for Groovy named-params form,

Posted by bo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

borinquenkid pushed a commit to branch 8.0.x-hibernate7-dev
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit a33dcf010d19f0fa44ecf1bd1254b1b39c746954
Author: Walter Duque de Estrada <wb...@mac.com>
AuthorDate: Sat Mar 7 22:44:23 2026 -0600

    hibernate7:
    - Fix alias resolution architecture:
    - Fix scroll():
    - Fix countDistinct/groupProperty
    - Add eq(Map, String, Object) overload for Groovy named-params form,
---
 .../groovy/grails/orm/CriteriaMethodInvoker.java   |  51 ++++----
 .../grails/orm/HibernateCriteriaBuilder.java       | 142 ++++++++-------------
 .../orm/hibernate/HibernateGormStaticApi.groovy    |   4 +-
 .../grails/orm/hibernate/query/HibernateQuery.java |  82 ++++++------
 .../grails/orm/CriteriaMethodInvokerSpec.groovy    |  26 +---
 .../grails/orm/HibernateCriteriaBuilderSpec.groovy |  21 +++
 6 files changed, 144 insertions(+), 182 deletions(-)

diff --git a/grails-data-hibernate7/core/src/main/groovy/grails/orm/CriteriaMethodInvoker.java b/grails-data-hibernate7/core/src/main/groovy/grails/orm/CriteriaMethodInvoker.java
index 9dae907053..dcfd3c8d3f 100644
--- a/grails-data-hibernate7/core/src/main/groovy/grails/orm/CriteriaMethodInvoker.java
+++ b/grails-data-hibernate7/core/src/main/groovy/grails/orm/CriteriaMethodInvoker.java
@@ -123,6 +123,8 @@ public class CriteriaMethodInvoker {
           hibernateQuery.order(order);
         }
         result = new PagedResultList<>(hibernateQuery);
+      } else if (builder.isScroll()) {
+        result = hibernateQuery.scroll();
       } else {
         result = hibernateQuery.list();
       }
@@ -224,13 +226,13 @@ public class CriteriaMethodInvoker {
           final String value = (String) args[0];
           switch (method) {
             case IS_NULL ->
-                builder.getHibernateQuery().isNull(builder.calculatePropertyName(value));
+                builder.getHibernateQuery().isNull(value);
             case IS_NOT_NULL ->
-                builder.getHibernateQuery().isNotNull(builder.calculatePropertyName(value));
+                builder.getHibernateQuery().isNotNull(value);
             case IS_EMPTY ->
-                builder.getHibernateQuery().isEmpty(builder.calculatePropertyName(value));
+                builder.getHibernateQuery().isEmpty(value);
             case IS_NOT_EMPTY ->
-                builder.getHibernateQuery().isNotEmpty(builder.calculatePropertyName(value));
+                builder.getHibernateQuery().isNotEmpty(value);
           }
           return name;
       }
@@ -246,54 +248,53 @@ public class CriteriaMethodInvoker {
 
     switch (method) {
       case RLIKE:
-        return builder.rlike(builder.calculatePropertyName(propertyName), args[1]);
+        return builder.rlike(propertyName, args[1]);
       case BETWEEN:
         if (args.length >= 3) {
-          return builder.between(builder.calculatePropertyName(propertyName), args[1], args[2]);
+          return builder.between(propertyName, args[1], args[2]);
         }
         break;
       case EQUALS:
         if (args.length == 3 && args[2] instanceof Map) {
-          return builder.eq(builder.calculatePropertyName(propertyName), args[1], (Map) args[2]);
+          return builder.eq(propertyName, args[1], (Map) args[2]);
         }
-        return builder.eq(builder.calculatePropertyName(propertyName), args[1]);
+        return builder.eq(propertyName, args[1]);
       case EQUALS_PROPERTY:
-        return builder.eqProperty(builder.calculatePropertyName(propertyName), args[1].toString());
+        return builder.eqProperty(propertyName, args[1].toString());
       case GREATER_THAN:
-        return builder.gt(builder.calculatePropertyName(propertyName), args[1]);
+        return builder.gt(propertyName, args[1]);
       case GREATER_THAN_PROPERTY:
-        return builder.gtProperty(builder.calculatePropertyName(propertyName), args[1].toString());
+        return builder.gtProperty(propertyName, args[1].toString());
       case GREATER_THAN_OR_EQUAL:
-        return builder.ge(builder.calculatePropertyName(propertyName), args[1]);
+        return builder.ge(propertyName, args[1]);
       case GREATER_THAN_OR_EQUAL_PROPERTY:
-        return builder.geProperty(builder.calculatePropertyName(propertyName), args[1].toString());
+        return builder.geProperty(propertyName, args[1].toString());
       case ILIKE:
-        return builder.ilike(builder.calculatePropertyName(propertyName), args[1]);
+        return builder.ilike(propertyName, args[1]);
       case IN:
         if (args[1] instanceof Collection) {
-          return builder.in(builder.calculatePropertyName(propertyName), (Collection) args[1]);
+          return builder.in(propertyName, (Collection) args[1]);
         } else if (args[1] instanceof Object[]) {
-          return builder.in(builder.calculatePropertyName(propertyName), (Object[]) args[1]);
+          return builder.in(propertyName, (Object[]) args[1]);
         }
         break;
       case LESS_THAN:
-        return builder.lt(builder.calculatePropertyName(propertyName), args[1]);
+        return builder.lt(propertyName, args[1]);
       case LESS_THAN_PROPERTY:
-        return builder.ltProperty(builder.calculatePropertyName(propertyName), args[1].toString());
+        return builder.ltProperty(propertyName, args[1].toString());
       case LESS_THAN_OR_EQUAL:
-        return builder.le(builder.calculatePropertyName(propertyName), args[1]);
+        return builder.le(propertyName, args[1]);
       case LESS_THAN_OR_EQUAL_PROPERTY:
-        return builder.leProperty(builder.calculatePropertyName(propertyName), args[1].toString());
+        return builder.leProperty(propertyName, args[1].toString());
       case LIKE:
-        return builder.like(builder.calculatePropertyName(propertyName), args[1]);
+        return builder.like(propertyName, args[1]);
       case NOT_EQUAL:
-        return builder.ne(builder.calculatePropertyName(propertyName), args[1]);
+        return builder.ne(propertyName, args[1]);
       case NOT_EQUAL_PROPERTY:
-        return builder.neProperty(builder.calculatePropertyName(propertyName), args[1].toString());
+        return builder.neProperty(propertyName, args[1].toString());
       case SIZE_EQUALS:
         if (args[1] instanceof Number) {
-          return builder.sizeEq(
-              builder.calculatePropertyName(propertyName), ((Number) args[1]).intValue());
+          return builder.sizeEq(propertyName, ((Number) args[1]).intValue());
         }
         break;
     }
diff --git a/grails-data-hibernate7/core/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java b/grails-data-hibernate7/core/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java
index f157479d7c..f381729239 100644
--- a/grails-data-hibernate7/core/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java
+++ b/grails-data-hibernate7/core/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java
@@ -9,12 +9,11 @@
  *
  *    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.
+ *  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 grails.orm;
 
@@ -26,10 +25,8 @@ import groovy.lang.GroovyObjectSupport;
 import groovy.util.logging.Slf4j;
 import jakarta.persistence.criteria.CriteriaQuery;
 import jakarta.persistence.criteria.JoinType;
-import jakarta.persistence.criteria.Root;
 import jakarta.persistence.metamodel.Attribute;
 import jakarta.persistence.metamodel.PluralAttribute;
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
@@ -46,11 +43,7 @@ import org.grails.orm.hibernate.HibernateSession;
 import org.grails.orm.hibernate.GrailsHibernateTemplate;
 import org.grails.orm.hibernate.query.HibernateQuery;
 import org.hibernate.FetchMode;
-import org.hibernate.Session;
 import org.hibernate.SessionFactory;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.core.convert.ConversionService;
 
 /**
  * Implements the GORM criteria DSL for Hibernate 7+. The builder exposes a Groovy-closure DSL that
@@ -101,36 +94,28 @@ import org.springframework.core.convert.ConversionService;
  */
 @Slf4j
 @SuppressWarnings("PMD.AvoidDuplicateLiterals")
-public class HibernateCriteriaBuilder extends GroovyObjectSupport
-    implements BuildableCriteria, ProjectionList {
+public class HibernateCriteriaBuilder extends GroovyObjectSupport implements BuildableCriteria, ProjectionList {
   /*
    * Define constants which may be used inside of criteria queries
    * to refer to standard Hibernate Type instances.
    */
 
-  private static final Logger log = LoggerFactory.getLogger(HibernateCriteriaBuilder.class);
-  protected SessionFactory sessionFactory;
-  protected Session hibernateSession;
-  protected Class<?> targetClass;
-  protected CriteriaQuery criteriaQuery;
-  protected boolean uniqueResult = false;
-  protected boolean participate;
+  private final SessionFactory sessionFactory;
+  private Class<?> targetClass;
+  private CriteriaQuery<?> criteriaQuery;
+  private boolean uniqueResult = false;
+  private boolean participate;
 
   @SuppressWarnings("PMD.AvoidFieldNameMatchingMethodName")
-  protected boolean scroll;
+  private boolean scroll;
 
   @SuppressWarnings("PMD.AvoidFieldNameMatchingMethodName")
-  protected boolean count;
-
-  protected List<String> aliasStack = new ArrayList<String>();
-  protected static final String ALIAS = "_alias";
-  protected boolean paginationEnabledList = false;
-  protected ConversionService conversionService;
-  protected int defaultFlushMode;
-  protected HibernateDatastore datastore;
-  protected org.hibernate.query.criteria.HibernateCriteriaBuilder cb;
-  protected Root root;
-  protected HibernateQuery hibernateQuery;
+  private boolean count;
+
+  private boolean paginationEnabledList = false;
+  private int defaultFlushMode;
+  private final org.hibernate.query.criteria.HibernateCriteriaBuilder cb;
+  private final HibernateQuery hibernateQuery;
   private boolean shouldLock;
   private boolean shouldCache;
 
@@ -138,7 +123,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport
   private boolean readOnly;
 
   @SuppressWarnings("PMD.AvoidFieldNameMatchingMethodName")
-  protected boolean distinct = false;
+  private boolean distinct = false;
 
   @SuppressWarnings("rawtypes")
   public HibernateCriteriaBuilder(
@@ -155,16 +140,12 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport
   }
 
   public final void setDatastore(HibernateDatastore datastore) {
-    this.datastore = datastore;
     if (MultiTenant.class.isAssignableFrom(targetClass)
         && datastore.getMultiTenancyMode() == MultiTenancySettings.MultiTenancyMode.DISCRIMINATOR) {
       datastore.enableMultiTenancyFilter();
     }
   }
 
-  public void setConversionService(ConversionService conversionService) {
-    this.conversionService = conversionService;
-  }
 
   /**
    * A projection that selects a property name
@@ -259,30 +240,11 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport
     return this;
   }
 
-  /**
-   * Calculates the property name including any alias paths
-   *
-   * @param propertyName The property name
-   * @return The calculated property name
-   */
-  protected String calculatePropertyName(String propertyName) {
-    return propertyName;
-  }
-
-  private String getLastAlias() {
-    if (aliasStack.size() > 0) {
-      return aliasStack.get(aliasStack.size() - 1).toString();
-    }
-    return null;
-  }
 
   public Class<?> getTargetClass() {
     return targetClass;
   }
 
-  protected DetachedCriteria convertToHibernateCriteria(QueryableCriteria<?> queryableCriteria) {
-    return null;
-  }
 
   /**
    * Adds a projection that allows the criteria to return the property count
@@ -619,7 +581,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport
 
   @Override
   public Criteria gtSome(String propertyName, Closure<?> propertyValue) {
-    return gtSome(propertyName, new grails.gorm.DetachedCriteria(targetClass).build(propertyValue));
+    return gtSome(propertyName, new DetachedCriteria<>(targetClass).build(propertyValue));
   }
 
   @Override
@@ -630,7 +592,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport
 
   @Override
   public Criteria geSome(String propertyName, Closure<?> propertyValue) {
-    return geSome(propertyName, new grails.gorm.DetachedCriteria(targetClass).build(propertyValue));
+    return geSome(propertyName, new DetachedCriteria<>(targetClass).build(propertyValue));
   }
 
   @Override
@@ -641,7 +603,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport
 
   @Override
   public Criteria ltSome(String propertyName, Closure<?> propertyValue) {
-    return ltSome(propertyName, new grails.gorm.DetachedCriteria(targetClass).build(propertyValue));
+    return ltSome(propertyName, new DetachedCriteria<>(targetClass).build(propertyValue));
   }
 
   @Override
@@ -652,7 +614,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport
 
   @Override
   public Criteria leSome(String propertyName, Closure<?> propertyValue) {
-    return leSome(propertyName, new grails.gorm.DetachedCriteria(targetClass).build(propertyValue));
+    return leSome(propertyName, new DetachedCriteria<>(targetClass).build(propertyValue));
   }
 
   @Override
@@ -668,12 +630,12 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport
 
   @Override
   public Criteria in(String propertyName, Closure<?> subquery) {
-    return inList(propertyName, new DetachedCriteria(targetClass).build(subquery));
+    return inList(propertyName, new DetachedCriteria<>(targetClass).build(subquery));
   }
 
   @Override
   public Criteria inList(String propertyName, Closure<?> subquery) {
-    return inList(propertyName, new DetachedCriteria(targetClass).build(subquery));
+    return inList(propertyName, new DetachedCriteria<>(targetClass).build(subquery));
   }
 
   @Override
@@ -684,7 +646,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport
 
   @Override
   public Criteria notIn(String propertyName, Closure<?> subquery) {
-    return notIn(propertyName, new grails.gorm.DetachedCriteria(targetClass).build(subquery));
+    return notIn(propertyName, new DetachedCriteria<>(targetClass).build(subquery));
   }
 
   /**
@@ -850,20 +812,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport
     return eq("id", o);
   }
 
-  /**
-   * Groovy moves the map to the first parameter if using the idiomatic form, e.g. <code>
-   * eq 'firstName', 'Fred', ignoreCase: true</code>.
-   *
-   * @param params optional map with customization parameters; currently only 'ignoreCase' is
-   *     supported.
-   * @param propertyName
-   * @param propertyValue
-   * @return A Criterion instance
-   */
-  @SuppressWarnings("rawtypes")
-  public Criteria eq(Map params, String propertyName, Object propertyValue) {
-    return eq(propertyName, propertyValue, params);
-  }
+
 
   /**
    * Creates an "equals" Criterion based on the specified property name and value. Supports
@@ -886,6 +835,11 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport
     return this;
   }
 
+  @SuppressWarnings("rawtypes")
+  public Criteria eq(Map params, String propertyName, Object propertyValue) {
+    return eq(propertyName, propertyValue, params);
+  }
+
   /**
    * Creates a Criterion with from the specified property name and "like" expression
    *
@@ -1104,7 +1058,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport
 
   @Override
   public Object list(@DelegatesTo(Criteria.class) Closure c) {
-    hibernateQuery.setDetachedCriteria(new DetachedCriteria(targetClass));
+    hibernateQuery.setDetachedCriteria(new DetachedCriteria<>(targetClass));
     return invokeMethod(CriteriaMethods.LIST_CALL.getName(), new Object[] {c});
   }
 
@@ -1118,7 +1072,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport
 
   @Override
   public Object list(Map params, @DelegatesTo(Criteria.class) Closure c) {
-    hibernateQuery.setDetachedCriteria(new DetachedCriteria(targetClass));
+    hibernateQuery.setDetachedCriteria(new DetachedCriteria<>(targetClass));
     return invokeMethod(CriteriaMethods.LIST_CALL.getName(), new Object[] {params, c});
   }
 
@@ -1155,12 +1109,22 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport
     return new CriteriaMethodInvoker(this).invokeMethod(name, args);
   }
 
+  @Override
+  public Object getProperty(String propertyName) {
+    return super.getProperty(propertyName);
+  }
+
+  @Override
+  public void setProperty(String propertyName, Object newValue) {
+    super.setProperty(propertyName, newValue);
+  }
+
   /**
    * Returns the criteria instance
    *
    * @return The criteria instance
    */
-  public CriteriaQuery getInstance() {
+  public CriteriaQuery<?> getInstance() {
     return criteriaQuery;
   }
 
@@ -1193,6 +1157,10 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport
     this.scroll = scroll;
   }
 
+  public boolean isScroll() {
+    return scroll;
+  }
+
   public void setCount(boolean count) {
     this.count = count;
   }
@@ -1221,15 +1189,15 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport
     return cb;
   }
 
-  protected Class getClassForAssociationType(Attribute<?, ?> type) {
+  public Class<?> getClassForAssociationType(Attribute<?, ?> type) {
     if (type instanceof PluralAttribute) {
-      return ((PluralAttribute) type).getElementType().getJavaType();
+      return ((PluralAttribute<?,?,?>) type).getElementType().getJavaType();
     }
     return type.getJavaType();
   }
 
   /** Throws a runtime exception where necessary to ensure the session gets closed */
-  protected void throwRuntimeException(RuntimeException t) {
+  public void throwRuntimeException(RuntimeException t) {
     closeSessionFollowingException();
     throw t;
   }
@@ -1241,10 +1209,8 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport
   }
 
   /** Closes the session if it is copen */
-  protected void closeSession() {
-    if (hibernateSession != null && hibernateSession.isOpen() && !participate) {
-      hibernateSession.close();
-    }
+  public void closeSession() {
+    hibernateQuery.getSession().disconnect();
   }
 
   public int getDefaultFlushMode() {
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy
index c56a484d2f..b0ad1678cb 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy
@@ -459,9 +459,7 @@ class HibernateGormStaticApi<D> extends GormStaticApi<D> {
 
     @Override
     GrailsCriteria createCriteria() {
-        def builder = new HibernateCriteriaBuilder(persistentClass, sessionFactory, (HibernateDatastore) datastore)
-        builder.conversionService = conversionService
-        return builder
+        return new HibernateCriteriaBuilder(persistentClass, sessionFactory, (HibernateDatastore) datastore)
     }
 
     protected void firePostQueryEvent(Object result) {
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java
index 985dc3d2ae..7600503b27 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java
@@ -92,13 +92,13 @@ public class HibernateQuery extends Query {
 
   @Override
   public Query isEmpty(String property) {
-    detachedCriteria.isEmpty(property);
+    detachedCriteria.isEmpty(calculatePropertyName(property));
     return this;
   }
 
   @Override
   public Query isNotEmpty(String property) {
-    detachedCriteria.isNotEmpty(property);
+    detachedCriteria.isNotEmpty(calculatePropertyName(property));
     return this;
   }
 
@@ -109,13 +109,13 @@ public class HibernateQuery extends Query {
 
   @Override
   public Query isNull(String property) {
-    detachedCriteria.isNull(property);
+    detachedCriteria.isNull(calculatePropertyName(property));
     return this;
   }
 
   @Override
   public Query isNotNull(String property) {
-    detachedCriteria.isNotNull(property);
+    detachedCriteria.isNotNull(calculatePropertyName(property));
     return this;
   }
 
@@ -166,7 +166,7 @@ public class HibernateQuery extends Query {
 
   @Override
   public Query eq(String property, Object value) {
-    detachedCriteria.eq(property, value);
+    detachedCriteria.eq(calculatePropertyName(property), value);
     return this;
   }
 
@@ -178,7 +178,7 @@ public class HibernateQuery extends Query {
 
   @Override
   public Query gt(String property, Object value) {
-    detachedCriteria.gt(property, value);
+    detachedCriteria.gt(calculatePropertyName(property), value);
     return this;
   }
 
@@ -246,67 +246,67 @@ public class HibernateQuery extends Query {
   @Override
   public Query allEq(Map<String, Object> values) {
     values.forEach(
-        (key, value) -> detachedCriteria.eq(key, value));
+        (key, value) -> detachedCriteria.eq(calculatePropertyName(key), value));
     return this;
   }
 
   @Override
   public Query ge(String property, Object value) {
-    detachedCriteria.ge(property, value);
+    detachedCriteria.ge(calculatePropertyName(property), value);
     return this;
   }
 
   @Override
   public Query le(String property, Object value) {
-    detachedCriteria.le(property, value);
+    detachedCriteria.le(calculatePropertyName(property), value);
     return this;
   }
 
   @Override
   public Query gte(String property, Object value) {
-    detachedCriteria.gte(property, value);
+    detachedCriteria.gte(calculatePropertyName(property), value);
     return this;
   }
 
   @Override
   public Query lte(String property, Object value) {
-    detachedCriteria.lte(property, value);
+    detachedCriteria.lte(calculatePropertyName(property), value);
     return this;
   }
 
   @Override
   public Query lt(String property, Object value) {
-    detachedCriteria.lt(property, value);
+    detachedCriteria.lt(calculatePropertyName(property), value);
     return this;
   }
 
   @Override
   public Query in(String property, List values) {
-    detachedCriteria.in(property, values);
+    detachedCriteria.in(calculatePropertyName(property), values);
     return this;
   }
 
   @Override
   public Query between(String property, Object start, Object end) {
-    detachedCriteria.between(property, start, end);
+    detachedCriteria.between(calculatePropertyName(property), start, end);
     return this;
   }
 
   @Override
   public Query like(String property, String expr) {
-    detachedCriteria.like(property, expr);
+    detachedCriteria.like(calculatePropertyName(property), expr);
     return this;
   }
 
   @Override
   public Query ilike(String property, String expr) {
-    detachedCriteria.ilike(property, expr);
+    detachedCriteria.ilike(calculatePropertyName(property), expr);
     return this;
   }
 
   @Override
   public Query rlike(String property, String expr) {
-    detachedCriteria.rlike(property, expr);
+    detachedCriteria.rlike(calculatePropertyName(property), expr);
     return this;
   }
 
@@ -472,7 +472,7 @@ public class HibernateQuery extends Query {
   }
 
   public Query in(String propertyName, QueryableCriteria<?> subquery) {
-    detachedCriteria.inList(propertyName, subquery);
+    detachedCriteria.inList(calculatePropertyName(propertyName), subquery);
     return this;
   }
 
@@ -493,7 +493,7 @@ public class HibernateQuery extends Query {
   }
 
   public Query notIn(String propertyName, QueryableCriteria<?> subquery) {
-    detachedCriteria.notIn(propertyName, subquery);
+    detachedCriteria.notIn(calculatePropertyName(propertyName), subquery);
     return this;
   }
 
@@ -508,112 +508,112 @@ public class HibernateQuery extends Query {
   }
 
   public Query gtAll(String propertyName, QueryableCriteria<?> subquery) {
-    detachedCriteria.gtAll(propertyName, subquery);
+    detachedCriteria.gtAll(calculatePropertyName(propertyName), subquery);
     return this;
   }
 
   public Query geAll(String propertyName, QueryableCriteria<?> subquery) {
-    detachedCriteria.geAll(propertyName, subquery);
+    detachedCriteria.geAll(calculatePropertyName(propertyName), subquery);
     return this;
   }
 
   public Query ltAll(String propertyName, QueryableCriteria<?> subquery) {
-    detachedCriteria.ltAll(propertyName, subquery);
+    detachedCriteria.ltAll(calculatePropertyName(propertyName), subquery);
     return this;
   }
 
   public Query leAll(String propertyName, QueryableCriteria<?> subquery) {
-    detachedCriteria.leAll(propertyName, subquery);
+    detachedCriteria.leAll(calculatePropertyName(propertyName), subquery);
     return this;
   }
 
   public Query gtSome(String propertyName, QueryableCriteria<?> subquery) {
-    detachedCriteria.gtSome(propertyName, subquery);
+    detachedCriteria.gtSome(calculatePropertyName(propertyName), subquery);
     return this;
   }
 
   public Query geSome(String propertyName, QueryableCriteria<?> subquery) {
-    detachedCriteria.geSome(propertyName, subquery);
+    detachedCriteria.geSome(calculatePropertyName(propertyName), subquery);
     return this;
   }
 
   public Query ltSome(String propertyName, QueryableCriteria<?> subquery) {
-    detachedCriteria.ltSome(propertyName, subquery);
+    detachedCriteria.ltSome(calculatePropertyName(propertyName), subquery);
     return this;
   }
 
   public Query leSome(String propertyName, QueryableCriteria<?> subquery) {
-    detachedCriteria.leSome(propertyName, subquery);
+    detachedCriteria.leSome(calculatePropertyName(propertyName), subquery);
     return this;
   }
 
   public Query eqAll(String propertyName, QueryableCriteria propertyValue) {
-    detachedCriteria.eqAll(propertyName, propertyValue);
+    detachedCriteria.eqAll(calculatePropertyName(propertyName), propertyValue);
     return this;
   }
 
   public Query ne(String propertyName, Object propertyValue) {
-    detachedCriteria.ne(propertyName, propertyValue);
+    detachedCriteria.ne(calculatePropertyName(propertyName), propertyValue);
     return this;
   }
 
   public Query eqProperty(String propertyName, String otherPropertyName) {
-    detachedCriteria.eqProperty(propertyName, otherPropertyName);
+    detachedCriteria.eqProperty(calculatePropertyName(propertyName), otherPropertyName);
     return this;
   }
 
   public Query neProperty(String propertyName, String otherPropertyName) {
-    detachedCriteria.neProperty(propertyName, otherPropertyName);
+    detachedCriteria.neProperty(calculatePropertyName(propertyName), otherPropertyName);
     return this;
   }
 
   public Query gtProperty(String propertyName, String otherPropertyName) {
-    detachedCriteria.gtProperty(propertyName, otherPropertyName);
+    detachedCriteria.gtProperty(calculatePropertyName(propertyName), otherPropertyName);
     return this;
   }
 
   public Query geProperty(String propertyName, String otherPropertyName) {
-    detachedCriteria.geProperty(propertyName, otherPropertyName);
+    detachedCriteria.geProperty(calculatePropertyName(propertyName), otherPropertyName);
     return this;
   }
 
   public Query ltProperty(String propertyName, String otherPropertyName) {
-    detachedCriteria.ltProperty(propertyName, otherPropertyName);
+    detachedCriteria.ltProperty(calculatePropertyName(propertyName), otherPropertyName);
     return this;
   }
 
   public Query leProperty(String propertyName, String otherPropertyName) {
-    detachedCriteria.leProperty(propertyName, otherPropertyName);
+    detachedCriteria.leProperty(calculatePropertyName(propertyName), otherPropertyName);
     return this;
   }
 
   public Query sizeEq(String propertyName, int size) {
-    detachedCriteria.sizeEq(propertyName, size);
+    detachedCriteria.sizeEq(calculatePropertyName(propertyName), size);
     return this;
   }
 
   public Query sizeGt(String propertyName, int size) {
-    detachedCriteria.sizeGt(propertyName, size);
+    detachedCriteria.sizeGt(calculatePropertyName(propertyName), size);
     return this;
   }
 
   public Query sizeGe(String propertyName, int size) {
-    detachedCriteria.sizeGe(propertyName, size);
+    detachedCriteria.sizeGe(calculatePropertyName(propertyName), size);
     return this;
   }
 
   public Query sizeLe(String propertyName, int size) {
-    detachedCriteria.sizeLe(propertyName, size);
+    detachedCriteria.sizeLe(calculatePropertyName(propertyName), size);
     return this;
   }
 
   public Query sizeLt(String propertyName, int size) {
-    detachedCriteria.sizeLt(propertyName, size);
+    detachedCriteria.sizeLt(calculatePropertyName(propertyName), size);
     return this;
   }
 
   public Query sizeNe(String propertyName, int size) {
-    detachedCriteria.sizeNe(propertyName, size);
+    detachedCriteria.sizeNe(calculatePropertyName(propertyName), size);
     return this;
   }
 
diff --git a/grails-data-hibernate7/core/src/test/groovy/grails/orm/CriteriaMethodInvokerSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/grails/orm/CriteriaMethodInvokerSpec.groovy
index 3f9c34f5da..a0f8e7e560 100644
--- a/grails-data-hibernate7/core/src/test/groovy/grails/orm/CriteriaMethodInvokerSpec.groovy
+++ b/grails-data-hibernate7/core/src/test/groovy/grails/orm/CriteriaMethodInvokerSpec.groovy
@@ -184,7 +184,6 @@ class CriteriaMethodInvokerSpec extends Specification {
         invoker.trySimpleCriteria('isNull', CriteriaMethods.IS_NULL, ['branch'] as Object[])
 
         then:
-        1 * builder.calculatePropertyName('branch') >> 'branch'
         1 * query.isNull('branch')
     }
 
@@ -193,7 +192,6 @@ class CriteriaMethodInvokerSpec extends Specification {
         invoker.trySimpleCriteria('isNotNull', CriteriaMethods.IS_NOT_NULL, ['branch'] as Object[])
 
         then:
-        1 * builder.calculatePropertyName('branch') >> 'branch'
         1 * query.isNotNull('branch')
     }
 
@@ -202,7 +200,6 @@ class CriteriaMethodInvokerSpec extends Specification {
         invoker.trySimpleCriteria('isEmpty', CriteriaMethods.IS_EMPTY, ['transactions'] as Object[])
 
         then:
-        1 * builder.calculatePropertyName('transactions') >> 'transactions'
         1 * query.isEmpty('transactions')
     }
 
@@ -211,7 +208,6 @@ class CriteriaMethodInvokerSpec extends Specification {
         invoker.trySimpleCriteria('isNotEmpty', CriteriaMethods.IS_NOT_EMPTY, ['transactions'] as Object[])
 
         then:
-        1 * builder.calculatePropertyName('transactions') >> 'transactions'
         1 * query.isNotEmpty('transactions')
     }
 
@@ -232,7 +228,7 @@ class CriteriaMethodInvokerSpec extends Specification {
 
         then:
         result != null  // UNHANDLED sentinel object
-        0 * builder.calculatePropertyName(_)
+        0 * query.isNull(_)
     }
 
     void "trySimpleCriteria: null method returns UNHANDLED"() {
@@ -251,7 +247,6 @@ class CriteriaMethodInvokerSpec extends Specification {
         invoker.tryPropertyCriteria(CriteriaMethods.RLIKE, ['firstName', '^F.*'] as Object[])
 
         then:
-        1 * builder.calculatePropertyName('firstName') >> 'firstName'
         1 * builder.rlike('firstName', '^F.*')
     }
 
@@ -260,7 +255,6 @@ class CriteriaMethodInvokerSpec extends Specification {
         invoker.tryPropertyCriteria(CriteriaMethods.BETWEEN, ['balance', 10, 100] as Object[])
 
         then:
-        1 * builder.calculatePropertyName('balance') >> 'balance'
         1 * builder.between('balance', 10, 100)
     }
 
@@ -269,7 +263,6 @@ class CriteriaMethodInvokerSpec extends Specification {
         invoker.tryPropertyCriteria(CriteriaMethods.EQUALS, ['firstName', 'Fred'] as Object[])
 
         then:
-        1 * builder.calculatePropertyName('firstName') >> 'firstName'
         1 * builder.eq('firstName', 'Fred')
     }
 
@@ -281,7 +274,6 @@ class CriteriaMethodInvokerSpec extends Specification {
         invoker.tryPropertyCriteria(CriteriaMethods.EQUALS, ['firstName', 'Fred', params] as Object[])
 
         then:
-        1 * builder.calculatePropertyName('firstName') >> 'firstName'
         1 * builder.eq('firstName', 'Fred', params)
     }
 
@@ -290,7 +282,6 @@ class CriteriaMethodInvokerSpec extends Specification {
         invoker.tryPropertyCriteria(CriteriaMethods.EQUALS_PROPERTY, ['firstName', 'lastName'] as Object[])
 
         then:
-        1 * builder.calculatePropertyName('firstName') >> 'firstName'
         1 * builder.eqProperty('firstName', 'lastName')
     }
 
@@ -299,7 +290,6 @@ class CriteriaMethodInvokerSpec extends Specification {
         invoker.tryPropertyCriteria(CriteriaMethods.GREATER_THAN, ['balance', 100] as Object[])
 
         then:
-        1 * builder.calculatePropertyName('balance') >> 'balance'
         1 * builder.gt('balance', 100)
     }
 
@@ -308,7 +298,6 @@ class CriteriaMethodInvokerSpec extends Specification {
         invoker.tryPropertyCriteria(CriteriaMethods.GREATER_THAN_PROPERTY, ['balance', 'balance'] as Object[])
 
         then:
-        1 * builder.calculatePropertyName('balance') >> 'balance'
         1 * builder.gtProperty('balance', 'balance')
     }
 
@@ -317,7 +306,6 @@ class CriteriaMethodInvokerSpec extends Specification {
         invoker.tryPropertyCriteria(CriteriaMethods.GREATER_THAN_OR_EQUAL, ['balance', 100] as Object[])
 
         then:
-        1 * builder.calculatePropertyName('balance') >> 'balance'
         1 * builder.ge('balance', 100)
     }
 
@@ -326,7 +314,6 @@ class CriteriaMethodInvokerSpec extends Specification {
         invoker.tryPropertyCriteria(CriteriaMethods.GREATER_THAN_OR_EQUAL_PROPERTY, ['balance', 'balance'] as Object[])
 
         then:
-        1 * builder.calculatePropertyName('balance') >> 'balance'
         1 * builder.geProperty('balance', 'balance')
     }
 
@@ -335,7 +322,6 @@ class CriteriaMethodInvokerSpec extends Specification {
         invoker.tryPropertyCriteria(CriteriaMethods.ILIKE, ['firstName', 'fr%'] as Object[])
 
         then:
-        1 * builder.calculatePropertyName('firstName') >> 'firstName'
         1 * builder.ilike('firstName', 'fr%')
     }
 
@@ -347,7 +333,6 @@ class CriteriaMethodInvokerSpec extends Specification {
         invoker.tryPropertyCriteria(CriteriaMethods.IN, ['firstName', names] as Object[])
 
         then:
-        1 * builder.calculatePropertyName('firstName') >> 'firstName'
         1 * builder.in('firstName', names)
     }
 
@@ -359,7 +344,6 @@ class CriteriaMethodInvokerSpec extends Specification {
         invoker.tryPropertyCriteria(CriteriaMethods.IN, ['firstName', names] as Object[])
 
         then:
-        1 * builder.calculatePropertyName('firstName') >> 'firstName'
         1 * builder.in('firstName', names)
     }
 
@@ -368,7 +352,6 @@ class CriteriaMethodInvokerSpec extends Specification {
         invoker.tryPropertyCriteria(CriteriaMethods.LESS_THAN, ['balance', 500] as Object[])
 
         then:
-        1 * builder.calculatePropertyName('balance') >> 'balance'
         1 * builder.lt('balance', 500)
     }
 
@@ -377,7 +360,6 @@ class CriteriaMethodInvokerSpec extends Specification {
         invoker.tryPropertyCriteria(CriteriaMethods.LESS_THAN_PROPERTY, ['balance', 'balance'] as Object[])
 
         then:
-        1 * builder.calculatePropertyName('balance') >> 'balance'
         1 * builder.ltProperty('balance', 'balance')
     }
 
@@ -386,7 +368,6 @@ class CriteriaMethodInvokerSpec extends Specification {
         invoker.tryPropertyCriteria(CriteriaMethods.LESS_THAN_OR_EQUAL, ['balance', 500] as Object[])
 
         then:
-        1 * builder.calculatePropertyName('balance') >> 'balance'
         1 * builder.le('balance', 500)
     }
 
@@ -395,7 +376,6 @@ class CriteriaMethodInvokerSpec extends Specification {
         invoker.tryPropertyCriteria(CriteriaMethods.LESS_THAN_OR_EQUAL_PROPERTY, ['balance', 'balance'] as Object[])
 
         then:
-        1 * builder.calculatePropertyName('balance') >> 'balance'
         1 * builder.leProperty('balance', 'balance')
     }
 
@@ -404,7 +384,6 @@ class CriteriaMethodInvokerSpec extends Specification {
         invoker.tryPropertyCriteria(CriteriaMethods.LIKE, ['firstName', 'Fr%'] as Object[])
 
         then:
-        1 * builder.calculatePropertyName('firstName') >> 'firstName'
         1 * builder.like('firstName', 'Fr%')
     }
 
@@ -413,7 +392,6 @@ class CriteriaMethodInvokerSpec extends Specification {
         invoker.tryPropertyCriteria(CriteriaMethods.NOT_EQUAL, ['firstName', 'Fred'] as Object[])
 
         then:
-        1 * builder.calculatePropertyName('firstName') >> 'firstName'
         1 * builder.ne('firstName', 'Fred')
     }
 
@@ -422,7 +400,6 @@ class CriteriaMethodInvokerSpec extends Specification {
         invoker.tryPropertyCriteria(CriteriaMethods.NOT_EQUAL_PROPERTY, ['firstName', 'lastName'] as Object[])
 
         then:
-        1 * builder.calculatePropertyName('firstName') >> 'firstName'
         1 * builder.neProperty('firstName', 'lastName')
     }
 
@@ -431,7 +408,6 @@ class CriteriaMethodInvokerSpec extends Specification {
         invoker.tryPropertyCriteria(CriteriaMethods.SIZE_EQUALS, ['transactions', 2] as Object[])
 
         then:
-        1 * builder.calculatePropertyName('transactions') >> 'transactions'
         1 * builder.sizeEq('transactions', 2)
     }
 
diff --git a/grails-data-hibernate7/core/src/test/groovy/grails/orm/HibernateCriteriaBuilderSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/grails/orm/HibernateCriteriaBuilderSpec.groovy
index 91dc5f8384..fa297dea84 100644
--- a/grails-data-hibernate7/core/src/test/groovy/grails/orm/HibernateCriteriaBuilderSpec.groovy
+++ b/grails-data-hibernate7/core/src/test/groovy/grails/orm/HibernateCriteriaBuilderSpec.groovy
@@ -462,6 +462,27 @@ class HibernateCriteriaBuilderSpec extends HibernateGormDatastoreSpec {
         results.size() == 1
         results[0].firstName == "Fred"
     }
+
+    void "scroll returns a ScrollableResults cursor over matching rows"() {
+        when:
+        def results = c.scroll {
+            eq("lastName", "Flintstone")
+            order("firstName", "asc")
+        }
+
+        then:
+        results instanceof org.hibernate.ScrollableResults
+        results.next()
+        results.get().firstName == "Fred"
+        results.next()
+        results.get().firstName == "Pebbles"
+        results.next()
+        results.get().firstName == "Wilma"
+        !results.next()
+
+        cleanup:
+        results?.close()
+    }
 }
 
 @Entity


(grails-core) 24/34: hibernate7: removed deprecated code from HibernateGormInstanceApi

Posted by bo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

borinquenkid pushed a commit to branch 8.0.x-hibernate7-dev
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit afd4c177af9af2e2636134c20da2a9222aef7bb3
Author: Walter Duque de Estrada <wb...@mac.com>
AuthorDate: Sat Mar 7 16:19:50 2026 -0600

    hibernate7: removed deprecated code from HibernateGormInstanceApi
---
 .../orm/hibernate/HibernateGormInstanceApi.groovy  | 139 +++++++--------------
 1 file changed, 43 insertions(+), 96 deletions(-)

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 6e80ef9baf..195da3939c 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
@@ -1,11 +1,11 @@
 /*
- * Copyright 2013 the original author or authors.
+ * Copyright 2013-2026 the original author or authors.
  *
  * Licensed 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
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ * http://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,
@@ -15,9 +15,12 @@
  */
 package org.grails.orm.hibernate
 
+import org.hibernate.LockMode
+
 import grails.gorm.validation.CascadingValidator
 import groovy.transform.CompileStatic
 import jakarta.persistence.FlushModeType
+import jakarta.persistence.LockModeType
 import org.codehaus.groovy.runtime.InvokerHelper
 import org.grails.datastore.gorm.GormInstanceApi
 import org.grails.datastore.gorm.GormValidateable
@@ -35,13 +38,11 @@ import org.grails.orm.hibernate.cfg.GrailsHibernateUtil
 import org.grails.orm.hibernate.support.HibernateRuntimeUtils
 
 import org.hibernate.HibernateException
-import org.hibernate.LockMode
 import org.hibernate.Session
 import org.hibernate.SessionFactory
 import org.hibernate.engine.spi.EntityEntry
 import org.hibernate.engine.spi.SessionImplementor
 import org.hibernate.persister.entity.EntityPersister
-import org.hibernate.tuple.NonIdentifierAttribute
 import org.springframework.beans.BeanWrapperImpl
 import org.springframework.beans.InvalidPropertyException
 import org.springframework.dao.DataAccessException
@@ -49,10 +50,7 @@ import org.springframework.validation.Errors
 import org.springframework.validation.Validator
 
 /**
- * The implementation of the GORM instance API contract for Hibernate.
- *
- * @author Graeme Rocher
- * @since 1.0
+ * The implementation of the GORM instance API contract for Hibernate 7.
  */
 @CompileStatic
 class HibernateGormInstanceApi<D> extends GormInstanceApi<D> {
@@ -78,9 +76,7 @@ class HibernateGormInstanceApi<D> extends GormInstanceApi<D> {
     protected SessionFactory sessionFactory
     protected ClassLoader classLoader
     protected IHibernateTemplate hibernateTemplate
-
     boolean autoFlush
-
     protected InstanceApiHelper instanceApiHelper
 
     HibernateGormInstanceApi(Class<D> persistentClass, HibernateDatastore datastore, ClassLoader classLoader) {
@@ -110,7 +106,6 @@ class HibernateGormInstanceApi<D> extends GormInstanceApi<D> {
 
         if (shouldValidate) {
             Validator validator = datastore.mappingContext.getEntityValidator(domainClass)
-
             Errors errors = HibernateRuntimeUtils.setupErrorsProperty(target)
 
             if (validator) {
@@ -131,7 +126,6 @@ class HibernateGormInstanceApi<D> extends GormInstanceApi<D> {
                     }
                     return null
                 }
-
                 setObjectToReadWrite(target)
             }
         }
@@ -156,8 +150,6 @@ class HibernateGormInstanceApi<D> extends GormInstanceApi<D> {
 
     private static void runDeferredBinding() {
         if (DEFERRED_BINDING != null) {
-            // DeferredBindingActions is from grails-data-binding (optional dep); invoked via reflection
-            // because it belongs to the migration plugin, which runs once per deployment and need not be on the compile classpath
             DEFERRED_BINDING.getMethod('runActions').invoke(null)
         }
     }
@@ -195,7 +187,7 @@ class HibernateGormInstanceApi<D> extends GormInstanceApi<D> {
         catch (DataAccessException e) {
             try {
                 hibernateTemplate.execute { Session session ->
-                    session.flushMode = FlushModeType.COMMIT
+                    session.setFlushMode(FlushModeType.COMMIT)
                 }
             }
             finally {
@@ -231,7 +223,7 @@ class HibernateGormInstanceApi<D> extends GormInstanceApi<D> {
     protected D performMerge(final D target, final boolean flush) {
         hibernateTemplate.execute { Session session ->
             Object merged = session.merge(target)
-            session.lock(merged, LockMode.NONE)
+            session.lock(merged, LockModeType.NONE)
             if (flush) {
                 flushSession session
             }
@@ -258,7 +250,7 @@ class HibernateGormInstanceApi<D> extends GormInstanceApi<D> {
         try {
             session.flush()
         } catch (HibernateException e) {
-            session.setFlushMode FlushModeType.COMMIT
+            session.setFlushMode(FlushModeType.COMMIT)
             throw e
         }
     }
@@ -270,7 +262,6 @@ class HibernateGormInstanceApi<D> extends GormInstanceApi<D> {
         for (PersistentProperty prop in entity.associations) {
             if (prop instanceof ToOne && !(prop instanceof Embedded)) {
                 ToOne toOne = (ToOne) prop
-
                 def propertyName = prop.name
                 def propValue = reflector.getProperty(target, propertyName)
                 if (propValue == null || t.contains(propValue)) {
@@ -278,14 +269,10 @@ class HibernateGormInstanceApi<D> extends GormInstanceApi<D> {
                 }
 
                 PersistentEntity otherSide = toOne.associatedEntity
-                if (otherSide == null) {
-                    continue
-                }
+                if (otherSide == null) continue
 
                 def identity = otherSide.identity
-                if (identity == null) {
-                    continue
-                }
+                if (identity == null) continue
 
                 def otherSideReflector = datastore.mappingContext.getEntityReflector(otherSide)
                 try {
@@ -297,17 +284,13 @@ class HibernateGormInstanceApi<D> extends GormInstanceApi<D> {
                         }
                     }
                 }
-                catch (InvalidPropertyException ignored) {
-                    // property is not accessable
-                }
+                catch (InvalidPropertyException ignored) {}
             }
         }
     }
 
     private static boolean shouldValidate(Map arguments, PersistentEntity entity) {
-        if (!entity) {
-            return false
-        }
+        if (!entity) return false
         if (arguments?.containsKey(ARGUMENT_VALIDATE)) {
             return ClassUtils.getBooleanFromMap(ARGUMENT_VALIDATE, arguments)
         }
@@ -345,7 +328,7 @@ class HibernateGormInstanceApi<D> extends GormInstanceApi<D> {
         return null
     }
 
-    protected void setErrorsOnInstance(Object target, Errors errors) {
+    protected static void setErrorsOnInstance(Object target, Errors errors) {
         if (target instanceof GormValidateable) {
             ((GormValidateable) target).setErrors(errors)
         } else {
@@ -361,113 +344,77 @@ class HibernateGormInstanceApi<D> extends GormInstanceApi<D> {
         insertActiveThreadLocal.remove()
     }
 
-    /**
-     * Checks whether a field is dirty
-     *
-     * @param instance The instance
-     * @param fieldName The name of the field
-     *
-     * @return true if the field is dirty
-     */
+    // --- Dirty Checking Logic ---
+
     boolean isDirty(D instance, String fieldName) {
         SessionImplementor session = (SessionImplementor) sessionFactory.currentSession
         EntityEntry entry = findEntityEntry(instance, session)
-        if (!entry || !entry.loadedState) {
-            return false
-        }
+        if (!entry || !entry.loadedState) return false
 
         EntityPersister persister = entry.persister
-        Object[] values = persister.getPropertyValues(instance)
+        Object[] values = persister.getValues(instance)
         int[] dirtyProperties = findDirty(persister, values, entry, instance, session)
-        if (dirtyProperties == null) {
-            return false
-        }
-        NonIdentifierAttribute[] props = persister.getEntityMetamodel().getProperties()
+        if (dirtyProperties == null) return false
+
+        String[] propertyNames = persister.getPropertyNames()
         int fieldIndex = -1
-        for (int i = 0; i < props.length; i++) {
-            if (props[i].name == fieldName) { fieldIndex = i; break }
+        for (int i = 0; i < propertyNames.length; i++) {
+            if (propertyNames[i] == fieldName) { fieldIndex = i; break }
         }
         return fieldIndex in dirtyProperties
     }
 
-    private int[] findDirty(EntityPersister persister, Object[] values, EntityEntry entry, D instance, SessionImplementor session) {
-        persister.findDirty(values, entry.loadedState, instance, session)
-    }
-
-    /**
-     * Checks whether an entity is dirty
-     *
-     * @param instance The instance
-     * @return true if it is dirty
-     */
     boolean isDirty(D instance) {
         SessionImplementor session = (SessionImplementor) sessionFactory.currentSession
         EntityEntry entry = findEntityEntry(instance, session)
-        if (!entry || !entry.loadedState) {
-            return false
-        }
+        if (!entry || !entry.loadedState) return false
+
         EntityPersister persister = entry.persister
-        Object[] currentState = persister.getPropertyValues(instance)
+        Object[] currentState = persister.getValues(instance)
         int[] dirtyPropertyIndexes = findDirty(persister, currentState, entry, instance, session)
         return dirtyPropertyIndexes != null
     }
 
-    /**
-     * Obtains a list of property names that are dirty
-     *
-     * @param instance The instance
-     * @return A list of property names that are dirty
-     */
     List<String> getDirtyPropertyNames(D instance) {
         SessionImplementor session = (SessionImplementor) sessionFactory.currentSession
         EntityEntry entry = findEntityEntry(instance, session)
-        if (!entry || !entry.loadedState) {
-            return []
-        }
+        if (!entry || !entry.loadedState) return []
 
         EntityPersister persister = entry.persister
-        Object[] currentState = persister.getPropertyValues(instance)
+        Object[] currentState = persister.getValues(instance)
         int[] dirtyPropertyIndexes = findDirty(persister, currentState, entry, instance, session)
+
         List<String> names = []
-        NonIdentifierAttribute[] entityProperties = persister.getEntityMetamodel().getProperties()
+        String[] propertyNames = persister.getPropertyNames()
         if (dirtyPropertyIndexes != null) {
             for (int index : dirtyPropertyIndexes) {
-                names.add(entityProperties[index].name)
+                names.add(propertyNames[index])
             }
         }
         return names
     }
 
-    /**
-     * Gets the original persisted value of a field.
-     *
-     * @param fieldName The field name
-     * @return The original persisted value
-     */
     Object getPersistentValue(D instance, String fieldName) {
         SessionImplementor session = (SessionImplementor) sessionFactory.currentSession
         def entry = findEntityEntry(instance, session, false)
-        if (!entry || !entry.loadedState) {
-            return null
-        }
+        if (!entry || !entry.loadedState) return null
 
         EntityPersister persister = entry.persister
-        int fieldIndex = persister.getEntityMetamodel().getProperties().findIndexOf {
-            NonIdentifierAttribute attribute -> fieldName == attribute.name
-        }
+        String[] propertyNames = persister.getPropertyNames()
+        int fieldIndex = propertyNames.findIndexOf { it == fieldName }
         return fieldIndex == -1 ? null : entry.loadedState[fieldIndex]
     }
 
-    protected EntityEntry findEntityEntry(D instance, SessionImplementor session, boolean forDirtyCheck = true) {
-        def entry = session.persistenceContext.getEntry(instance)
-        if (!entry) {
-            return null
-        }
+    // --- Helper Methods using proper Generic definitions to satisfy stubs ---
 
-        if (forDirtyCheck && !entry.requiresDirtyCheck(instance) && entry.loadedState) {
-            return null
-        }
+    private static <T> int[] findDirty(EntityPersister persister, Object[] values, EntityEntry entry, T instance, SessionImplementor session) {
+        persister.findDirty(values, entry.loadedState, instance, session)
+    }
 
+    protected static <T> EntityEntry findEntityEntry(T instance, SessionImplementor session, boolean forDirtyCheck = true) {
+        def entry = session.persistenceContext.getEntry(instance)
+        if (!entry) return null
+        if (forDirtyCheck && !entry.requiresDirtyCheck(instance) && entry.loadedState) return null
         return entry
     }
 
@@ -478,4 +425,4 @@ class HibernateGormInstanceApi<D> extends GormInstanceApi<D> {
     void setObjectToReadOnly(Object target) {
         GrailsHibernateUtil.setObjectToReadyOnly(target, sessionFactory)
     }
-}
+}
\ No newline at end of file


(grails-core) 21/34: hibernate7: more Codenarc

Posted by bo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

borinquenkid pushed a commit to branch 8.0.x-hibernate7-dev
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit 117af70c0cfec3f2569a157146ec27c2288f0da3
Author: Walter Duque de Estrada <wb...@mac.com>
AuthorDate: Sat Mar 7 13:36:42 2026 -0600

    hibernate7: more Codenarc
---
 .../orm/hibernate/HibernateGormStaticApi.groovy    | 98 ++++++++++------------
 .../hibernate/HibernateGormValidationApi.groovy    |  4 +-
 2 files changed, 48 insertions(+), 54 deletions(-)

diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy
index f4f49f10cb..d6545ee4db 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy
@@ -72,7 +72,7 @@ class HibernateGormStaticApi<D> extends GormStaticApi<D> {
         this.conversionService = datastore.mappingContext.conversionService
         this.proxyHandler = datastore.mappingContext.proxyHandler
         this.hibernateSession = new HibernateSession(
-                (HibernateDatastore)datastore,
+                (HibernateDatastore) datastore,
                 hibernateTemplate.getSessionFactory()
         )
         this.classLoader = classLoader
@@ -108,11 +108,11 @@ class HibernateGormStaticApi<D> extends GormStaticApi<D> {
             return null
         }
 
-        if(persistentEntity.isMultiTenant()) {
+        if (persistentEntity.isMultiTenant()) {
             // for multi-tenant entities we process get(..) via a query
-            (D)hibernateTemplate.execute(  { Session session ->
-                return new HibernateQuery(hibernateSession,persistentEntity ).idEq(id).singleResult()
-            } )
+            (D) hibernateTemplate.execute { Session session ->
+                new HibernateQuery(hibernateSession, persistentEntity).idEq(id).singleResult()
+            }
         }
         else {
             // for non multi-tenant entities we process get(..) via the second level cache
@@ -130,28 +130,28 @@ class HibernateGormStaticApi<D> extends GormStaticApi<D> {
             return null
         }
 
-        (D)hibernateTemplate.execute(  { Session session ->
+        (D) hibernateTemplate.execute { Session session ->
             CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder()
             CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(persistentEntity.javaClass)
 
             Root queryRoot = criteriaQuery.from(persistentEntity.javaClass)
-            criteriaQuery = criteriaQuery.where (
+            criteriaQuery = criteriaQuery.where(
                     //TODO: Remove explicit type cast once GROOVY-9460
-                    criteriaBuilder.equal((Expression<?>)  queryRoot.get(persistentEntity.identity.name), id)
+                    criteriaBuilder.equal((Expression<?>) queryRoot.get(persistentEntity.identity.name), id)
             )
             Query criteria = session.createQuery(criteriaQuery)
                     .setHint(AvailableHints.HINT_READ_ONLY, true)
             HibernateHqlQuery hibernateHqlQuery = new HibernateHqlQuery(
                     hibernateSession, persistentEntity, criteria)
-            return proxyHandler.unwrap( hibernateHqlQuery.singleResult() )
-        } )
+            proxyHandler.unwrap(hibernateHqlQuery.singleResult())
+        }
     }
 
     @Override
     D load(Serializable id) {
         id = convertIdentifier(id)
         if (id != null) {
-            return (D) hibernateTemplate.load((Class)persistentClass, id)
+            return (D) hibernateTemplate.load((Class) persistentClass, id)
         }
         else {
             return null
@@ -164,7 +164,7 @@ class HibernateGormStaticApi<D> extends GormStaticApi<D> {
         if (id != null) {
             // Use the configured MappingContext proxyFactory (e.g. GroovyProxyFactory) so proxies are created correctly
             def proxyFactory = datastore.getMappingContext().getProxyFactory()
-            return (D) proxyFactory.createProxy(datastore.currentSession, (Class)persistentClass, id)
+            return (D) proxyFactory.createProxy(datastore.currentSession, (Class) persistentClass, id)
         }
         else {
             return null
@@ -176,7 +176,6 @@ class HibernateGormStaticApi<D> extends GormStaticApi<D> {
         doListInternal("from ${persistentEntity.name}".toString(), [:], [], [:], false)
     }
 
-
     @Override
     Integer count() {
         String entity = persistentEntity.name
@@ -211,12 +210,12 @@ class HibernateGormStaticApi<D> extends GormStaticApi<D> {
 
     @Override
     D find(CharSequence query, Collection positionalParams, Map args) {
-       doSingleInternal(query, [:], positionalParams, args, false)
+        doSingleInternal(query, [:], positionalParams, args, false)
     }
 
     @Override
     List<D> findAll(CharSequence query, Map namedParams, Map args) {
-      doListInternal(query, namedParams, [], args, false)
+        doListInternal(query, namedParams, [], args, false)
     }
 
     D findWithNativeSql(CharSequence sql, Map args = Collections.emptyMap()) {
@@ -241,25 +240,25 @@ class HibernateGormStaticApi<D> extends GormStaticApi<D> {
 
     @Override
     List<D> findAll(CharSequence query) {
-        requireGString(query, "findAll")
+        requireGString(query, 'findAll')
         doListInternal(query, [:], [], [:], false)
     }
 
     @Override
     List executeQuery(CharSequence query) {
-        requireGString(query, "executeQuery")
+        requireGString(query, 'executeQuery')
         doListInternal(query, [:], [], [:], false)
     }
 
     @Override
     Integer executeUpdate(CharSequence query) {
-        requireGString(query, "executeUpdate")
-        doInternalExecuteUpdate(query,[:],[],[:])
+        requireGString(query, 'executeUpdate')
+        doInternalExecuteUpdate(query, [:], [], [:])
     }
 
     @Override
     D find(CharSequence query) {
-        requireGString(query, "find")
+        requireGString(query, 'find')
         doSingleInternal(query, [:], [], [:], false)
     }
 
@@ -289,23 +288,26 @@ class HibernateGormStaticApi<D> extends GormStaticApi<D> {
         doListInternal(query, [:], [], args, false)
     }
 
-
     @Override
     D findWhere(Map queryMap, Map args) {
         if (!queryMap) return null
-        String entity = persistentEntity.name
-        String where = queryMap.keySet().collect { "$it = :$it" }.join(' and ')
-        doSingleInternal("from $entity where $where" as String, queryMap as Map, [], args, false)
+        String hql = buildWhereHql(queryMap)
+        doSingleInternal(hql, queryMap, [], args, false)
     }
 
     @Override
     List<D> findAllWhere(Map queryMap, Map args) {
         if (!queryMap) return null
-        String entity = persistentEntity.name
-        String where = queryMap.keySet().collect { "$it = :$it" }.join(' and ')
-        doListInternal("from $entity where $where" as String, queryMap as Map, [], args, false)
+        String hql = buildWhereHql(queryMap)
+        doListInternal(hql, queryMap, [], args, false)
     }
 
+    private String buildWhereHql(Map queryMap) {
+        String whereClause = queryMap.keySet().collect { Object key -> "$key = :$key" }.join(' and ')
+        return "from ${persistentEntity.name} where $whereClause"
+    }
+
+
     @Override
     List executeQuery(CharSequence query, Map namedParams, Map args) {
         doListInternal(query, namedParams, [], args, false)
@@ -332,14 +334,11 @@ class HibernateGormStaticApi<D> extends GormStaticApi<D> {
         ids.collect { byId[it] }
     }
 
-
     @Override
     List<D> getAll(Serializable... ids) {
         getAllInternal(ids as List)
     }
 
-
-
     private List<D> doListInternal(CharSequence hql,
                                    Map namedParams,
                                    Collection positionalParams,
@@ -367,12 +366,12 @@ class HibernateGormStaticApi<D> extends GormStaticApi<D> {
 
     @Override
     Integer executeUpdate(CharSequence query, Map params, Map args) {
-        doInternalExecuteUpdate(query,params,[],args)
+        doInternalExecuteUpdate(query, params, [], args)
     }
 
     @Override
     Integer executeUpdate(CharSequence query, Collection indexedParams, Map args) {
-        doInternalExecuteUpdate(query,[:],indexedParams,args)
+        doInternalExecuteUpdate(query, [:], indexedParams, args)
     }
 
     private Integer doInternalExecuteUpdate(CharSequence hql,
@@ -389,7 +388,7 @@ class HibernateGormStaticApi<D> extends GormStaticApi<D> {
     @SuppressWarnings('GroovyAssignabilityCheck')
     private HibernateHqlQuery prepareHqlQuery(CharSequence hql, boolean isNative, boolean isUpdate,
                                               Map namedParams, Collection positionalParams, Map querySettings) {
-        def ctx = HqlQueryContext.prepare(persistentEntity, hql, namedParams, positionalParams,querySettings, isNative, isUpdate,)
+        def ctx = HqlQueryContext.prepare(persistentEntity, hql, namedParams, positionalParams, querySettings, isNative, isUpdate)
         return HibernateHqlQuery.createHqlQuery(
                 (HibernateDatastore) datastore,
                 sessionFactory,
@@ -401,21 +400,21 @@ class HibernateGormStaticApi<D> extends GormStaticApi<D> {
         )
     }
 
-
     protected Serializable convertIdentifier(Serializable id) {
         def identity = persistentEntity.identity
-        if(identity != null) {
+        if (identity != null) {
             ConversionService conversionService = persistentEntity.mappingContext.conversionService
-            if(id != null) {
+            if (id != null) {
                 Class identityType = identity.type
                 Class idInstanceType = id.getClass()
-                if(identityType.isAssignableFrom(idInstanceType)) {
+                if (identityType.isAssignableFrom(idInstanceType)) {
                     return id
                 }
-                else if(conversionService.canConvert(idInstanceType, identityType)) {
+                else if (conversionService.canConvert(idInstanceType, identityType)) {
                     try {
-                        return (Serializable)conversionService.convert(id, identityType)
-                    } catch (Throwable ignored) {
+                        return (Serializable) conversionService.convert(id, identityType)
+                    }
+                    catch (Throwable ignored) {
                         return null
                     }
                 }
@@ -427,13 +426,12 @@ class HibernateGormStaticApi<D> extends GormStaticApi<D> {
         return id
     }
 
-
     @Override
     List<D> list(Map params = Collections.emptyMap()) {
         firePreQueryEvent()
-        HqlListQueryBuilder builder = new HqlListQueryBuilder(persistentEntity, params);
-        String hql = builder.buildListHql();
-        HqlQueryContext ctx = HqlQueryContext.prepare(persistentEntity, hql, Collections.emptyMap(), Collections.emptyList(), params , false, false );
+        HqlListQueryBuilder builder = new HqlListQueryBuilder(persistentEntity, params)
+        String hql = builder.buildListHql()
+        HqlQueryContext ctx = HqlQueryContext.prepare(persistentEntity, hql, Collections.emptyMap(), Collections.emptyList(), params, false, false)
         HibernateHqlQuery hqlQuery = HibernateHqlQuery.createHqlQuery(
                 (HibernateDatastore) datastore,
                 sessionFactory,
@@ -452,7 +450,7 @@ class HibernateGormStaticApi<D> extends GormStaticApi<D> {
 
     @Override
     def propertyMissing(String name) {
-        if(datastore instanceof ConnectionSourcesProvider) {
+        if (datastore instanceof ConnectionSourcesProvider) {
             return GormEnhancer.findStaticApi(persistentClass, name)
         }
         else {
@@ -462,16 +460,15 @@ class HibernateGormStaticApi<D> extends GormStaticApi<D> {
 
     @Override
     GrailsCriteria createCriteria() {
-        def builder = new HibernateCriteriaBuilder(persistentClass, sessionFactory,(HibernateDatastore)datastore)
+        def builder = new HibernateCriteriaBuilder(persistentClass, sessionFactory, (HibernateDatastore) datastore)
         builder.conversionService = conversionService
         return builder
     }
 
-
     protected void firePostQueryEvent(Object result) {
         def hibernateQuery = new HibernateQuery(new HibernateSession((HibernateDatastore) datastore, sessionFactory), persistentEntity)
-        def list = result instanceof List ? (List)result :  Collections.singletonList(result)
-        datastore.applicationEventPublisher.publishEvent( new PostQueryEvent(datastore, hibernateQuery, list))
+        def list = result instanceof List ? (List) result : Collections.singletonList(result)
+        datastore.applicationEventPublisher.publishEvent(new PostQueryEvent(datastore, hibernateQuery, list))
     }
 
     protected void firePreQueryEvent() {
@@ -479,7 +476,4 @@ class HibernateGormStaticApi<D> extends GormStaticApi<D> {
         def hibernateQuery = new HibernateQuery(hibernateSession, persistentEntity)
         datastore.applicationEventPublisher.publishEvent(new PreQueryEvent(datastore, hibernateQuery))
     }
-
-
-
 }
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormValidationApi.groovy b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormValidationApi.groovy
index 05e652bf1c..2bf204e982 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormValidationApi.groovy
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormValidationApi.groovy
@@ -32,8 +32,8 @@ import org.springframework.validation.Validator
 @CompileStatic
 class HibernateGormValidationApi<D> extends GormValidationApi<D> {
 
-    public static final String ARGUMENT_DEEP_VALIDATE = "deepValidate"
-    private static final String ARGUMENT_EVICT = "evict"
+    public static final String ARGUMENT_DEEP_VALIDATE = 'deepValidate'
+    private static final String ARGUMENT_EVICT = 'evict'
 
     protected ClassLoader classLoader
     protected HibernateDatastore datastore


(grails-core) 02/34: hibernate7: CloseSuppressingInvocationHandler

Posted by bo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

borinquenkid pushed a commit to branch 8.0.x-hibernate7-dev
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit 217121b3c413dbddfbe49867cda3dcb9c4109daa
Author: Walter Duque de Estrada <wb...@mac.com>
AuthorDate: Thu Mar 5 16:05:27 2026 -0600

    hibernate7: CloseSuppressingInvocationHandler
---
 grails-data-hibernate7/core/COVERAGE.md            | 255 +++++++++++++++++++++
 .../CloseSuppressingInvocationHandler.java         |  79 +++++++
 .../CloseSuppressingInvocationHandlerSpec.groovy   |  93 ++++++++
 3 files changed, 427 insertions(+)

diff --git a/grails-data-hibernate7/core/COVERAGE.md b/grails-data-hibernate7/core/COVERAGE.md
new file mode 100644
index 0000000000..b69ba9a97e
--- /dev/null
+++ b/grails-data-hibernate7/core/COVERAGE.md
@@ -0,0 +1,255 @@
+# Hibernate 7 Core Module Test Coverage
+
+| Class | Instruction Coverage |
+| :--- | :--- |
+| org.grails.orm.hibernate.GrailsHibernateTemplate.CloseSuppressingInvocationHandler | 0% |
+| org.grails.orm.hibernate.HibernateDatastore.new DataSourceConnectionSourceFactory() {...} | 0% |
+| org.grails.orm.hibernate.HibernateGormInstanceApi._delete_closure2 | 0% |
+| org.grails.orm.hibernate.HibernateGormStaticApi._get_closure1 | 0% |
+| org.grails.orm.hibernate.SessionFactoryHolder | 0% |
+| org.grails.orm.hibernate.cfg.InstanceProxy | 0% |
+| org.grails.orm.hibernate.cfg.PersistentEntityNamingStrategy | 0% |
+| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateEmbeddedCollectionProperty | 0% |
+| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateMappingBuilder.new GroovyObject() {...} | 0% |
+| org.grails.orm.hibernate.exceptions.CouldNotDetermineHibernateDialectException | 0% |
+| org.grails.orm.hibernate.exceptions.GrailsHibernateConfigurationException | 0% |
+| org.grails.orm.hibernate.exceptions.GrailsHibernateException | 0% |
+| org.grails.orm.hibernate.query.HibernateQueryConstants | 0% |
+| org.grails.orm.hibernate.support.DataSourceFactoryBean | 0% |
+| org.grails.orm.hibernate.support.HibernateDatastoreConnectionSourcesRegistrar | 0% |
+| org.grails.orm.hibernate.support.HibernateDatastoreFactoryBean | 0% |
+| org.grails.orm.hibernate.support.HibernateDialectDetectorFactoryBean | 0% |
+| org.grails.orm.hibernate.support.HibernateDialectDetectorFactoryBean.new DialectResolutionInfoSource() {...} | 0% |
+| org.grails.orm.hibernate.support.HibernateDialectDetectorFactoryBean.new ServiceRegistryImplementor() {...} | 0% |
+| org.grails.orm.hibernate.cfg.domainbinding.util.GeneratorCreationContextWrapper | 16% |
+| org.grails.orm.hibernate.InstanceApiHelper | 17% |
+| org.grails.orm.hibernate.GrailsSessionContext | 26% |
+| org.grails.orm.hibernate.cfg.domainbinding.secondpass.ListSecondPassBinder | 32% |
+| org.grails.orm.hibernate.cfg.GrailsHibernateUtil | 35% |
+| org.grails.orm.hibernate.cfg.Table | 35% |
+| org.grails.orm.hibernate.cfg.ColumnConfig | 42% |
+| org.grails.orm.hibernate.cfg.domainbinding.secondpass.MapSecondPassBinder | 43% |
+| org.grails.orm.hibernate.exceptions.GrailsQueryException | 44% |
+| org.grails.orm.hibernate.query.MutationQueryDelegate | 45% |
+| org.grails.orm.hibernate.cfg.Identity | 46% |
+| org.grails.orm.hibernate.HibernateDatastore.new HibernateGormEnhancer() {...} | 50% |
+| org.grails.orm.hibernate.cfg.HibernateMappingContextConfiguration | 54% |
+| org.grails.orm.hibernate.query.GrailsHibernateQueryUtils | 54% |
+| org.grails.orm.hibernate.query.SelectQueryDelegate | 57% |
+| org.grails.orm.hibernate.HibernateDatastore | 59% |
+| org.grails.orm.hibernate.cfg.SortConfig | 59% |
+| org.grails.orm.hibernate.HibernateEventListeners | 60% |
+| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateEmbeddedPersistentEntity | 60% |
+| org.grails.orm.hibernate.proxy.HibernateProxyHandler | 61% |
+| org.grails.orm.hibernate.HibernateSession | 62% |
+| org.grails.orm.hibernate.cfg.MappingCacheHolder | 63% |
+| org.grails.orm.hibernate.GrailsHibernateTransactionManager | 65% |
+| grails.orm.HibernateCriteriaBuilder | 67% |
+| org.grails.orm.hibernate.cfg.JoinTable | 67% |
+| org.grails.orm.hibernate.connections.HibernateConnectionSourceFactory | 67% |
+| org.grails.orm.hibernate.GrailsHibernateTemplate | 68% |
+| org.grails.orm.hibernate.access.TraitPropertyAccessStrategy | 69% |
+| org.grails.orm.hibernate.cfg.domainbinding.generator.GrailsIncrementGenerator | 70% |
+| org.grails.orm.hibernate.query.HqlQueryDelegate | 71% |
+| org.grails.orm.hibernate.cfg.DiscriminatorConfig | 72% |
+| org.grails.orm.hibernate.connections.HibernateConnectionSourceSettingsBuilder | 72% |
+| org.grails.orm.hibernate.cfg.IdentityEnumType | 74% |
+| org.grails.orm.hibernate.cfg.domainbinding.binder.SingleTableSubclassBinder | 74% |
+| org.grails.orm.hibernate.cfg.domainbinding.generator.GrailsNativeGenerator | 74% |
+| org.grails.orm.hibernate.support.SoftKey | 75% |
+| org.grails.orm.hibernate.EventListenerIntegrator | 76% |
+| org.grails.orm.hibernate.HibernateDatastore.new HibernateDatastore() {...} | 78% |
+| org.grails.orm.hibernate.cfg.domainbinding.util.CascadeBehaviorFetcher | 78% |
+| org.grails.orm.hibernate.support.ClosureEventTriggeringInterceptor | 78% |
+| org.grails.orm.hibernate.cfg.Mapping | 79% |
+| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateMappingFactory | 79% |
+| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernatePersistentProperty | 79% |
+| org.grails.orm.hibernate.cfg.domainbinding.secondpass.BasicCollectionElementBinder | 80% |
+| org.grails.orm.hibernate.cfg.CompositeIdentity | 81% |
+| org.grails.orm.hibernate.multitenancy.MultiTenantEventListener | 81% |
+| org.grails.orm.hibernate.cfg.domainbinding.secondpass.CollectionWithJoinTableBinder | 82% |
+| org.grails.orm.hibernate.query.GrailsHibernateQueryUtils.new Comparator() {...} | 82% |
+| org.grails.orm.hibernate.cfg.domainbinding.util.TableForManyCalculator | 84% |
+| org.grails.orm.hibernate.event.listener.HibernateEventListener | 84% |
+| org.grails.orm.hibernate.HibernateGormInstanceApi | 85% |
+| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateIdentityMapping | 85% |
+| org.grails.orm.hibernate.cfg.domainbinding.binder.SimpleValueBinder | 86% |
+| org.grails.orm.hibernate.connections.HibernateConnectionSourceSettings.HibernateSettings | 86% |
+| org.grails.orm.hibernate.query.PredicateGenerator | 86% |
+| grails.orm.CriteriaMethodInvoker | 87% |
+| org.grails.orm.hibernate.cfg.CacheConfig | 87% |
+| org.grails.orm.hibernate.cfg.domainbinding.binder.ManyToOneBinder | 87% |
+| org.grails.orm.hibernate.cfg.domainbinding.collectionType.CollectionType | 87% |
+| org.grails.orm.hibernate.HibernateGormStaticApi | 88% |
+| org.grails.orm.hibernate.HibernateGormValidationApi | 88% |
+| org.grails.orm.hibernate.cfg.IdentityEnumType.BidiEnumMap | 88% |
+| org.grails.orm.hibernate.cfg.domainbinding.util.NamespaceNameExtractor | 88% |
+| org.grails.orm.hibernate.query.PagedResultList | 88% |
+| org.grails.orm.hibernate.support.HibernateRuntimeUtils | 88% |
+| org.grails.orm.hibernate.cfg.PropertyConfig | 89% |
+| org.grails.orm.hibernate.cfg.PropertyDefinitionDelegate | 89% |
+| org.grails.orm.hibernate.cfg.domainbinding.generator.GrailsSequenceStyleGenerator | 89% |
+| org.grails.orm.hibernate.cfg.domainbinding.util.UniqueKeyForColumnsCreator | 89% |
+| org.grails.orm.hibernate.cfg.domainbinding.binder.ClassBinder | 90% |
+| org.grails.orm.hibernate.cfg.domainbinding.binder.ClassPropertiesBinder | 90% |
+| org.grails.orm.hibernate.cfg.domainbinding.generator.GrailsTableGenerator | 90% |
+| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateOneToOneProperty | 90% |
+| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateToManyProperty | 90% |
+| org.grails.orm.hibernate.cfg.domainbinding.util.DefaultColumnNameFetcher | 90% |
+| org.grails.orm.hibernate.query.HibernateAssociationQuery | 90% |
+| org.grails.orm.hibernate.query.HibernateQueryExecutor | 90% |
+| org.grails.orm.hibernate.cfg.domainbinding.util.NamingStrategyProvider | 91% |
+| org.grails.orm.hibernate.support.ClosureEventListener | 91% |
+| org.grails.orm.hibernate.HibernateGormEnhancer | 92% |
+| org.grails.orm.hibernate.cfg.domainbinding.binder.CollectionBinder | 92% |
+| org.grails.orm.hibernate.cfg.domainbinding.binder.RootPersistentClassCommonValuesBinder | 92% |
+| org.grails.orm.hibernate.cfg.domainbinding.generator.GrailsSequenceGeneratorEnum | 92% |
+| org.grails.orm.hibernate.cfg.domainbinding.util.GrailsEnumType | 92% |
+| org.grails.orm.hibernate.cfg.domainbinding.util.UniqueNameGenerator | 92% |
+| org.grails.orm.hibernate.compiler.HibernateEntityTransformation | 92% |
+| org.grails.orm.hibernate.dirty.GrailsEntityDirtinessStrategy | 92% |
+| org.grails.orm.hibernate.query.HibernateHqlQuery | 92% |
+| org.grails.orm.hibernate.query.HibernateQuery | 92% |
+| org.grails.orm.hibernate.HibernateGormInstanceApi._delete_closure1 | 93% |
+| org.grails.orm.hibernate.cfg.domainbinding.binder.ColumnBinder | 93% |
+| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateAssociation | 93% |
+| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateMappingBuilder | 93% |
+| org.grails.orm.hibernate.cfg.NaturalId | 94% |
+| org.grails.orm.hibernate.cfg.domainbinding.binder.SimpleValueColumnBinder | 94% |
+| org.grails.orm.hibernate.cfg.domainbinding.hibernate.GrailsHibernatePersistentEntity | 94% |
+| org.grails.orm.hibernate.cfg.domainbinding.secondpass.UnidirectionalOneToManyBinder | 94% |
+| org.grails.orm.hibernate.dirty.GrailsEntityDirtinessStrategy._findDirty_closure1 | 94% |
+| org.grails.orm.hibernate.HibernateGormInstanceApi._performMerge_closure4 | 95% |
+| org.grails.orm.hibernate.HibernateGormInstanceApi._performPersist_closure5 | 95% |
+| org.grails.orm.hibernate.HibernateGormValidationApi._validate_closure1 | 95% |
+| org.grails.orm.hibernate.cfg.Identity._getProperties_closure1 | 95% |
+| org.grails.orm.hibernate.cfg.domainbinding.binder.CompositeIdentifierToManyToOneBinder | 95% |
+| org.grails.orm.hibernate.cfg.domainbinding.binder.EnumTypeBinder | 95% |
+| org.grails.orm.hibernate.compiler.HibernateEntityTransformation.new GroovyObject() {...} | 95% |
+| org.grails.orm.hibernate.query.HqlQueryContext | 95% |
+| org.grails.orm.hibernate.HibernateGormStaticApi._list_closure7 | 96% |
+| org.grails.orm.hibernate.cfg.HibernateMappingContext | 96% |
+| org.grails.orm.hibernate.cfg.domainbinding.binder.ComponentBinder | 96% |
+| org.grails.orm.hibernate.cfg.domainbinding.binder.GrailsPropertyBinder | 96% |
+| org.grails.orm.hibernate.cfg.domainbinding.util.NamingStrategyWrapper | 96% |
+| grails.gorm.hibernate.mapping.MappingBuilder.ClosureMappingDefinition | 97% |
+| org.grails.orm.hibernate.cfg.domainbinding.binder.SimpleIdBinder | 97% |
+| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateMappingBuilder._id_closure1 | 97% |
+| org.grails.orm.hibernate.cfg.domainbinding.secondpass.CollectionSecondPassBinder | 97% |
+| org.grails.orm.hibernate.cfg.domainbinding.util.LogCascadeMapping | 97% |
+| org.grails.orm.hibernate.cfg.domainbinding.util.MultiTenantFilterBinder | 97% |
+| org.grails.orm.hibernate.connections.HibernateConnectionSourceSettings.HibernateSettings.FlushSettings.FlushMode | 97% |
+| org.grails.orm.hibernate.query.HibernateQueryArgument | 97% |
+| org.grails.orm.hibernate.query.JpaFromProvider | 97% |
+| org.grails.orm.hibernate.cfg.domainbinding.binder.IndexBinder | 98% |
+| org.grails.orm.hibernate.query.ProjectionPredicate | 98% |
+| grails.orm.CriteriaMethods | 99% |
+| org.grails.orm.hibernate.cfg.domainbinding.binder.ColumnConfigToColumnBinder | 99% |
+| org.grails.orm.hibernate.cfg.domainbinding.binder.GrailsDomainBinder | 99% |
+| org.grails.orm.hibernate.cfg.domainbinding.util.OrderByClauseBuilder | 99% |
+| grails.gorm.hibernate.mapping.MappingBuilder | 100% |
+| org.grails.orm.hibernate.HibernateDatastore.new Closure() {...} | 100% |
+| org.grails.orm.hibernate.HibernateDatastore.new HibernateDatastore() {...} | 100% |
+| org.grails.orm.hibernate.HibernateDatastore.new MappingContext.Listener() {...} | 100% |
+| org.grails.orm.hibernate.HibernateGormInstanceApi._attach_closure3 | 100% |
+| org.grails.orm.hibernate.HibernateGormInstanceApi._getPersistentValue_closure6 | 100% |
+| org.grails.orm.hibernate.HibernateGormStaticApi._findAllWhere_closure4 | 100% |
+| org.grails.orm.hibernate.HibernateGormStaticApi._findWhere_closure5 | 100% |
+| org.grails.orm.hibernate.HibernateGormStaticApi._getAllInternal_closure6 | 100% |
+| org.grails.orm.hibernate.HibernateGormStaticApi._getAllInternal_closure6._closure10 | 100% |
+| org.grails.orm.hibernate.HibernateGormStaticApi._getAllInternal_closure6._closure8 | 100% |
+| org.grails.orm.hibernate.HibernateGormStaticApi._getAllInternal_closure6._closure9 | 100% |
+| org.grails.orm.hibernate.HibernateGormStaticApi._get_closure2 | 100% |
+| org.grails.orm.hibernate.HibernateGormStaticApi._read_closure3 | 100% |
+| org.grails.orm.hibernate.MetadataIntegrator | 100% |
+| org.grails.orm.hibernate.SchemaTenantDataSource | 100% |
+| org.grails.orm.hibernate.access.TraitPropertyAccessStrategy.new PropertyAccess() {...} | 100% |
+| org.grails.orm.hibernate.cfg.CompositeIdentity._getHibernateProperties_closure1 | 100% |
+| org.grails.orm.hibernate.cfg.CompositeIdentity._getHibernateProperties_closure2 | 100% |
+| org.grails.orm.hibernate.cfg.GrailsNamedStrategyContributor | 100% |
+| org.grails.orm.hibernate.cfg.HibernateMappingContextConfiguration.new ClassLoaderServiceImpl() {...} | 100% |
+| org.grails.orm.hibernate.cfg.HibernateMappingContextConfiguration.new SessionFactoryObserver() {...} | 100% |
+| org.grails.orm.hibernate.cfg.Identity._getProperties_closure1._closure2 | 100% |
+| org.grails.orm.hibernate.cfg.PropertyConfig._getTypeName_closure1 | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.binder.CollectionForPropertyConfigBinder | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.binder.ComponentUpdater | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.binder.CompositeIdBinder | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.binder.ConfiguredDiscriminatorBinder | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.binder.DefaultDiscriminatorBinder | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.binder.DiscriminatorPropertyBinder | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.binder.ForeignKeyOneToOneBinder | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.binder.IdentityBinder | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.binder.JoinedSubClassBinder | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.binder.ManyToOneValuesBinder | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.binder.NaturalIdentifierBinder | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.binder.NumericColumnConstraintsBinder | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.binder.OneToOneBinder | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.binder.PropertyBinder | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.binder.RootBinder | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.binder.StringColumnConstraintsBinder | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.binder.SubClassBinder | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.binder.SubclassMappingBinder | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.binder.UnionSubclassBinder | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.binder.VersionBinder | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.collectionType.BagCollectionType | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.collectionType.CollectionHolder | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.collectionType.ListCollectionType | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.collectionType.MapCollectionType | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.collectionType.SetCollectionType | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.collectionType.SortedSetCollectionType | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.generator.GrailsIdentityGenerator | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.generator.GrailsSequenceGeneratorEnum._fromName_closure1 | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.generator.GrailsSequenceWrapper | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.hibernate.GrailsJpaMappingConfigurationStrategy | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateBasicProperty | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateClassMapping | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateCustomEnumProperty | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateCustomProperty | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateEmbeddedClassMapping | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateEmbeddedProperty | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateIdentityProperty | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateManyToManyProperty | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateManyToOneProperty | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateMappingBuilder._handlePropertyInternal_closure2 | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateOneToManyProperty | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernatePersistentEntity | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateSimpleEnumProperty | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateSimpleProperty | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateTenantIdProperty | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.secondpass.BidirectionalMapElementBinder | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.secondpass.BidirectionalOneToManyLinker | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.secondpass.CollectionKeyBinder | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.secondpass.CollectionKeyColumnUpdater | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.secondpass.CollectionMultiTenantFilterBinder | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.secondpass.CollectionOrderByBinder | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.secondpass.DependentKeyValueBinder | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.secondpass.GrailsSecondPass | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.secondpass.ListSecondPass | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.secondpass.ManyToManyElementBinder | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.secondpass.MapSecondPass | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.secondpass.PrimaryKeyValueCreator | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.secondpass.SetSecondPass | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.secondpass.UnidirectionalOneToManyInverseValuesBinder | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.util.BackticksRemover | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.util.BasicValueIdCreator | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.util.CascadeBehavior | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.util.ColumnNameForPropertyAndPathFetcher | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.util.ConfigureDerivedPropertiesConsumer | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.util.CreateKeyForProps | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.util.ForeignKeyColumnCountCalculator | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.util.GrailsPropertyResolver | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.util.MultiTenantFilterDefinitionBinder | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.util.OrderByClauseBuilder.SortEntry | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.util.PropertyFromValueCreator | 100% |
+| org.grails.orm.hibernate.cfg.domainbinding.util.SimpleValueColumnFetcher | 100% |
+| org.grails.orm.hibernate.connections.HibernateConnectionSource | 100% |
+| org.grails.orm.hibernate.connections.HibernateConnectionSourceSettings | 100% |
+| org.grails.orm.hibernate.query.AliasMapEntryFunction | 100% |
+| org.grails.orm.hibernate.query.CriteriaAndAlias | 100% |
+| org.grails.orm.hibernate.query.DetachedAssociationFunction | 100% |
+| org.grails.orm.hibernate.query.GrailsRLikeFunctionContributor | 100% |
+| org.grails.orm.hibernate.query.HibernateQuery.new Closure() {...} | 100% |
+| org.grails.orm.hibernate.query.JpaCriteriaQueryCreator | 100% |
+| org.grails.orm.hibernate.query.PagedResultList.new GrailsHibernateTemplate.HibernateCallback() {...} | 100% |
+| org.grails.orm.hibernate.query.RegexDialectPattern | 100% |
+| org.hibernate.proxy.HibernateProxyHelper | 100% |
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/CloseSuppressingInvocationHandler.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/CloseSuppressingInvocationHandler.java
new file mode 100644
index 0000000000..b4fa3dc6b3
--- /dev/null
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/CloseSuppressingInvocationHandler.java
@@ -0,0 +1,79 @@
+/*
+ *  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.orm.hibernate;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+
+import org.hibernate.Session;
+import org.hibernate.query.Query;
+
+/**
+ * Invocation handler that suppresses close calls on Hibernate Sessions. Also prepares returned
+ * Query and Criteria objects.
+ *
+ * @see org.hibernate.Session#close
+ */
+public class CloseSuppressingInvocationHandler implements InvocationHandler {
+
+    protected final Session target;
+    protected final GrailsHibernateTemplate template;
+
+    public CloseSuppressingInvocationHandler(Session target, GrailsHibernateTemplate template) {
+        this.target = target;
+        this.template = template;
+    }
+
+    @Override
+    public Object invoke(Object proxy, Method method, Object[] args) throws Exception {
+        // Invocation on Session interface coming in...
+
+        switch (method.getName()) {
+            case "equals" -> {
+                // Only consider equal when proxies are identical.
+                return (proxy == args[0]);
+                // Only consider equal when proxies are identical.
+            }
+            case "hashCode" -> {
+                // Use hashCode of Session proxy.
+                return System.identityHashCode(proxy);
+                // Use hashCode of Session proxy.
+            }
+            case "close" -> {
+                // Handle close method: suppress, not valid.
+                return null;
+            }
+        }
+
+
+            Object retVal = method.invoke(target, args);
+
+            // If return value is a Query or Criteria, apply transaction timeout.
+            // Applies to createQuery, getNamedQuery, createCriteria.
+            if (retVal instanceof org.hibernate.query.Query<?> query) {
+                template.prepareQuery(query);
+            }
+            if (retVal instanceof Query<?> query) {
+                template.prepareCriteria(query);
+            }
+
+            return retVal;
+
+    }
+}
diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/CloseSuppressingInvocationHandlerSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/CloseSuppressingInvocationHandlerSpec.groovy
new file mode 100644
index 0000000000..eea98d9883
--- /dev/null
+++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/CloseSuppressingInvocationHandlerSpec.groovy
@@ -0,0 +1,93 @@
+/*
+ *  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.orm.hibernate
+
+import org.hibernate.Session
+import org.hibernate.query.Query
+import spock.lang.Specification
+import java.lang.reflect.Method
+
+class CloseSuppressingInvocationHandlerSpec extends Specification {
+
+    def "test close is suppressed"() {
+        given:
+        Session target = Mock(Session)
+        GrailsHibernateTemplate template = Mock(GrailsHibernateTemplate)
+        CloseSuppressingInvocationHandler handler = new CloseSuppressingInvocationHandler(target, template)
+        Method closeMethod = Session.class.getMethod("close")
+
+        when:
+        def result = handler.invoke(null, closeMethod, null)
+
+        then:
+        0 * target.close()
+        result == null
+    }
+
+    def "test equals and hashCode"() {
+        given:
+        Session target = Mock(Session)
+        GrailsHibernateTemplate template = Mock(GrailsHibernateTemplate)
+        CloseSuppressingInvocationHandler handler = new CloseSuppressingInvocationHandler(target, template)
+        Method equalsMethod = Object.class.getMethod("equals", Object.class)
+        Method hashCodeMethod = Object.class.getMethod("hashCode")
+        def proxy = new Object()
+
+        expect:
+        handler.invoke(proxy, equalsMethod, [proxy] as Object[]) == true
+        handler.invoke(proxy, equalsMethod, [new Object()] as Object[]) == false
+        handler.invoke(proxy, hashCodeMethod, null) == System.identityHashCode(proxy)
+    }
+
+    def "test query preparation"() {
+        given:
+        Session target = Mock(Session)
+        GrailsHibernateTemplate template = Mock(GrailsHibernateTemplate)
+        CloseSuppressingInvocationHandler handler = new CloseSuppressingInvocationHandler(target, template)
+        
+        Query hibernateQuery = Mock(Query)
+        Method createQueryMethod = Session.class.getMethod("createQuery", String.class)
+        
+        when:
+        def result = handler.invoke(null, createQueryMethod, ["from Book"] as Object[])
+
+        then:
+        1 * target.createQuery("from Book") >> hibernateQuery
+        1 * template.prepareQuery(hibernateQuery)
+        result == hibernateQuery
+    }
+
+    def "test criteria preparation"() {
+        given:
+        Session target = Mock(Session)
+        GrailsHibernateTemplate template = Mock(GrailsHibernateTemplate)
+        CloseSuppressingInvocationHandler handler = new CloseSuppressingInvocationHandler(target, template)
+        
+        Query jpaQuery = Mock(Query)
+        Method createQueryMethod = Session.class.getMethod("createQuery", String.class, Class.class)
+        
+        when:
+        def result = handler.invoke(null, createQueryMethod, ["from Book", Object.class] as Object[])
+
+        then:
+        1 * target.createQuery("from Book", Object.class) >> jpaQuery
+        1 * template.prepareCriteria(jpaQuery)
+        result == jpaQuery
+    }
+}


(grails-core) 29/34: hibernate7: HibernateGormValidationApi bug fix

Posted by bo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

borinquenkid pushed a commit to branch 8.0.x-hibernate7-dev
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit a4617c9106ffbd108e5f75d3507722c8046c190f
Author: Walter Duque de Estrada <wb...@mac.com>
AuthorDate: Sat Mar 7 19:34:41 2026 -0600

    hibernate7: HibernateGormValidationApi bug fix
---
 .../hibernate/HibernateGormValidationApi.groovy    |  14 ++-
 .../HibernateGormValidationApiSpec.groovy          | 121 +++++++++++++++++++++
 2 files changed, 129 insertions(+), 6 deletions(-)

diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormValidationApi.groovy b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormValidationApi.groovy
index 2bf204e982..666ab92cba 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormValidationApi.groovy
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormValidationApi.groovy
@@ -57,7 +57,7 @@ class HibernateGormValidationApi<D> extends GormValidationApi<D> {
         Validator validator = getValidator()
         if (validator == null) return true
 
-        Boolean valid = Boolean.TRUE
+        boolean valid = true
         boolean evict = false
         boolean deepValidate = true
         Set validatedFields = null
@@ -69,7 +69,9 @@ class HibernateGormValidationApi<D> extends GormValidationApi<D> {
             deepValidate = ClassUtils.getBooleanFromMap(ARGUMENT_DEEP_VALIDATE, arguments)
         }
 
-        evict = ClassUtils.getBooleanFromMap(ARGUMENT_EVICT, arguments)
+        if (arguments?.containsKey(ARGUMENT_EVICT)) {
+            evict = ClassUtils.getBooleanFromMap(ARGUMENT_EVICT, arguments)
+        }
 
         fireEvent(instance, validatedFieldsList)
 
@@ -95,7 +97,7 @@ class HibernateGormValidationApi<D> extends GormValidationApi<D> {
         errors = filterErrors(errors, validatedFields, instance)
 
         if (errors.hasErrors()) {
-            valid = Boolean.FALSE
+            valid = false
             if (evict) {
                 if (hibernateTemplate.contains(instance)) {
                     hibernateTemplate.evict(instance)
@@ -116,8 +118,8 @@ class HibernateGormValidationApi<D> extends GormValidationApi<D> {
         datastore.getApplicationEventPublisher().publishEvent(event)
     }
 
-    @SuppressWarnings("rawtypes")
-    private Errors filterErrors(Errors errors, Set validatedFields, Object target) {
+    @SuppressWarnings('rawtypes')
+    private static Errors filterErrors(Errors errors, Set validatedFields, Object target) {
         if (validatedFields == null) return errors
 
         ValidationErrors result = new ValidationErrors(target)
@@ -135,7 +137,7 @@ class HibernateGormValidationApi<D> extends GormValidationApi<D> {
         return result
     }
 
-    protected Errors setupErrorsProperty(Object target) {
+    protected static Errors setupErrorsProperty(Object target) {
         HibernateRuntimeUtils.setupErrorsProperty target
     }
 }
diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/HibernateGormValidationApiSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/HibernateGormValidationApiSpec.groovy
new file mode 100644
index 0000000000..f5be2b07ce
--- /dev/null
+++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/HibernateGormValidationApiSpec.groovy
@@ -0,0 +1,121 @@
+/*
+ *  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.orm.hibernate
+
+import grails.gorm.annotation.Entity
+import grails.gorm.transactions.Rollback
+import org.grails.datastore.mapping.core.DatastoreUtils
+import org.grails.orm.hibernate.cfg.Settings
+import org.springframework.core.env.PropertyResolver
+import org.springframework.transaction.PlatformTransactionManager
+import spock.lang.AutoCleanup
+import spock.lang.Shared
+import spock.lang.Specification
+
+class HibernateGormValidationApiSpec extends Specification {
+
+    @Shared PropertyResolver configuration = DatastoreUtils.createPropertyResolver(
+            (Settings.SETTING_DB_CREATE): 'create-drop',
+            'dataSource.url': 'jdbc:h2:mem:validationApiSpec;LOCK_TIMEOUT=10000'
+    )
+    @Shared @AutoCleanup HibernateDatastore hibernateDatastore = new HibernateDatastore(configuration, ValidatedBook)
+    @Shared PlatformTransactionManager transactionManager = hibernateDatastore.getTransactionManager()
+
+    @Rollback
+    void "validate returns true (not a boxed Boolean) for a valid instance"() {
+        given:
+        def book = new ValidatedBook(title: 'Clean Code')
+
+        when:
+        def result = book.validate()
+
+        then:
+        result == true
+        result instanceof Boolean
+        !book.hasErrors()
+    }
+
+    @Rollback
+    void "validate returns false for an invalid instance"() {
+        given:
+        def book = new ValidatedBook(title: null)
+
+        when:
+        def result = book.validate()
+
+        then:
+        result == false
+        book.hasErrors()
+        book.errors.getFieldError('title')
+    }
+
+    @Rollback
+    void "validate with evict:false (default) leaves invalid instance in the session"() {
+        given:
+        def book = new ValidatedBook(title: 'Valid Title').save(flush: true)
+        book.title = null
+        def session = hibernateDatastore.sessionFactory.currentSession
+
+        when:
+        def result = book.validate(evict: false)
+
+        then:
+        result == false
+        session.contains(book)
+    }
+
+    @Rollback
+    void "validate with evict:true removes invalid instance from the session"() {
+        given:
+        def book = new ValidatedBook(title: 'Valid Title').save(flush: true)
+        book.title = null
+        def session = hibernateDatastore.sessionFactory.currentSession
+
+        when:
+        def result = book.validate(evict: true)
+
+        then:
+        result == false
+        !session.contains(book)
+    }
+
+    @Rollback
+    void "validate with specific fields only validates those fields"() {
+        given:
+        def book = new ValidatedBook(title: null, author: null)
+
+        when:
+        def result = book.validate(['author'])
+
+        then:
+        result == true
+        !book.hasErrors()
+    }
+}
+
+@Entity
+class ValidatedBook {
+    String title
+    String author
+
+    static constraints = {
+        title nullable: false
+        author nullable: true
+    }
+}


(grails-core) 17/34: hibernate7: codenarc

Posted by bo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

borinquenkid pushed a commit to branch 8.0.x-hibernate7-dev
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit c4fbe5f0856478f3b6a3bee037fe95c0edd2db16
Author: Walter Duque de Estrada <wb...@mac.com>
AuthorDate: Sat Mar 7 11:54:12 2026 -0600

    hibernate7: codenarc
---
 .../hibernate/support/HibernateRuntimeUtils.groovy | 62 +++++++++++-----------
 1 file changed, 31 insertions(+), 31 deletions(-)

diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/support/HibernateRuntimeUtils.groovy b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/support/HibernateRuntimeUtils.groovy
index edd3afde28..7c6b39223a 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/support/HibernateRuntimeUtils.groovy
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/support/HibernateRuntimeUtils.groovy
@@ -1,20 +1,22 @@
 package org.grails.orm.hibernate.support
 
 import groovy.transform.CompileStatic
-import org.grails.datastore.gorm.GormValidateable
-import org.grails.datastore.mapping.model.config.GormProperties
-import org.grails.datastore.mapping.proxy.ProxyHandler
-import org.grails.datastore.mapping.validation.ValidationErrors
 import org.codehaus.groovy.runtime.StringGroovyMethods
-import org.grails.datastore.mapping.model.PersistentEntity
-import org.grails.datastore.mapping.model.types.Association
-import org.grails.datastore.mapping.model.types.OneToOne
+
 import org.hibernate.Session
 import org.hibernate.SessionFactory
+
 import org.springframework.core.convert.ConversionService
 import org.springframework.validation.Errors
 import org.springframework.validation.FieldError
+import org.springframework.validation.ObjectError
 
+import org.grails.datastore.gorm.GormValidateable
+import org.grails.datastore.mapping.model.PersistentEntity
+import org.grails.datastore.mapping.model.config.GormProperties
+import org.grails.datastore.mapping.model.types.Association
+import org.grails.datastore.mapping.model.types.OneToOne
+import org.grails.datastore.mapping.validation.ValidationErrors
 /**
  * Utility methods used at runtime by the GORM for Hibernate implementation
  *
@@ -24,14 +26,14 @@ import org.springframework.validation.FieldError
 @CompileStatic
 class HibernateRuntimeUtils {
 
-    private static final String DYNAMIC_FILTER_ENABLER = "dynamicFilterEnabler";
+    private static final String DYNAMIC_FILTER_ENABLER = "dynamicFilterEnabler"
 
     @SuppressWarnings("rawtypes")
-    public static void enableDynamicFilterEnablerIfPresent(SessionFactory sessionFactory, Session session) {
+    static void enableDynamicFilterEnablerIfPresent(SessionFactory sessionFactory, Session session) {
         if (sessionFactory != null && session != null) {
-            final Set definedFilterNames = sessionFactory.getDefinedFilterNames();
+            final Set definedFilterNames = sessionFactory.getDefinedFilterNames()
             if (definedFilterNames != null && definedFilterNames.contains(DYNAMIC_FILTER_ENABLER))
-                session.enableFilter(DYNAMIC_FILTER_ENABLER); // work around for HHH-2624
+                session.enableFilter(DYNAMIC_FILTER_ENABLER) // work around for HHH-2624
         }
     }
 
@@ -43,14 +45,14 @@ class HibernateRuntimeUtils {
      * @param target object to initialize
      * @return the new Errors object
      */
-    public static Errors setupErrorsProperty(Object target) {
+    static Errors setupErrorsProperty(Object target) {
 
+        MetaClass metaClass = GroovySystem.metaClassRegistry.getMetaClass(target.getClass())
         boolean isGormValidateable = target instanceof GormValidateable
 
-        MetaClass mc = isGormValidateable ? null : GroovySystem.metaClassRegistry.getMetaClass(target.getClass())
         def errors = new ValidationErrors(target)
 
-        Errors originalErrors = isGormValidateable ? ((GormValidateable)target).getErrors() : (Errors) mc.getProperty(target, GormProperties.ERRORS)
+        Errors originalErrors = isGormValidateable ? ((GormValidateable)target).getErrors() : (Errors) metaClass.getProperty(target, GormProperties.ERRORS)
         // Copy binding failures and any existing object-level errors
         for (Object o in originalErrors.allErrors) {
             if (o instanceof FieldError) {
@@ -65,7 +67,7 @@ class HibernateRuntimeUtils {
                             fe.defaultMessage))
                 }
             } else {
-                errors.addError((org.springframework.validation.ObjectError) o)
+                errors.addError((ObjectError) o)
             }
         }
 
@@ -73,12 +75,12 @@ class HibernateRuntimeUtils {
             ((GormValidateable)target).setErrors(errors)
         }
         else {
-            mc.setProperty(target, GormProperties.ERRORS, errors);
+            metaClass.setProperty(target, GormProperties.ERRORS, errors)
         }
-        return errors;
+        return errors
     }
 
-    public static void autoAssociateBidirectionalOneToOnes(PersistentEntity entity, Object target) {
+    static void autoAssociateBidirectionalOneToOnes(PersistentEntity entity, Object target) {
         def mappingContext = entity.mappingContext
         for (Association association :  entity.associations) {
             if (!(association instanceof OneToOne) || !association.bidirectional || !association.owningSide) {
@@ -111,36 +113,34 @@ class HibernateRuntimeUtils {
         }
     }
 
-    static Object convertValueToType(Object passedValue, Class targetType, ConversionService conversionService) {
-        // workaround for GROOVY-6127, do not assign directly in parameters before it's fixed
-        Object value = passedValue
-        if(targetType != null && value != null && !(value in targetType)) {
+    static Object convertValueToType(Object value, Class targetType, ConversionService conversionService) {
+        if (targetType != null && value != null && !targetType.isInstance(value)) {
             if (value instanceof CharSequence) {
                 value = value.toString()
-                if(value in targetType) {
+                if (targetType.isInstance(value)) {
                     return value
                 }
             }
             try {
-                if (value instanceof Number && (targetType==Long || targetType==Integer)) {
-                    if(targetType == Long) {
-                        value = ((Number)value).toLong()
+                if (value instanceof Number && (targetType == Long || targetType == Integer)) {
+                    if (targetType == Long) {
+                        value = ((Number) value).toLong()
                     } else {
-                        value = ((Number)value).toInteger()
+                        value = ((Number) value).toInteger()
                     }
-                } else if (value instanceof String && targetType in Number) {
+                } else if (value instanceof String && Number.isAssignableFrom(targetType)) {
                     String strValue = value.trim()
-                    if(targetType == Long) {
+                    if (targetType == Long) {
                         value = Long.parseLong(strValue)
                     } else if (targetType == Integer) {
                         value = Integer.parseInt(strValue)
                     } else {
-                        value = StringGroovyMethods.asType(strValue, targetType)
+                        value = StringGroovyMethods.asType(strValue, targetType as Class<Object>)
                     }
                 } else {
                     value = conversionService.convert(value, targetType)
                 }
-            } catch (e) {
+            } catch (ignored) {
                 // ignore
             }
         }


(grails-core) 03/34: hibernate7: clean up GrailsHibernateTemplate

Posted by bo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

borinquenkid pushed a commit to branch 8.0.x-hibernate7-dev
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit 4bc5c19e7544b72aa164c5aec23b9beb6111ff1e
Author: Walter Duque de Estrada <wb...@mac.com>
AuthorDate: Thu Mar 5 16:18:32 2026 -0600

    hibernate7: clean up GrailsHibernateTemplate
---
 .../orm/hibernate/GrailsHibernateTemplate.java     | 124 +++++----------------
 1 file changed, 30 insertions(+), 94 deletions(-)

diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/GrailsHibernateTemplate.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/GrailsHibernateTemplate.java
index 41abd6a36b..c75a101bb5 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/GrailsHibernateTemplate.java
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/GrailsHibernateTemplate.java
@@ -23,17 +23,15 @@ import jakarta.persistence.LockModeType;
 import jakarta.persistence.PersistenceException;
 import jakarta.persistence.criteria.CriteriaBuilder;
 import jakarta.persistence.criteria.CriteriaQuery;
-import jakarta.persistence.criteria.Root;
 import java.io.Serializable;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
 import java.sql.Connection;
 import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
+import java.util.Objects;
+
 import javax.sql.DataSource;
 import org.codehaus.groovy.runtime.DefaultGroovyMethods;
 import org.hibernate.*;
@@ -96,10 +94,13 @@ public class GrailsHibernateTemplate implements IHibernateTemplate {
         ((SessionFactoryImplementor) sessionFactory)
             .getServiceRegistry()
             .getService(ConnectionProvider.class);
-    this.dataSource = connectionProvider.unwrap(DataSource.class);
+    this.dataSource = connectionProvider != null ? connectionProvider.unwrap(DataSource.class) : null;
     if (this.dataSource != null) {
       if (this.dataSource instanceof TransactionAwareDataSourceProxy) {
-        this.dataSource = ((TransactionAwareDataSourceProxy) this.dataSource).getTargetDataSource();
+        DataSource target = ((TransactionAwareDataSourceProxy) this.dataSource).getTargetDataSource();
+        if (target != null) {
+          this.dataSource = target;
+        }
       }
       jdbcExceptionTranslator = new SQLErrorCodeSQLExceptionTranslator(this.dataSource);
     } else {
@@ -134,12 +135,12 @@ public class GrailsHibernateTemplate implements IHibernateTemplate {
 
   /** Maps a Hibernate {@link FlushMode} to one of the {@code FLUSH_*} constants of this class. */
   static int hibernateFlushModeToConstant(FlushMode mode) {
-    switch (mode) {
-      case MANUAL: return FLUSH_NEVER;
-      case COMMIT: return FLUSH_COMMIT;
-      case ALWAYS: return FLUSH_ALWAYS;
-      default: return FLUSH_AUTO;
-    }
+      return switch (mode) {
+          case MANUAL -> FLUSH_NEVER;
+          case COMMIT -> FLUSH_COMMIT;
+          case ALWAYS -> FLUSH_ALWAYS;
+          default -> FLUSH_AUTO;
+      };
   }
 
   @Override
@@ -188,7 +189,7 @@ public class GrailsHibernateTemplate implements IHibernateTemplate {
       sessionHolder = new SessionHolder(newSession);
       TransactionSynchronizationManager.bindResource(sessionFactory, sessionHolder);
 
-      return execute(callable::call);
+      return callable.call(newSession);
     } finally {
       try {
         // if an active synchronization was registered during the life time of the new session clear
@@ -259,7 +260,7 @@ public class GrailsHibernateTemplate implements IHibernateTemplate {
   }
 
   @Override
-  public void applySettings(org.hibernate.query.Query query) {
+  public void applySettings(org.hibernate.query.Query<?> query) {
     if (exposeNativeSession) {
       prepareQuery(query);
     }
@@ -348,10 +349,7 @@ public class GrailsHibernateTemplate implements IHibernateTemplate {
       }
       throw ex;
     } catch (SQLException ex) {
-      throw jdbcExceptionTranslator.translate("Hibernate-related JDBC operation", null, ex);
-    } catch (RuntimeException ex) {
-      // Callback code threw application exception...
-      throw ex;
+      throw Objects.requireNonNull(jdbcExceptionTranslator.translate("Hibernate-related JDBC operation", null, ex));
     } finally {
       if (existingTransaction) {
         LOG.debug("Not closing pre-bound Hibernate Session after HibernateTemplate");
@@ -403,7 +401,7 @@ public class GrailsHibernateTemplate implements IHibernateTemplate {
         Proxy.newProxyInstance(
             Thread.currentThread().getContextClassLoader(),
             sessionIfcs,
-            new CloseSuppressingInvocationHandler(session));
+            new CloseSuppressingInvocationHandler(session, this));
   }
 
   @Deprecated(since = "7.0", forRemoval = true)
@@ -425,14 +423,6 @@ public class GrailsHibernateTemplate implements IHibernateTemplate {
         true);
   }
 
-  public void flush(final Object entity) throws DataAccessException {
-    doExecute(
-        session -> {
-          session.flush();
-          return null;
-        },
-        true);
-  }
 
   public <T> T load(final Class<T> entityClass, final Serializable id) throws DataAccessException {
     return doExecute(session -> session.getReference(entityClass, id), true);
@@ -448,7 +438,7 @@ public class GrailsHibernateTemplate implements IHibernateTemplate {
         session -> {
           final CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
           final CriteriaQuery<T> query = criteriaBuilder.createQuery(entityClass);
-          final Root<T> root = query.from(entityClass);
+          query.from(entityClass);
           final Query<T> jpaQuery = session.createQuery(query);
           prepareCriteria(jpaQuery);
           return jpaQuery.getResultList();
@@ -508,7 +498,11 @@ public class GrailsHibernateTemplate implements IHibernateTemplate {
    *
    * @param query the Query object to prepare
    */
-  protected void prepareQuery(org.hibernate.query.Query query) {
+  void prepareQuery(org.hibernate.query.Query<?> query) {
+    internalQuery(query);
+  }
+
+  private void internalQuery(Query<?> query) {
     if (cacheQueries) {
       query.setCacheable(true);
     }
@@ -527,72 +521,13 @@ public class GrailsHibernateTemplate implements IHibernateTemplate {
    *
    * @param jpaQuery the Query object to prepare
    */
-  protected <T> void prepareCriteria(Query<T> jpaQuery) {
-    if (cacheQueries) {
-      jpaQuery.setCacheable(true);
-    }
-    if (shouldPassReadOnlyToHibernate()) {
-      jpaQuery.setReadOnly(true);
-    }
-    SessionHolder sessionHolder =
-        (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
-    if (sessionHolder != null && sessionHolder.hasTimeout()) {
-      jpaQuery.setTimeout(sessionHolder.getTimeToLiveInSeconds());
-    }
-  }
-
-  /**
-   * Invocation handler that suppresses close calls on Hibernate Sessions. Also prepares returned
-   * Query and Criteria objects.
-   *
-   * @see org.hibernate.Session#close
-   */
-  protected class CloseSuppressingInvocationHandler implements InvocationHandler {
-
-    protected final Session target;
-
-    protected CloseSuppressingInvocationHandler(Session target) {
-      this.target = target;
-    }
-
-    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
-      // Invocation on Session interface coming in...
-
-      if (method.getName().equals("equals")) {
-        // Only consider equal when proxies are identical.
-        return (proxy == args[0]);
-      }
-      if (method.getName().equals("hashCode")) {
-        // Use hashCode of Session proxy.
-        return System.identityHashCode(proxy);
-      }
-      if (method.getName().equals("close")) {
-        // Handle close method: suppress, not valid.
-        return null;
-      }
-
-      // Invoke method on target Session.
-      try {
-        Object retVal = method.invoke(target, args);
-
-        // If return value is a Query or Criteria, apply transaction timeout.
-        // Applies to createQuery, getNamedQuery, createCriteria.
-        if (retVal instanceof org.hibernate.query.Query) {
-          prepareQuery(((org.hibernate.query.Query) retVal));
-        }
-        if (retVal instanceof Query) {
-          prepareCriteria(((Query) retVal));
-        }
-
-        return retVal;
-      } catch (InvocationTargetException ex) {
-        throw ex.getTargetException();
-      }
-    }
+  <T> void prepareCriteria(Query<T> jpaQuery) {
+    internalQuery(jpaQuery);
   }
 
-  /**
-   * Never flush is a good strategy for read-only units of work. Hibernate will not track and look
+    /**
+    * Never flush is a good strategy for read-only units of work.
+ Hibernate will not track and look
    * for changes in this case, avoiding any overhead of modification detection.
    *
    * <p>In case of an existing Session, FLUSH_NEVER will turn the flush mode to NEVER for the scope
@@ -698,7 +633,8 @@ public class GrailsHibernateTemplate implements IHibernateTemplate {
         session.setHibernateFlushMode(FlushMode.MANUAL);
       }
     } else if (getFlushMode() == FLUSH_EAGER) {
-      if (existingTransaction) {
+        //noinspection StatementWithEmptyBody
+        if (existingTransaction) {
         FlushMode previousFlushMode = session.getHibernateFlushMode();
         if (!previousFlushMode.equals(FlushMode.AUTO)) {
           session.setHibernateFlushMode(FlushMode.AUTO);


(grails-core) 33/34: hibernate7: added cache and readOnly support to CriteriaMethodInvoker

Posted by bo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

borinquenkid pushed a commit to branch 8.0.x-hibernate7-dev
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit cd5579f94b6731bc5b3753e915e3317448eded3c
Author: Walter Duque de Estrada <wb...@mac.com>
AuthorDate: Sun Mar 8 12:28:34 2026 -0500

    hibernate7:
    added cache and readOnly support to CriteriaMethodInvoker
---
 .../groovy/grails/orm/CriteriaMethodInvoker.java   | 36 +++++++++++++---------
 .../main/groovy/grails/orm/CriteriaMethods.java    |  4 ++-
 .../grails/orm/HibernateCriteriaBuilder.java       |  3 +-
 .../grails/orm/hibernate/cfg/IdentityEnumType.java |  1 -
 .../grails/orm/CriteriaMethodInvokerSpec.groovy    | 16 ++++++++++
 5 files changed, 42 insertions(+), 18 deletions(-)

diff --git a/grails-data-hibernate7/core/src/main/groovy/grails/orm/CriteriaMethodInvoker.java b/grails-data-hibernate7/core/src/main/groovy/grails/orm/CriteriaMethodInvoker.java
index 6a7ac3aee5..5b28247255 100644
--- a/grails-data-hibernate7/core/src/main/groovy/grails/orm/CriteriaMethodInvoker.java
+++ b/grails-data-hibernate7/core/src/main/groovy/grails/orm/CriteriaMethodInvoker.java
@@ -82,7 +82,7 @@ public class CriteriaMethodInvoker {
     // Check for pagination params
     if (method == CriteriaMethods.LIST_CALL && args.length == 2) {
       builder.setPaginationEnabledList(true);
-      if (args[0] instanceof Map map) {
+      if (args[0] instanceof Map<?, ?> map) {
         if (map.get("max") instanceof Number max) {
           hibernateQuery.maxResults(max.intValue());
         }
@@ -104,7 +104,7 @@ public class CriteriaMethodInvoker {
         hibernateQuery.projections().count();
         result = hibernateQuery.singleResult();
       } else if (builder.isPaginationEnabledList()) {
-        Map argMap = (Map) args[0];
+        Map<?, ?> argMap = (Map<?, ?>) args[0];
         final String sortField = (String) argMap.get(HibernateQueryArgument.SORT.value());
         if (sortField != null) {
           final boolean ignoreCase =
@@ -115,13 +115,11 @@ public class CriteriaMethodInvoker {
                   ? Query.Order.Direction.DESC
                   : Query.Order.Direction.ASC;
           Query.Order order;
-          if (ignoreCase) {
-            order = new Query.Order(sortField, direction);
-            order.ignoreCase();
-          } else {
             order = new Query.Order(sortField, direction);
+            if (ignoreCase) {
+                order.ignoreCase();
           }
-          hibernateQuery.order(order);
+            hibernateQuery.order(order);
         }
         result = new PagedResultList<>(hibernateQuery);
       } else if (builder.isScroll()) {
@@ -153,7 +151,7 @@ public class CriteriaMethodInvoker {
     }
 
     final boolean hasMoreThanOneArg = args.length > 1;
-    final Closure callable = hasMoreThanOneArg ? (Closure) args[1] : (Closure) args[0];
+    final Closure<?> callable = hasMoreThanOneArg ? (Closure<?>) args[1] : (Closure<?>) args[0];
     final HibernateQuery hibernateQuery = builder.getHibernateQuery();
 
     if (method != null) {
@@ -185,7 +183,7 @@ public class CriteriaMethodInvoker {
       final Attribute<?, ?> attribute = entityType.getAttribute(name);
 
       if (attribute.isAssociation()) {
-        Class oldTargetClass = builder.getTargetClass();
+        Class<?> oldTargetClass = builder.getTargetClass();
         builder.setTargetClass(builder.getClassForAssociationType(attribute));
         JoinType joinType;
         if (hasMoreThanOneArg) {
@@ -197,7 +195,7 @@ public class CriteriaMethodInvoker {
         }
 
         hibernateQuery.join(name, joinType);
-        hibernateQuery.in(name, new DetachedCriteria(builder.getTargetClass()).build(callable));
+        hibernateQuery.in(name, new DetachedCriteria<>(builder.getTargetClass()).build(callable));
         builder.setTargetClass(oldTargetClass);
 
         return name;
@@ -216,6 +214,16 @@ public class CriteriaMethodInvoker {
       switch (method) {
         case ID_EQUALS:
           return builder.eq("id", args[0]);
+        case CACHE:
+          if (args[0] instanceof Boolean b) {
+            builder.cache(b);
+          }
+          return name;
+        case READ_ONLY:
+          if (args[0] instanceof Boolean b) {
+            builder.readOnly(b);
+          }
+          return name;
         case IS_NULL, IS_NOT_NULL, IS_EMPTY, IS_NOT_EMPTY:
           if (!(args[0] instanceof String)) {
             builder.throwRuntimeException(
@@ -261,8 +269,8 @@ public class CriteriaMethodInvoker {
         }
         break;
       case EQUALS:
-        if (args.length == 3 && args[2] instanceof Map) {
-          return builder.eq(propertyName, args[1], (Map) args[2]);
+        if (args.length == 3 && args[2] instanceof Map<?, ?> map) {
+          return builder.eq(propertyName, args[1], map);
         }
         return builder.eq(propertyName, args[1]);
       case EQUALS_PROPERTY:
@@ -279,7 +287,7 @@ public class CriteriaMethodInvoker {
         return builder.ilike(propertyName, args[1]);
       case IN:
         if (args[1] instanceof Collection) {
-          return builder.in(propertyName, (Collection) args[1]);
+          return builder.in(propertyName, (Collection<?>) args[1]);
         } else if (args[1] instanceof Object[]) {
           return builder.in(propertyName, (Object[]) args[1]);
         }
@@ -320,7 +328,7 @@ public class CriteriaMethodInvoker {
   private boolean isCriteriaConstructionMethod(CriteriaMethods method, Object... args) {
     return (method == CriteriaMethods.LIST_CALL
             && args.length == 2
-            && args[0] instanceof Map
+            && args[0] instanceof Map<?, ?>
             && args[1] instanceof Closure)
         || (method == CriteriaMethods.ROOT_CALL
             || method == CriteriaMethods.ROOT_DO_CALL
diff --git a/grails-data-hibernate7/core/src/main/groovy/grails/orm/CriteriaMethods.java b/grails-data-hibernate7/core/src/main/groovy/grails/orm/CriteriaMethods.java
index 11e81c6609..46d0f4b35f 100644
--- a/grails-data-hibernate7/core/src/main/groovy/grails/orm/CriteriaMethods.java
+++ b/grails-data-hibernate7/core/src/main/groovy/grails/orm/CriteriaMethods.java
@@ -57,7 +57,9 @@ public enum CriteriaMethods {
   COUNT_CALL("count"),
   GET_CALL("get"),
   SCROLL_CALL("scroll"),
-  PROJECTIONS("projections");
+  PROJECTIONS("projections"),
+  CACHE("cache"),
+  READ_ONLY("readOnly");
 
   private final String name;
 
diff --git a/grails-data-hibernate7/core/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java b/grails-data-hibernate7/core/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java
index 99eba287aa..62221c4df1 100644
--- a/grails-data-hibernate7/core/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java
+++ b/grails-data-hibernate7/core/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java
@@ -870,8 +870,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    *     supported.
    * @return A Criterion instance
    */
-  @SuppressWarnings("rawtypes")
-  public Criteria eq(String propertyName, Object propertyValue, Map params) {
+  public Criteria eq(String propertyName, Object propertyValue, Map<?,?> params) {
     if (Boolean.TRUE.equals(params.get("ignoreCase"))) {
       hibernateQuery.like(propertyName, "%" + propertyValue.toString() + "%");
     } else {
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/IdentityEnumType.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/IdentityEnumType.java
index 47210825f2..8e584fb168 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/IdentityEnumType.java
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/IdentityEnumType.java
@@ -102,7 +102,6 @@ public class IdentityEnumType implements UserType, ParameterizedType, Serializab
     }
   }
 
-  @Override
   public int[] getSqlTypes() {
     return sqlTypes != null ? sqlTypes.clone() : null;
   }
diff --git a/grails-data-hibernate7/core/src/test/groovy/grails/orm/CriteriaMethodInvokerSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/grails/orm/CriteriaMethodInvokerSpec.groovy
index a0f8e7e560..978c64532c 100644
--- a/grails-data-hibernate7/core/src/test/groovy/grails/orm/CriteriaMethodInvokerSpec.groovy
+++ b/grails-data-hibernate7/core/src/test/groovy/grails/orm/CriteriaMethodInvokerSpec.groovy
@@ -179,6 +179,22 @@ class CriteriaMethodInvokerSpec extends Specification {
         1 * builder.eq('id', 42L)
     }
 
+    void "trySimpleCriteria: cache delegates to builder.cache"() {
+        when:
+        invoker.trySimpleCriteria('cache', CriteriaMethods.CACHE, [true] as Object[])
+
+        then:
+        1 * builder.cache(true)
+    }
+
+    void "trySimpleCriteria: readOnly delegates to builder.readOnly"() {
+        when:
+        invoker.trySimpleCriteria('readOnly', CriteriaMethods.READ_ONLY, [true] as Object[])
+
+        then:
+        1 * builder.readOnly(true)
+    }
+
     void "trySimpleCriteria: isNull with String delegates to hibernateQuery.isNull"() {
         when:
         invoker.trySimpleCriteria('isNull', CriteriaMethods.IS_NULL, ['branch'] as Object[])


(grails-core) 09/34: hibernate7: cleanup update MapSecondPassBinderSpec

Posted by bo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

borinquenkid pushed a commit to branch 8.0.x-hibernate7-dev
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit dace1829201ecb7b1f9cdeefabe3e0f4ff6b11f1
Author: Walter Duque de Estrada <wb...@mac.com>
AuthorDate: Thu Mar 5 22:13:18 2026 -0600

    hibernate7: cleanup update MapSecondPassBinderSpec
---
 .../cfg/HibernateMappingContextConfiguration.java  | 38 ++++++++++++++--------
 .../secondpass/MapSecondPassBinderSpec.groovy      | 26 +++++++++++++--
 2 files changed, 48 insertions(+), 16 deletions(-)

diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateMappingContextConfiguration.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateMappingContextConfiguration.java
index 12011f907c..ae84343985 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateMappingContextConfiguration.java
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateMappingContextConfiguration.java
@@ -18,10 +18,13 @@
  */
 package org.grails.orm.hibernate.cfg;
 
+import jakarta.annotation.Nullable;
 import jakarta.persistence.Embeddable;
 import jakarta.persistence.Entity;
 import jakarta.persistence.MappedSuperclass;
 import java.io.IOException;
+import java.io.Serial;
+import java.io.Serializable;
 import java.util.*;
 import javax.sql.DataSource;
 import org.grails.datastore.gorm.GormEntity;
@@ -78,7 +81,8 @@ import org.springframework.util.ClassUtils;
   "PMD.CloseResource"
 })
 public class HibernateMappingContextConfiguration extends Configuration
-    implements ApplicationContextAware {
+        implements ApplicationContextAware, Serializable {
+  @Serial
   private static final long serialVersionUID = -7115087342689305517L;
 
   private static final String RESOURCE_PATTERN = "/**/*.class";
@@ -93,21 +97,21 @@ public class HibernateMappingContextConfiguration extends Configuration
   protected String sessionFactoryBeanName = "sessionFactory";
   protected String dataSourceName = ConnectionSource.DEFAULT;
   protected HibernateMappingContext hibernateMappingContext;
-  private Class<? extends CurrentSessionContext> currentSessionContext = GrailsSessionContext.class;
+  private final Class<? extends CurrentSessionContext> currentSessionContext = GrailsSessionContext.class;
   private HibernateEventListeners hibernateEventListeners;
   private Map<String, Object> eventListeners;
   private ServiceRegistry serviceRegistry;
   private ResourcePatternResolver resourcePatternResolver =
       new PathMatchingResourcePatternResolver();
   //    private MetadataContributor metadataContributor;
-  private Set<Class> additionalClasses = new HashSet<>();
+  private final Set<Class> additionalClasses = new HashSet<>();
 
   public void setHibernateMappingContext(HibernateMappingContext hibernateMappingContext) {
     this.hibernateMappingContext = hibernateMappingContext;
   }
 
   @Override
-  public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+  public void setApplicationContext(@Nullable ApplicationContext applicationContext) throws BeansException {
     resourcePatternResolver = ResourcePatternUtils.getResourcePatternResolver(applicationContext);
     String dsName =
         ConnectionSource.DEFAULT.equals(dataSourceName)
@@ -115,11 +119,16 @@ public class HibernateMappingContextConfiguration extends Configuration
             : "dataSource_" + dataSourceName;
     Properties properties = getProperties();
 
-    if (applicationContext.containsBean(dsName)) {
-      properties.put(JdbcSettings.JAKARTA_NON_JTA_DATASOURCE, applicationContext.getBean(dsName));
+    if (applicationContext != null) {
+      if (applicationContext.containsBean(dsName)) {
+        properties.put(JdbcSettings.JAKARTA_NON_JTA_DATASOURCE, applicationContext.getBean(dsName));
+      }
+      properties.put(Environment.CURRENT_SESSION_CONTEXT_CLASS, currentSessionContext.getName());
+      ClassLoader classLoader = applicationContext.getClassLoader();
+      if (classLoader != null) {
+        properties.put(AvailableSettings.CLASSLOADERS, classLoader);
+      }
     }
-    properties.put(Environment.CURRENT_SESSION_CONTEXT_CLASS, currentSessionContext.getName());
-    properties.put(AvailableSettings.CLASSLOADERS, applicationContext.getClassLoader());
   }
 
   /**
@@ -200,7 +209,11 @@ public class HibernateMappingContextConfiguration extends Configuration
             MetadataReader reader = readerFactory.getMetadataReader(resource);
             String className = reader.getClassMetadata().getClassName();
             if (matchesFilter(reader, readerFactory)) {
-              Class<?> loadedClass = resourcePatternResolver.getClassLoader().loadClass(className);
+              ClassLoader classLoader = resourcePatternResolver.getClassLoader();
+              Class<?> loadedClass =
+                  classLoader != null
+                      ? classLoader.loadClass(className)
+                      : ClassUtils.forName(className, null);
               addAnnotatedClasses(loadedClass);
             }
           }
@@ -276,7 +289,7 @@ public class HibernateMappingContextConfiguration extends Configuration
       }
     }
 
-    addAnnotatedClasses(annotatedClasses.toArray(new Class[annotatedClasses.size()]));
+    addAnnotatedClasses(annotatedClasses.toArray(new Class[0]));
 
     ClassLoaderService classLoaderService =
         new ClassLoaderServiceImpl(appClassLoader) {
@@ -302,11 +315,10 @@ public class HibernateMappingContextConfiguration extends Configuration
 
     SessionFactoryObserver sessionFactoryObserver =
         new SessionFactoryObserver() {
+          @Serial
           private static final long serialVersionUID = 1;
 
-          public void sessionFactoryCreated(SessionFactory factory) {}
-
-          public void sessionFactoryClosed(SessionFactory factory) {
+            public void sessionFactoryClosed(SessionFactory factory) {
             if (serviceRegistry != null) {
               ((ServiceRegistryImplementor) serviceRegistry).destroy();
             }
diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/MapSecondPassBinderSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/MapSecondPassBinderSpec.groovy
index 17c37ff7d5..6df8a1aa53 100644
--- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/MapSecondPassBinderSpec.groovy
+++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/MapSecondPassBinderSpec.groovy
@@ -172,19 +172,34 @@ class MapSecondPassBinderSpec extends HibernateGormDatastoreSpec {
         def mapBinder = collectionBinder.mapSecondPassBinder
 
         def authorEntity = getPersistentEntity(MSBAuthor) as GrailsHibernatePersistentEntity
+        def bookEntity = getPersistentEntity(MSBBook) as GrailsHibernatePersistentEntity
         def booksProp = authorEntity.getPropertyByName("books") as HibernateToManyProperty
 
         def rootClass = new RootClass(metadataBuildingContext)
         rootClass.setEntityName(authorEntity.name)
+        rootClass.setClassName(authorEntity.name)
+        rootClass.setJpaEntityName(authorEntity.name)
         rootClass.setTable(collector.addTable(null, null, "MSB_AUTHOR", null, false, metadataBuildingContext))
         collector.addEntityBinding(rootClass)
 
+        def bookRootClass = new RootClass(metadataBuildingContext)
+        bookRootClass.setEntityName(bookEntity.name)
+        bookRootClass.setClassName(bookEntity.name)
+        bookRootClass.setJpaEntityName(bookEntity.name)
+        bookRootClass.setTable(collector.addTable(null, null, "MSB_BOOK", null, false, metadataBuildingContext))
+        collector.addEntityBinding(bookRootClass)
+
+        def persistentClasses = [
+            (authorEntity.name): rootClass,
+            (bookEntity.name): bookRootClass
+        ]
+
         def map = new org.hibernate.mapping.Map(metadataBuildingContext, rootClass)
         map.setRole("${authorEntity.name}.books".toString())
         map.setCollectionTable(rootClass.getTable())
 
         when:
-        mapBinder.bindMapSecondPass(booksProp, collector, [:], map)
+        mapBinder.bindMapSecondPass(booksProp, collector, persistentClasses, map)
 
         then:
         noExceptionThrown()
@@ -205,15 +220,20 @@ class MapSecondPassBinderSpec extends HibernateGormDatastoreSpec {
         def mapBinder = collectionBinder.mapSecondPassBinder
 
         def authorEntity = getPersistentEntity(MSBAuthor) as GrailsHibernatePersistentEntity
+        def bookEntity = getPersistentEntity(MSBBook) as GrailsHibernatePersistentEntity
         def booksProp = authorEntity.getPropertyByName("books") as HibernateToManyProperty
 
         def rootClass = new RootClass(metadataBuildingContext)
         rootClass.setEntityName(authorEntity.name)
+        rootClass.setClassName(authorEntity.name)
+        rootClass.setJpaEntityName(authorEntity.name)
         rootClass.setTable(collector.addTable(null, null, "MSB_AUTHOR", null, false, metadataBuildingContext))
         collector.addEntityBinding(rootClass)
 
         def bookRootClass = new RootClass(metadataBuildingContext)
-        bookRootClass.setEntityName(MSBBook.name)
+        bookRootClass.setEntityName(bookEntity.name)
+        bookRootClass.setClassName(bookEntity.name)
+        bookRootClass.setJpaEntityName(bookEntity.name)
         bookRootClass.setTable(collector.addTable(null, null, "MSB_BOOK", null, false, metadataBuildingContext))
         collector.addEntityBinding(bookRootClass)
 
@@ -237,7 +257,7 @@ class MapSecondPassBinderSpec extends HibernateGormDatastoreSpec {
         noExceptionThrown()
         map.index != null
         map.index.isTypeSpecified()
-        map.index.getColumnIterator().next().name == "BOOK_TITLE"
+        map.index.getColumns()[0].name == "books_idx"
     }
 }
 


(grails-core) 12/34: hibernate7: Refactoring GrailsHibernateQueryUtils and HibernateGormStaticApi

Posted by bo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

borinquenkid pushed a commit to branch 8.0.x-hibernate7-dev
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit d5de3307bf8d3cf0b487b9b98ba59bf51c0fe5ab
Author: Walter Duque de Estrada <wb...@mac.com>
AuthorDate: Fri Mar 6 08:24:52 2026 -0600

    hibernate7: Refactoring GrailsHibernateQueryUtils and HibernateGormStaticApi
---
 .../orm/hibernate/HibernateGormStaticApi.groovy    | 52 ++++++++--------------
 .../hibernate/query/GrailsHibernateQueryUtils.java | 14 +++---
 .../query/GrailsHibernateQueryUtilsSpec.groovy     | 10 +++--
 3 files changed, 32 insertions(+), 44 deletions(-)

diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy
index d37bba3881..f65b874bbe 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy
@@ -65,6 +65,7 @@ class HibernateGormStaticApi<D> extends GormStaticApi<D> {
     protected final HibernateSession hibernateSession
     protected ProxyHandler proxyHandler
     protected SessionFactory sessionFactory
+    protected GrailsHibernateQueryUtils queryUtils
     protected Class identityType
     protected ClassLoader classLoader
     private HibernateGormInstanceApi<D> instanceApi
@@ -75,6 +76,7 @@ class HibernateGormStaticApi<D> extends GormStaticApi<D> {
         this.hibernateTemplate = new GrailsHibernateTemplate(datastore.getSessionFactory(), datastore)
         this.conversionService = datastore.mappingContext.conversionService
         this.proxyHandler = datastore.mappingContext.proxyHandler
+        this.queryUtils = new GrailsHibernateQueryUtils()
         this.hibernateSession = new HibernateSession(
                 (HibernateDatastore)datastore,
                 hibernateTemplate.getSessionFactory()
@@ -310,14 +312,10 @@ class HibernateGormStaticApi<D> extends GormStaticApi<D> {
     }
 
     @SuppressWarnings('GroovyAssignabilityCheck')
-    private List<D> doListInternal(CharSequence hql,
-                                   Map namedParams,
-                                   Collection positionalParams,
-                                   Map args
-                                   , boolean isNative) {
-        boolean isUpdate = false
+    private HibernateHqlQuery prepareHqlQuery(CharSequence hql, boolean isNative, boolean isUpdate,
+                                              Map namedParams, Collection positionalParams, Map args) {
         def ctx = HqlQueryContext.prepare(hql, isNative, isUpdate, namedParams, persistentEntity)
-        def hqlQuery = HibernateHqlQuery.createHqlQuery(
+        return HibernateHqlQuery.createHqlQuery(
                 (HibernateDatastore) datastore,
                 sessionFactory,
                 persistentEntity,
@@ -326,6 +324,14 @@ class HibernateGormStaticApi<D> extends GormStaticApi<D> {
                 positionalParams,
                 getHibernateTemplate()
         )
+    }
+
+    private List<D> doListInternal(CharSequence hql,
+                                   Map namedParams,
+                                   Collection positionalParams,
+                                   Map args
+                                   , boolean isNative) {
+        def hqlQuery = prepareHqlQuery(hql, isNative, false, namedParams, positionalParams, args)
         firePreQueryEvent()
         def ds = (List<D>) hqlQuery.list()
         firePostQueryEvent(ds)
@@ -338,17 +344,7 @@ class HibernateGormStaticApi<D> extends GormStaticApi<D> {
                                Collection positionalParams,
                                Map args
                                , boolean isNative) {
-        boolean isUpdate = false
-        def ctx = HqlQueryContext.prepare(hql, isNative, isUpdate, namedParams, persistentEntity)
-        def hqlQuery = HibernateHqlQuery.createHqlQuery(
-                (HibernateDatastore) datastore,
-                sessionFactory,
-                persistentEntity,
-                ctx,
-                args,
-                positionalParams,
-                getHibernateTemplate()
-        )
+        def hqlQuery = prepareHqlQuery(hql, isNative, false, namedParams, positionalParams, args)
         firePreQueryEvent()
         def sm = hqlQuery.singleResult()
         firePostQueryEvent(sm)
@@ -359,18 +355,7 @@ class HibernateGormStaticApi<D> extends GormStaticApi<D> {
                                             Map namedParams,
                                             Collection positionalParams,
                                             Map args) {
-        boolean isNative = false
-        boolean isUpdate  = true
-        def ctx = HqlQueryContext.prepare(hql, isNative, isUpdate, namedParams, persistentEntity)
-        def hqlQuery = HibernateHqlQuery.createHqlQuery(
-                (HibernateDatastore) datastore,
-                sessionFactory,
-                persistentEntity,
-                ctx,
-                args,
-                positionalParams,
-                getHibernateTemplate()
-        )
+        def hqlQuery = prepareHqlQuery(hql, false, true, namedParams, positionalParams, args)
         firePreQueryEvent()
         def execute = hqlQuery.executeUpdate()
         firePostQueryEvent(execute)
@@ -476,8 +461,8 @@ class HibernateGormStaticApi<D> extends GormStaticApi<D> {
         hibernateTemplate.execute { Session session ->
             CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder()
             CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(persistentEntity.javaClass)
-            Root queryRoot = criteriaQuery.from(persistentEntity.javaClass)
-            GrailsHibernateQueryUtils.populateArgumentsForCriteria(
+            var queryRoot = criteriaQuery.from(persistentEntity.javaClass)
+            queryUtils.populateArgumentsForCriteria(
                     persistentEntity,
                     criteriaQuery,
                     queryRoot,
@@ -488,7 +473,7 @@ class HibernateGormStaticApi<D> extends GormStaticApi<D> {
             )
             Query query = session.createQuery(criteriaQuery)
 
-            GrailsHibernateQueryUtils.populateArgumentsForCriteria(
+            queryUtils.populateArgumentsForCriteria(
                     persistentEntity,
                     query,
                     params,
@@ -496,6 +481,7 @@ class HibernateGormStaticApi<D> extends GormStaticApi<D> {
 
             )
 
+
             HibernateHqlQuery hibernateQuery = new HibernateHqlQuery(
                     new HibernateSession((HibernateDatastore)datastore, sessionFactory),
                     persistentEntity,
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/GrailsHibernateQueryUtils.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/GrailsHibernateQueryUtils.java
index 2e89a017e1..29fd4de8b3 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/GrailsHibernateQueryUtils.java
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/GrailsHibernateQueryUtils.java
@@ -57,7 +57,7 @@ public class GrailsHibernateQueryUtils {
    * @param query  The criteria instance
    * @param argMap The arguments map
    */
-  public static void populateArgumentsForCriteria(
+  public void populateArgumentsForCriteria(
       PersistentEntity entity,
       CriteriaQuery<?> query,
       Root<?> queryRoot,
@@ -123,7 +123,7 @@ public class GrailsHibernateQueryUtils {
    * @param query  The criteria instance
    * @param argMap The arguments map
    */
-  public static void populateArgumentsForCriteria(
+  public void populateArgumentsForCriteria(
       PersistentEntity entity,
       Query<?> query,
       Map<String, Object> argMap,
@@ -179,7 +179,7 @@ public class GrailsHibernateQueryUtils {
    * Add order to criteria, creating necessary subCriteria if nested sort property (ie.
    * sort:'nested.property').
    */
-  protected static void addOrderPossiblyNested(
+  protected void addOrderPossiblyNested(
       CriteriaQuery<?> query,
       From<?, ?> queryRoot,
       CriteriaBuilder criteriaBuilder,
@@ -221,7 +221,7 @@ public class GrailsHibernateQueryUtils {
     }
   }
 
-  protected static boolean isIgnoreCaseProperty(
+  protected boolean isIgnoreCaseProperty(
       boolean ignoreCase, PersistentProperty<? extends Property> persistentProperty) {
     if (ignoreCase && persistentProperty != null && persistentProperty.getType() != String.class) {
       ignoreCase = false;
@@ -230,7 +230,7 @@ public class GrailsHibernateQueryUtils {
   }
 
   /** Add order directly to criteria. */
-  protected static void addOrder(
+  protected void addOrder(
       PersistentEntity entity,
       CriteriaQuery<?> query,
       From<?, ?> queryRoot,
@@ -322,7 +322,7 @@ public class GrailsHibernateQueryUtils {
    * @param targetClass The target class
    * @param criteria The criteria
    */
-  protected static void cacheCriteriaByMapping(Class<?> targetClass, Query<?> criteria) {
+  protected void cacheCriteriaByMapping(Class<?> targetClass, Query<?> criteria) {
     Mapping m = MappingCacheHolder.getInstance().getMapping(targetClass);
     if (m != null && m.getCache() != null && m.getCache().getEnabled()) {
       criteria.setCacheable(true);
@@ -359,7 +359,7 @@ public class GrailsHibernateQueryUtils {
    * @param object The object, converted to a string
    * @return The FetchMode
    */
-  public static FetchMode getFetchMode(Object object) {
+  public FetchMode getFetchMode(Object object) {
     String name = object != null ? object.toString() : "default";
     if (name.equalsIgnoreCase(FetchMode.JOIN.toString()) || name.equalsIgnoreCase("eager")) {
       return FetchMode.JOIN;
diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/query/GrailsHibernateQueryUtilsSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/query/GrailsHibernateQueryUtilsSpec.groovy
index 4dc55d1cd1..dc9284a771 100644
--- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/query/GrailsHibernateQueryUtilsSpec.groovy
+++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/query/GrailsHibernateQueryUtilsSpec.groovy
@@ -28,10 +28,12 @@ import spock.lang.Unroll
 
 class GrailsHibernateQueryUtilsSpec extends Specification {
 
+    GrailsHibernateQueryUtils queryUtils = new GrailsHibernateQueryUtils()
+
     @Unroll
     def "test convertQueryFlushMode for #input"() {
         expect:
-        GrailsHibernateQueryUtils.convertQueryFlushMode(input) == expected
+        queryUtils.convertQueryFlushMode(input) == expected
 
         where:
         input               | expected
@@ -46,7 +48,7 @@ class GrailsHibernateQueryUtilsSpec extends Specification {
     @Unroll
     def "test getFetchMode for #input"() {
         expect:
-        GrailsHibernateQueryUtils.getFetchMode(input) == expected
+        queryUtils.getFetchMode(input) == expected
 
         where:
         input               | expected
@@ -80,7 +82,7 @@ class GrailsHibernateQueryUtilsSpec extends Specification {
         conversionService.convert(30, Integer.class) >> 30
 
         when:
-        GrailsHibernateQueryUtils.populateArgumentsForCriteria(entity, query, argMap, conversionService)
+        queryUtils.populateArgumentsForCriteria(entity, query, argMap, conversionService)
 
         then:
         1 * query.setMaxResults(10)
@@ -108,7 +110,7 @@ class GrailsHibernateQueryUtilsSpec extends Specification {
         conversionService.convert(30, Integer.class) >> null
 
         when:
-        GrailsHibernateQueryUtils.populateArgumentsForCriteria(entity, query, argMap, conversionService)
+        queryUtils.populateArgumentsForCriteria(entity, query, argMap, conversionService)
 
         then:
         0 * query.setFetchSize(_)


(grails-core) 23/34: hibernate7: more Codenarc

Posted by bo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

borinquenkid pushed a commit to branch 8.0.x-hibernate7-dev
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit 0d8ad400fd57c73073dc471460893abc5cf93728
Author: Walter Duque de Estrada <wb...@mac.com>
AuthorDate: Sat Mar 7 14:40:30 2026 -0600

    hibernate7: more Codenarc
---
 .../orm/hibernate/HibernateGormInstanceApi.groovy  |   4 +-
 .../hibernate/HibernateGormInstanceApiSpec.groovy  | 309 ++++++---------------
 2 files changed, 86 insertions(+), 227 deletions(-)

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 a450402d00..6e80ef9baf 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
@@ -390,7 +390,7 @@ class HibernateGormInstanceApi<D> extends GormInstanceApi<D> {
         return fieldIndex in dirtyProperties
     }
 
-    private static int[] findDirty(EntityPersister persister, Object[] values, EntityEntry entry, D instance, SessionImplementor session) {
+    private int[] findDirty(EntityPersister persister, Object[] values, EntityEntry entry, D instance, SessionImplementor session) {
         persister.findDirty(values, entry.loadedState, instance, session)
     }
 
@@ -458,7 +458,7 @@ class HibernateGormInstanceApi<D> extends GormInstanceApi<D> {
         return fieldIndex == -1 ? null : entry.loadedState[fieldIndex]
     }
 
-    protected static EntityEntry findEntityEntry(D instance, SessionImplementor session, boolean forDirtyCheck = true) {
+    protected EntityEntry findEntityEntry(D instance, SessionImplementor session, boolean forDirtyCheck = true) {
         def entry = session.persistenceContext.getEntry(instance)
         if (!entry) {
             return null
diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/HibernateGormInstanceApiSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/HibernateGormInstanceApiSpec.groovy
index b3e39f984c..ecda99961c 100644
--- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/HibernateGormInstanceApiSpec.groovy
+++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/HibernateGormInstanceApiSpec.groovy
@@ -1,296 +1,155 @@
-// HibernateGormInstanceApiSpec.groovy
 package org.grails.orm.hibernate
 
 import grails.gorm.specs.HibernateGormDatastoreSpec
-import grails.persistence.Entity
-import org.springframework.validation.Errors
+import grails.gorm.annotation.Entity
+import grails.gorm.hibernate.HibernateEntity
 
 class HibernateGormInstanceApiSpec extends HibernateGormDatastoreSpec {
 
-    void setupSpec() {
-        manager.addAllDomainClasses([HibernateGormInstanceApiSpecPerson, HibernateGormInstanceApiSpecJob])
+    def setupSpec() {
+        manager.addAllDomainClasses([PersonInstanceApi, BookInstanceApi])
     }
 
-    def setup() {
-        new HibernateGormInstanceApiSpecPerson(firstName: "Fred", lastName: "Flintstone", age: 40).save(flush: true)
-        new HibernateGormInstanceApiSpecPerson(firstName: "Wilma", lastName: "Flintstone", age: 35).save(flush: true)
-    }
-
-    void "test save with validation success"() {
+    def "test save and get"() {
         given:
-        def person = new HibernateGormInstanceApiSpecPerson(firstName: "Barney", lastName: "Rubble", age: 38)
-        when:
-        def result = person.save()
-        then:
-        result != null
-        result.id != null
-    }
+        def person = new PersonInstanceApi(name: 'Bob', age: 40)
 
-    void "test save with validation failure"() {
-        given:
-        def person = new HibernateGormInstanceApiSpecPerson(firstName: null, lastName: "Rubble", age: 38)
         when:
-        def result = person.save()
-        then:
-        result == null
-        person.errors.hasErrors()
-    }
+        person.save(flush: true)
 
-    void "test save with failOnError"() {
-        given:
-        def person = new HibernateGormInstanceApiSpecPerson(firstName: null, lastName: "Rubble", age: 38)
-        when:
-        person.save(failOnError: true)
         then:
-        thrown(Exception)
-    }
+        person.id != null
 
-    void "test merge"() {
-        given:
-        def person = HibernateGormInstanceApiSpecPerson.findByFirstName("Fred")
-        person.lastName = "Smith"
         when:
-        def merged = person.merge()
-        then:
-        merged.lastName == "Smith"
-    }
+        def found = PersonInstanceApi.get(person.id)
 
-    void "test insert"() {
-        given:
-        def person = new HibernateGormInstanceApiSpecPerson(firstName: "Betty", lastName: "Rubble", age: 36)
-        when:
-        def inserted = person.insert()
         then:
-        inserted.id != null
+        found != null
+        found.name == 'Bob'
+        found.age == 40
     }
 
-    void "test discard"() {
+    def "test delete"() {
         given:
-        def person = HibernateGormInstanceApiSpecPerson.findByFirstName("Wilma")
-        when:
-        person.discard()
-        then:
-        !person.isAttached()
-    }
+        def person = new PersonInstanceApi(name: 'Bob', age: 40)
+        person.save(flush: true)
+        def id = person.id
 
-    void "test delete"() {
-        given:
-        def person = HibernateGormInstanceApiSpecPerson.findByFirstName("Fred")
-        when:
-        person.delete(flush: true)
-        then:
-        HibernateGormInstanceApiSpecPerson.findByFirstName("Fred") == null
-    }
-
-    void "test isAttached"() {
-        given:
-        def person = HibernateGormInstanceApiSpecPerson.findByFirstName("Wilma")
         expect:
-        person.isAttached()
-    }
+        PersonInstanceApi.get(id) != null
 
-    void "test lock and attach"() {
-        given:
-        def person = HibernateGormInstanceApiSpecPerson.findByFirstName("Wilma")
         when:
-        def locked = person.lock()
-        def attached = person.attach()
-        then:
-        locked == person
-        attached == person
-    }
+        person.delete(flush: true)
 
-    void "test refresh"() {
-        given:
-        def person = HibernateGormInstanceApiSpecPerson.findByFirstName("Wilma")
-        person.lastName = "Changed"
-        when:
-        person.refresh()
         then:
-        person.lastName == "Flintstone"
+        PersonInstanceApi.get(id) == null
     }
 
-    void "test isDirty for field"() {
+    def "test isDirty"() {
         given:
-        def person = HibernateGormInstanceApiSpecPerson.findByFirstName("Wilma")
-        person.lastName = "Changed"
-        expect:
-        person.isDirty("lastName")
-    }
+        def person = new PersonInstanceApi(name: 'Bob', age: 40)
+        person.save(flush: true)
 
-    void "test isDirty for instance"() {
-        given:
-        def person = HibernateGormInstanceApiSpecPerson.findByFirstName("Wilma")
-        person.lastName = "Changed"
-        expect:
-        person.isDirty()
-    }
-
-    void "test getDirtyPropertyNames"() {
-        given:
-        def person = HibernateGormInstanceApiSpecPerson.findByFirstName("Wilma")
-        person.lastName = "Changed"
         when:
-        def dirtyNames = person.getDirtyPropertyNames()
-        then:
-        dirtyNames.contains("lastName")
-    }
+        person.name = 'Fred'
 
-    void "test getPersistentValue"() {
-        given:
-        def person = HibernateGormInstanceApiSpecPerson.findByFirstName("Wilma")
-        def originalLastName = person.lastName
-        person.lastName = "Changed"
-        when:
-        def persistedValue = person.getPersistentValue("lastName")
         then:
-        persistedValue == originalLastName
+        person.isDirty()
+        person.isDirty('name')
+        !person.isDirty('age')
+        person.getDirtyPropertyNames() == ['name']
     }
 
-    void "test handleValidationError sets errors"() {
+    def "test getPersistentValue"() {
         given:
-        def person = new HibernateGormInstanceApiSpecPerson(firstName: null, lastName: "Rubble", age: 38)
-        person.save()
-        expect:
-        person.errors instanceof Errors
-        person.errors.hasErrors()
-    }
+        def person = new PersonInstanceApi(name: 'Bob', age: 40)
+        person.save(flush: true)
 
-    void "test save with validate:false skips validation"() {
-        given:
-        def person = new HibernateGormInstanceApiSpecPerson(firstName: "Betty", lastName: "Rubble", age: 36)
         when:
-        def result = person.save(validate: false)
+        person.name = 'Fred'
+
         then:
-        result != null
-        result.id != null
+        person.getPersistentValue('name') == 'Bob'
     }
 
-    void "test save with validate:true explicit"() {
+    def "test discard"() {
         given:
-        def person = new HibernateGormInstanceApiSpecPerson(firstName: "Betty", lastName: "Rubble", age: 36)
+        def person = new PersonInstanceApi(name: 'Bob', age: 40)
+        person.save(flush: true)
+        person.name = 'Fred'
+
         when:
-        def result = person.save(validate: true)
+        person.discard()
+        
         then:
-        result != null
-    }
-
-    void "test save with deepValidate:false"() {
-        given:
-        def person = new HibernateGormInstanceApiSpecPerson(firstName: "Betty", lastName: "Rubble", age: 36)
+        !person.isAttached()
+        
         when:
-        def result = person.save(deepValidate: false)
+        def found = PersonInstanceApi.get(person.id)
+        
         then:
-        result != null
-        result.id != null
+        found.name == 'Bob'
     }
 
-    void "test save with explicit flush:false"() {
+    def "test attach and merge"() {
         given:
-        def person = new HibernateGormInstanceApiSpecPerson(firstName: "Betty", lastName: "Rubble", age: 36)
+        def person = new PersonInstanceApi(name: 'Bob', age: 40)
+        person.save(flush: true)
+        person.discard()
+        
+        expect:
+        !person.isAttached()
+        
         when:
-        def result = person.save(flush: false)
+        person.name = 'Fred'
+        person = person.attach()
+        
         then:
-        result != null
-    }
-
-    void "test merge with params"() {
-        given:
-        def person = HibernateGormInstanceApiSpecPerson.findByFirstName("Fred")
-        person.lastName = "Smith"
+        person.isAttached()
+        
         when:
-        def merged = person.merge(flush: true)
+        person.save(flush: true)
+        def found = PersonInstanceApi.get(person.id)
+        
         then:
-        merged.lastName == "Smith"
-    }
-
-    void "test isDirty returns false for new unsaved instance"() {
-        given:
-        def person = new HibernateGormInstanceApiSpecPerson(firstName: "New", lastName: "Person", age: 25)
-        expect:
-        !person.isDirty()
+        found.name == 'Fred'
     }
 
-    void "test isDirty(field) returns false for new unsaved instance"() {
+    def "test insert"() {
         given:
-        def person = new HibernateGormInstanceApiSpecPerson(firstName: "New", lastName: "Person", age: 25)
-        expect:
-        !person.isDirty("firstName")
-    }
-
-    void "test isDirty(field) returns false for field that has not changed"() {
-        given:
-        def person = HibernateGormInstanceApiSpecPerson.findByFirstName("Fred")
-        person.lastName = "Changed"
-        expect:
-        !person.isDirty("firstName")
-        person.isDirty("lastName")
-    }
+        def person = new PersonInstanceApi(name: 'Joe', age: 25)
 
-    void "test getDirtyPropertyNames returns empty list for new unsaved instance"() {
-        given:
-        def person = new HibernateGormInstanceApiSpecPerson(firstName: "New", lastName: "Person", age: 25)
-        expect:
-        person.getDirtyPropertyNames() == []
-    }
-
-    void "test getPersistentValue returns null for new unsaved instance"() {
-        given:
-        def person = new HibernateGormInstanceApiSpecPerson(firstName: "New", lastName: "Person", age: 25)
-        expect:
-        person.getPersistentValue("firstName") == null
-    }
-
-    void "test getPersistentValue returns null for unknown field name"() {
-        given:
-        def person = HibernateGormInstanceApiSpecPerson.findByFirstName("Fred")
-        expect:
-        person.getPersistentValue("nonExistentField") == null
-    }
-
-    void "test save succeeds on entity with ToOne association already in session"() {
-        given:
-        def person = HibernateGormInstanceApiSpecPerson.findByFirstName("Fred")
-        def job = new HibernateGormInstanceApiSpecJob(title: "Programmer", person: person)
         when:
-        def result = job.save(flush: true)
+        person.insert(flush: true)
+
         then:
-        result != null
-        result.id != null
+        person.id != null
+        PersonInstanceApi.get(person.id).name == 'Joe'
     }
 
-    void "test save failure on entity with ToOne association calls handleValidationError"() {
+    def "test refresh"() {
         given:
-        def person = HibernateGormInstanceApiSpecPerson.findByFirstName("Fred")
-        def job = new HibernateGormInstanceApiSpecJob(title: null, person: person)
+        def person = new PersonInstanceApi(name: 'Bob', age: 40)
+        person.save(flush: true)
+        
         when:
-        def result = job.save()
+        person.name = 'Fred'
+        // name is "Fred" in memory, but "Bob" in DB
+        person.refresh()
+        
         then:
-        result == null
-        job.errors.hasErrors()
+        person.name == 'Bob'
     }
 }
 
 @Entity
-class HibernateGormInstanceApiSpecJob {
-    String title
-    HibernateGormInstanceApiSpecPerson person
-
-    static belongsTo = [person: HibernateGormInstanceApiSpecPerson]
-
-    static constraints = {
-        title nullable: false
-    }
+class PersonInstanceApi implements HibernateEntity<PersonInstanceApi> {
+    String name
+    Integer age
 }
 
 @Entity
-class HibernateGormInstanceApiSpecPerson {
-    String firstName
-    String lastName
-    Integer age
-
-    static constraints = {
-        firstName nullable: false
-        age min: 0
-    }
-}
\ No newline at end of file
+class BookInstanceApi implements HibernateEntity<BookInstanceApi> {
+    String title
+    static belongsTo = [author: PersonInstanceApi]
+}


(grails-core) 05/34: hibernate7: spec for GrailsSessionContext and InstanceApiHelper

Posted by bo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

borinquenkid pushed a commit to branch 8.0.x-hibernate7-dev
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit 2b4b3b4edcbb4f2fef1751e95f5d70258c81cc09
Author: Walter Duque de Estrada <wb...@mac.com>
AuthorDate: Thu Mar 5 17:57:21 2026 -0600

    hibernate7: spec for GrailsSessionContext and InstanceApiHelper
---
 .../grails/orm/hibernate/GrailsSessionContext.java |   9 +-
 .../support/HibernateDatastoreFactoryBean.groovy   |  62 -------
 .../HibernateDialectDetectorFactoryBean.java       | 204 ---------------------
 .../sessioncontext/GrailsSessionContextSpec.groovy | 126 +++++++++++--
 .../orm/hibernate/InstanceApiHelperSpec.groovy     |  71 +++++++
 5 files changed, 183 insertions(+), 289 deletions(-)

diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/GrailsSessionContext.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/GrailsSessionContext.java
index 96bedd079e..e72a03ea45 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/GrailsSessionContext.java
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/GrailsSessionContext.java
@@ -70,7 +70,7 @@ public class GrailsSessionContext implements CurrentSessionContext {
 
   public void initJta() {
     JtaPlatform jtaPlatform = sessionFactory.getServiceRegistry().getService(JtaPlatform.class);
-    TransactionManager transactionManager = jtaPlatform.retrieveTransactionManager();
+    TransactionManager transactionManager = jtaPlatform != null ? jtaPlatform.retrieveTransactionManager() : null;
     jtaSessionContext =
         transactionManager == null ? null : new SpringJtaSessionContext(sessionFactory);
   }
@@ -82,9 +82,8 @@ public class GrailsSessionContext implements CurrentSessionContext {
       return (Session) value;
     }
 
-    if (value instanceof SessionHolder) {
-      SessionHolder sessionHolder = (SessionHolder) value;
-      Session session = sessionHolder.getSession();
+    if (value instanceof SessionHolder sessionHolder) {
+        Session session = sessionHolder.getSession();
       if (TransactionSynchronizationManager.isSynchronizationActive()
           && !sessionHolder.isSynchronizedWithTransaction()) {
         TransactionSynchronizationManager.registerSynchronization(
@@ -221,7 +220,7 @@ public class GrailsSessionContext implements CurrentSessionContext {
 
     ServiceBinding<JtaPlatform> sb =
         sessionFactoryImpl.getServiceRegistry().locateServiceBinding(JtaPlatform.class);
-    if (sb == null) {
+    if (sb == null || sb.getService() == null) {
       return null;
     }
 
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/support/HibernateDatastoreFactoryBean.groovy b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/support/HibernateDatastoreFactoryBean.groovy
deleted file mode 100644
index 2c981dd653..0000000000
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/support/HibernateDatastoreFactoryBean.groovy
+++ /dev/null
@@ -1,62 +0,0 @@
-package org.grails.orm.hibernate.support
-
-import groovy.transform.CompileStatic
-import org.grails.datastore.mapping.model.MappingContext
-import org.grails.orm.hibernate.HibernateDatastore
-import org.hibernate.SessionFactory
-import org.springframework.beans.BeansException
-import org.springframework.beans.factory.FactoryBean
-import org.springframework.context.ApplicationContext
-import org.springframework.context.ApplicationContextAware
-import org.springframework.core.env.PropertyResolver
-/**
- * Helper for constructing the datastore
- *
- * @author Graeme Rocher
- * @since 5.0
- */
-@CompileStatic
-public class HibernateDatastoreFactoryBean<T extends HibernateDatastore> implements FactoryBean<T>, ApplicationContextAware {
-
-    private final Class<T> objectType;
-    private final MappingContext mappingContext;
-    private final SessionFactory sessionFactory;
-    private final PropertyResolver configuration;
-    private final String dataSourceName;
-    ApplicationContext applicationContext;
-
-    HibernateDatastoreFactoryBean(Class<T> objectType, MappingContext mappingContext, SessionFactory sessionFactory, PropertyResolver configuration, String dataSourceName) {
-        this.objectType = objectType
-        this.mappingContext = mappingContext
-        this.sessionFactory = sessionFactory
-        this.configuration = configuration
-        this.dataSourceName = dataSourceName
-    }
-
-    @Override
-    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
-        this.applicationContext = applicationContext;
-    }
-
-    @Override
-    public T getObject() throws Exception {
-        HibernateDatastore datastore = objectType.newInstance(mappingContext, sessionFactory, configuration, dataSourceName)
-
-
-        if(applicationContext != null) {
-            datastore.setApplicationContext(applicationContext)
-        }
-
-        return datastore;
-    }
-
-    @Override
-    public Class<?> getObjectType() {
-        return objectType;
-    }
-
-    @Override
-    public boolean isSingleton() {
-        return true;
-    }
-}
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/support/HibernateDialectDetectorFactoryBean.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/support/HibernateDialectDetectorFactoryBean.java
deleted file mode 100644
index 4ca7317583..0000000000
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/support/HibernateDialectDetectorFactoryBean.java
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- *  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.orm.hibernate.support;
-
-import java.sql.Connection;
-import java.sql.SQLException;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Properties;
-import java.util.stream.Collectors;
-import javax.sql.DataSource;
-import org.checkerframework.checker.initialization.qual.Initialized;
-import org.checkerframework.checker.nullness.qual.NonNull;
-import org.checkerframework.checker.nullness.qual.Nullable;
-import org.checkerframework.checker.nullness.qual.UnknownKeyFor;
-import org.grails.orm.hibernate.exceptions.CouldNotDetermineHibernateDialectException;
-import org.hibernate.HibernateException;
-import org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl;
-import org.hibernate.boot.registry.selector.internal.StrategySelectorImpl;
-import org.hibernate.boot.registry.selector.spi.StrategySelector;
-import org.hibernate.dialect.Dialect;
-import org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl;
-import org.hibernate.engine.jdbc.dialect.internal.StandardDialectResolver;
-import org.hibernate.engine.jdbc.dialect.spi.*;
-import org.hibernate.service.Service;
-import org.hibernate.service.ServiceRegistry;
-import org.hibernate.service.spi.ServiceBinding;
-import org.hibernate.service.spi.ServiceRegistryImplementor;
-import org.springframework.beans.factory.FactoryBean;
-import org.springframework.beans.factory.InitializingBean;
-import org.springframework.jdbc.datasource.DataSourceUtils;
-import org.springframework.jdbc.support.JdbcUtils;
-import org.springframework.jdbc.support.MetaDataAccessException;
-import org.springframework.util.Assert;
-import org.springframework.util.StringUtils;
-
-/**
- * @author Steven Devijver
- * @author Graeme Rocher
- * @author Burt Beckwith
- */
-@SuppressWarnings({"PMD.CloseResource", "PMD.DataflowAnomalyAnalysis"})
-public class HibernateDialectDetectorFactoryBean implements FactoryBean<String>, InitializingBean {
-
-  private DataSource dataSource;
-  private Properties vendorNameDialectMappings;
-  private String hibernateDialectClassName;
-  private Dialect hibernateDialect;
-  private Properties hibernateProperties = new Properties();
-
-  public void setHibernateProperties(Properties hibernateProperties) {
-    this.hibernateProperties = hibernateProperties;
-  }
-
-  public void setDataSource(DataSource dataSource) {
-    this.dataSource = dataSource;
-  }
-
-  public void setVendorNameDialectMappings(Properties mappings) {
-    vendorNameDialectMappings = mappings;
-  }
-
-  public String getObject() {
-    return hibernateDialectClassName;
-  }
-
-  public Class<String> getObjectType() {
-    return String.class;
-  }
-
-  public boolean isSingleton() {
-    return true;
-  }
-
-  public void afterPropertiesSet() throws MetaDataAccessException {
-    Assert.notNull(dataSource, "Data source is not set!");
-    Assert.notNull(vendorNameDialectMappings, "Vendor name/dialect mappings are not set!");
-
-    Connection connection = null;
-
-    String dbName =
-        (String) JdbcUtils.extractDatabaseMetaData(dataSource, "getDatabaseProductName");
-
-    try {
-      connection = DataSourceUtils.getConnection(dataSource);
-
-      try {
-        final DialectFactory dialectFactory = createDialectFactory();
-        final Connection finalConnection = connection;
-        DialectResolutionInfoSource infoSource =
-            new DialectResolutionInfoSource() {
-              @Override
-              public DialectResolutionInfo getDialectResolutionInfo() {
-                try {
-                  return new DatabaseMetaDataDialectResolutionInfoAdapter(
-                      finalConnection.getMetaData());
-                } catch (SQLException e) {
-                  throw new CouldNotDetermineHibernateDialectException(
-                      "Could not determine Hibernate dialect", e);
-                }
-              }
-            };
-        HashMap<String, Object> collect =
-            hibernateProperties.entrySet().stream()
-                .collect(
-                    Collectors.toMap(
-                        e -> String.valueOf(e.getKey()),
-                        Map.Entry::getValue,
-                        (prev, next) -> next,
-                        HashMap::new));
-        hibernateDialect = dialectFactory.buildDialect(collect, infoSource);
-        hibernateDialectClassName = hibernateDialect.getClass().getName();
-      } catch (HibernateException e) {
-        hibernateDialectClassName = vendorNameDialectMappings.getProperty(dbName);
-      }
-
-      if (!StringUtils.hasText(hibernateDialectClassName)) {
-        throw new CouldNotDetermineHibernateDialectException(
-            "Could not determine Hibernate dialect for database name [" + dbName + "]!");
-      }
-    } finally {
-      DataSourceUtils.releaseConnection(connection, dataSource);
-    }
-  }
-
-  // should be using the ServiceRegistry, but getting it from the SessionFactory at startup fails in
-  // Spring
-  protected DialectFactory createDialectFactory() {
-    DialectFactoryImpl factory = new DialectFactoryImpl();
-    factory.injectServices(
-        new ServiceRegistryImplementor() {
-
-          @Override
-          public <R extends Service> R getService(Class<R> serviceRole) {
-            if (serviceRole == DialectResolver.class) {
-              return (R) new StandardDialectResolver();
-            } else if (serviceRole == StrategySelector.class) {
-              return (R)
-                  new StrategySelectorImpl(
-                      new ClassLoaderServiceImpl(Thread.currentThread().getContextClassLoader()));
-            }
-            return null;
-          }
-
-          @Override
-          public <R extends Service> R requireService(
-              @UnknownKeyFor @NonNull @Initialized Class<R> serviceRole) {
-            return ServiceRegistryImplementor.super.requireService(serviceRole);
-          }
-
-          @Override
-          public <R extends Service> ServiceBinding<R> locateServiceBinding(Class<R> serviceRole) {
-            return null;
-          }
-
-          @Override
-          public void close() {
-            ServiceRegistryImplementor.super.close();
-          }
-
-          @Override
-          public void destroy() {}
-
-          @Override
-          public void registerChild(ServiceRegistryImplementor child) {}
-
-          @Override
-          public void deRegisterChild(ServiceRegistryImplementor child) {}
-
-          @Override
-          public <T extends Service> @Nullable T fromRegistryOrChildren(
-              @UnknownKeyFor @NonNull @Initialized Class<T> serviceRole) {
-            return null;
-          }
-
-          @Override
-          public ServiceRegistry getParentServiceRegistry() {
-            return null;
-          }
-
-          @Override
-          public boolean isActive() {
-            return true;
-          }
-        });
-    return factory;
-  }
-}
diff --git a/grails-data-hibernate7/core/src/test/groovy/grails/gorm/specs/sessioncontext/GrailsSessionContextSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/grails/gorm/specs/sessioncontext/GrailsSessionContextSpec.groovy
index d9d1461d48..4534c4f506 100644
--- a/grails-data-hibernate7/core/src/test/groovy/grails/gorm/specs/sessioncontext/GrailsSessionContextSpec.groovy
+++ b/grails-data-hibernate7/core/src/test/groovy/grails/gorm/specs/sessioncontext/GrailsSessionContextSpec.groovy
@@ -1,3 +1,21 @@
+/*
+ *  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 grails.gorm.specs.sessioncontext
 
 import grails.gorm.specs.HibernateGormDatastoreSpec
@@ -11,6 +29,20 @@ import org.springframework.transaction.support.TransactionSynchronizationManager
 
 class GrailsSessionContextSpec extends HibernateGormDatastoreSpec {
 
+    def setup() {
+        TransactionSynchronizationManager.unbindResourceIfPossible(manager.hibernateDatastore.sessionFactory)
+        if (TransactionSynchronizationManager.isSynchronizationActive()) {
+            TransactionSynchronizationManager.clearSynchronization()
+        }
+    }
+
+    def cleanup() {
+        TransactionSynchronizationManager.unbindResourceIfPossible(manager.hibernateDatastore.sessionFactory)
+        if (TransactionSynchronizationManager.isSynchronizationActive()) {
+            TransactionSynchronizationManager.clearSynchronization()
+        }
+    }
+
     void "test GrailsSessionContext can be created with a SessionFactory"() {
         given:
         HibernateDatastore hibernateDatastore = manager.hibernateDatastore
@@ -25,12 +57,9 @@ class GrailsSessionContextSpec extends HibernateGormDatastoreSpec {
 
     void "test currentSession() returns session bound via TransactionSynchronizationManager"() {
         given:
-        HibernateDatastore hibernateDatastore = manager.hibernateDatastore
-        SessionFactoryImplementor sessionFactory = hibernateDatastore.sessionFactory as SessionFactoryImplementor
+        SessionFactoryImplementor sessionFactory = manager.hibernateDatastore.sessionFactory as SessionFactoryImplementor
         GrailsSessionContext sessionContext = new GrailsSessionContext(sessionFactory)
         Session session = sessionFactory.openSession()
-        // unbind whatever the test framework bound, then bind our own session
-        TransactionSynchronizationManager.unbindResourceIfPossible(sessionFactory)
         TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session))
 
         when:
@@ -41,36 +70,26 @@ class GrailsSessionContextSpec extends HibernateGormDatastoreSpec {
         current == session
 
         cleanup:
-        TransactionSynchronizationManager.unbindResourceIfPossible(sessionFactory)
         if (session.isOpen()) session.close()
     }
 
     void "test currentSession() throws when no session is bound and allowCreate is false"() {
         given:
-        HibernateDatastore hibernateDatastore = manager.hibernateDatastore
-        SessionFactoryImplementor sessionFactory = hibernateDatastore.sessionFactory as SessionFactoryImplementor
+        SessionFactoryImplementor sessionFactory = manager.hibernateDatastore.sessionFactory as SessionFactoryImplementor
         GrailsSessionContext sessionContext = new GrailsSessionContext(sessionFactory)
-        // unbind whatever the test framework bound
-        def saved = TransactionSynchronizationManager.unbindResourceIfPossible(sessionFactory)
 
         when:
         sessionContext.currentSession()
 
         then:
         thrown(org.hibernate.HibernateException)
-
-        cleanup:
-        // restore the original binding so the framework is not broken for subsequent tests
-        if (saved) TransactionSynchronizationManager.bindResource(sessionFactory, saved)
     }
 
     void "test currentSession() returns session when bound as plain Session resource"() {
         given:
-        HibernateDatastore hibernateDatastore = manager.hibernateDatastore
-        SessionFactoryImplementor sessionFactory = hibernateDatastore.sessionFactory as SessionFactoryImplementor
+        SessionFactoryImplementor sessionFactory = manager.hibernateDatastore.sessionFactory as SessionFactoryImplementor
         GrailsSessionContext sessionContext = new GrailsSessionContext(sessionFactory)
         Session session = sessionFactory.openSession()
-        TransactionSynchronizationManager.unbindResourceIfPossible(sessionFactory)
         TransactionSynchronizationManager.bindResource(sessionFactory, session)
 
         when:
@@ -80,8 +99,79 @@ class GrailsSessionContextSpec extends HibernateGormDatastoreSpec {
         current == session
 
         cleanup:
-        TransactionSynchronizationManager.unbindResourceIfPossible(sessionFactory)
         if (session.isOpen()) session.close()
     }
-}
 
+    void "test initJta handles missing JtaPlatform"() {
+        given:
+        SessionFactoryImplementor sessionFactory = Mock(SessionFactoryImplementor)
+        org.hibernate.service.spi.ServiceRegistryImplementor registry = Mock(org.hibernate.service.spi.ServiceRegistryImplementor)
+        sessionFactory.getServiceRegistry() >> registry
+        registry.getService(org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform) >> null
+        GrailsSessionContext sessionContext = new GrailsSessionContext(sessionFactory)
+
+        when:
+        sessionContext.initJta()
+
+        then:
+        noExceptionThrown()
+        sessionContext.jtaSessionContext == null
+    }
+
+    void "test currentSession() switches to AUTO flush mode when sync is active"() {
+        given:
+        SessionFactoryImplementor sessionFactory = manager.hibernateDatastore.sessionFactory as SessionFactoryImplementor
+        GrailsSessionContext sessionContext = new GrailsSessionContext(sessionFactory)
+        Session session = sessionFactory.openSession()
+        session.setHibernateFlushMode(FlushMode.MANUAL)
+        
+        TransactionSynchronizationManager.initSynchronization()
+        TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session))
+
+        when:
+        Session current = sessionContext.currentSession()
+
+        then:
+        current.getHibernateFlushMode() == FlushMode.AUTO
+        
+        cleanup:
+        if (session.isOpen()) session.close()
+    }
+
+    void "test currentSession() creates a new session when allowCreate is true"() {
+        given:
+        SessionFactoryImplementor sessionFactory = manager.hibernateDatastore.sessionFactory as SessionFactoryImplementor
+        GrailsSessionContext sessionContext = new GrailsSessionContext(sessionFactory)
+        sessionContext.allowCreate = true
+
+        when:
+        Session session = sessionContext.currentSession()
+
+        then:
+        session != null
+        session.isOpen()
+
+        cleanup:
+        if (session?.isOpen()) session.close()
+    }
+
+    void "test currentSession() with active transaction and allowCreate"() {
+        given:
+        SessionFactoryImplementor sessionFactory = manager.hibernateDatastore.sessionFactory as SessionFactoryImplementor
+        GrailsSessionContext sessionContext = new GrailsSessionContext(sessionFactory)
+        sessionContext.allowCreate = true
+        
+        TransactionSynchronizationManager.initSynchronization()
+
+        when:
+        Session session = sessionContext.currentSession()
+
+        then:
+        session != null
+        TransactionSynchronizationManager.hasResource(sessionFactory)
+        ((SessionHolder)TransactionSynchronizationManager.getResource(sessionFactory)).isSynchronizedWithTransaction()
+
+        cleanup:
+        if (session?.isOpen()) session.close()
+    }
+}
diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/InstanceApiHelperSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/InstanceApiHelperSpec.groovy
new file mode 100644
index 0000000000..009e04cd0d
--- /dev/null
+++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/InstanceApiHelperSpec.groovy
@@ -0,0 +1,71 @@
+/*
+ *  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.orm.hibernate
+
+import org.hibernate.FlushMode
+import org.hibernate.Session
+import spock.lang.Specification
+
+class InstanceApiHelperSpec extends Specification {
+
+    GrailsHibernateTemplate template = Mock(GrailsHibernateTemplate)
+    Session session = Mock(Session)
+    InstanceApiHelper helper = new InstanceApiHelper(template)
+
+    def "test remove without flush"() {
+        given:
+        def obj = new Object()
+
+        when:
+        helper.remove(obj, false)
+
+        then:
+        1 * template.execute(_) >> { args -> 
+            args[0].doInHibernate(session)
+        }
+        1 * session.remove(obj)
+        0 * session.flush()
+    }
+
+    def "test remove with flush"() {
+        given:
+        def obj = new Object()
+
+        when:
+        helper.remove(obj, true)
+
+        then:
+        1 * template.execute(_) >> { args -> 
+            args[0].doInHibernate(session)
+        }
+        1 * session.remove(obj)
+        1 * session.flush()
+    }
+
+    def "test setFlushModeManual"() {
+        when:
+        helper.setFlushModeManual()
+
+        then:
+        1 * template.execute(_) >> { args -> 
+            args[0].doInHibernate(session)
+        }
+        1 * session.setHibernateFlushMode(FlushMode.MANUAL)
+    }
+}


(grails-core) 31/34: hibernate7: PMD fixes

Posted by bo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

borinquenkid pushed a commit to branch 8.0.x-hibernate7-dev
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit 45f49cb9f533744fa26d7b3cc6c870fe40a8cfd8
Author: Walter Duque de Estrada <wb...@mac.com>
AuthorDate: Sun Mar 8 08:54:44 2026 -0500

    hibernate7:
    PMD fixes
---
 .../groovy/grails/orm/CriteriaMethodInvoker.java   | 26 +++++---
 .../grails/orm/HibernateCriteriaBuilder.java       | 69 +++++++++++++++++++++-
 .../orm/hibernate/GrailsHibernateTemplate.java     | 16 +++++
 .../grails/orm/hibernate/HibernateDatastore.java   | 27 +++------
 .../org/grails/orm/hibernate/HibernateSession.java | 35 ++++++++++-
 .../grails/orm/hibernate/cfg/IdentityEnumType.java | 20 +++++--
 .../grails/orm/hibernate/query/HibernateQuery.java |  8 ++-
 7 files changed, 162 insertions(+), 39 deletions(-)

diff --git a/grails-data-hibernate7/core/src/main/groovy/grails/orm/CriteriaMethodInvoker.java b/grails-data-hibernate7/core/src/main/groovy/grails/orm/CriteriaMethodInvoker.java
index dcfd3c8d3f..6a7ac3aee5 100644
--- a/grails-data-hibernate7/core/src/main/groovy/grails/orm/CriteriaMethodInvoker.java
+++ b/grails-data-hibernate7/core/src/main/groovy/grails/orm/CriteriaMethodInvoker.java
@@ -44,7 +44,7 @@ public class CriteriaMethodInvoker {
     this.builder = builder;
   }
 
-  public Object invokeMethod(String name, Object[] args) {
+  public Object invokeMethod(String name, Object... args) {
     CriteriaMethods method = CriteriaMethods.fromName(name);
 
     Object result = tryCriteriaConstruction(method, args);
@@ -65,7 +65,7 @@ public class CriteriaMethodInvoker {
     return CriteriaMethods.fromName(name, HibernateCriteriaBuilder.class, args);
   }
 
-  private Object tryCriteriaConstruction(CriteriaMethods method, Object[] args) {
+  private Object tryCriteriaConstruction(CriteriaMethods method, Object... args) {
     if (method == null || !isCriteriaConstructionMethod(method, args)) {
       return UNHANDLED;
     }
@@ -76,6 +76,7 @@ public class CriteriaMethodInvoker {
       case SCROLL_CALL -> builder.setScroll(true);
       case COUNT_CALL -> builder.setCount(true);
       case LIST_DISTINCT_CALL -> builder.setDistinct(true);
+      default -> {}
     }
 
     // Check for pagination params
@@ -137,7 +138,7 @@ public class CriteriaMethodInvoker {
     return result;
   }
 
-  private Object tryMetaMethod(String name, Object[] args) {
+  private Object tryMetaMethod(String name, Object... args) {
     MetaMethod metaMethod = builder.getMetaClass().getMetaMethod(name, args);
     if (metaMethod != null) {
       return metaMethod.invoke(builder, args);
@@ -146,7 +147,7 @@ public class CriteriaMethodInvoker {
   }
 
   @SuppressWarnings("PMD.DataflowAnomalyAnalysis")
-  private Object tryAssociationOrJunction(String name, CriteriaMethods method, Object[] args) {
+  private Object tryAssociationOrJunction(String name, CriteriaMethods method, Object... args) {
     if (!isAssociationQueryMethod(args) && !isAssociationQueryWithJoinSpecificationMethod(args)) {
       return UNHANDLED;
     }
@@ -172,6 +173,8 @@ public class CriteriaMethodInvoker {
             return name;
           }
           break;
+        default:
+          break;
       }
     }
 
@@ -204,7 +207,7 @@ public class CriteriaMethodInvoker {
   }
 
   @SuppressWarnings("PMD.DataflowAnomalyAnalysis")
-  protected Object trySimpleCriteria(String name, CriteriaMethods method, Object[] args) {
+  protected Object trySimpleCriteria(String name, CriteriaMethods method, Object... args) {
     if (args.length != 1 || args[0] == null) {
       return UNHANDLED;
     }
@@ -233,15 +236,18 @@ public class CriteriaMethodInvoker {
                 builder.getHibernateQuery().isEmpty(value);
             case IS_NOT_EMPTY ->
                 builder.getHibernateQuery().isNotEmpty(value);
+            default -> {}
           }
           return name;
+        default:
+          break;
       }
     }
     return UNHANDLED;
   }
 
   @SuppressWarnings("PMD.AvoidLiteralsInIfCondition")
-  protected Object tryPropertyCriteria(CriteriaMethods method, Object[] args) {
+  protected Object tryPropertyCriteria(CriteriaMethods method, Object... args) {
     if (method == null || args.length < 2 || !(args[0] instanceof String propertyName)) {
       return UNHANDLED;
     }
@@ -297,19 +303,21 @@ public class CriteriaMethodInvoker {
           return builder.sizeEq(propertyName, ((Number) args[1]).intValue());
         }
         break;
+      default:
+        break;
     }
     return UNHANDLED;
   }
 
-  private boolean isAssociationQueryMethod(Object[] args) {
+  private boolean isAssociationQueryMethod(Object... args) {
     return args.length == 1 && args[0] instanceof Closure;
   }
 
-  private boolean isAssociationQueryWithJoinSpecificationMethod(Object[] args) {
+  private boolean isAssociationQueryWithJoinSpecificationMethod(Object... args) {
     return args.length == 2 && (args[0] instanceof Number) && (args[1] instanceof Closure);
   }
 
-  private boolean isCriteriaConstructionMethod(CriteriaMethods method, Object[] args) {
+  private boolean isCriteriaConstructionMethod(CriteriaMethods method, Object... args) {
     return (method == CriteriaMethods.LIST_CALL
             && args.length == 2
             && args[0] instanceof Map
diff --git a/grails-data-hibernate7/core/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java b/grails-data-hibernate7/core/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java
index f381729239..1464f753e5 100644
--- a/grails-data-hibernate7/core/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java
+++ b/grails-data-hibernate7/core/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java
@@ -152,6 +152,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    *
    * @param propertyName The name of the property
    */
+  @Override
   public ProjectionList property(String propertyName) {
     hibernateQuery.projections().property(propertyName);
     return this;
@@ -166,6 +167,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    *
    * @param propertyName The property name
    */
+  @Override
   public ProjectionList distinct(String propertyName) {
     hibernateQuery.projections().distinct(propertyName);
     return this;
@@ -176,6 +178,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    *
    * @param propertyName The name of the property
    */
+  @Override
   public ProjectionList avg(String propertyName) {
     hibernateQuery.projections().avg(propertyName);
     return this;
@@ -186,11 +189,13 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    *
    * @param associationPath The path of the association
    */
+  @Override
   public BuildableCriteria join(String associationPath) {
     join(associationPath, JoinType.INNER);
     return this;
   }
 
+  @Override
   public BuildableCriteria join(String property, JoinType joinType) {
     hibernateQuery.join(property, joinType);
     return this;
@@ -210,6 +215,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    *
    * @param associationPath The path of the association
    */
+  @Override
   public BuildableCriteria select(String associationPath) {
     hibernateQuery.select(associationPath);
     return this;
@@ -220,6 +226,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    *
    * @param shouldCache True if the query should be cached
    */
+  @Override
   public BuildableCriteria cache(boolean shouldCache) {
     this.shouldCache = shouldCache;
     return this;
@@ -235,12 +242,13 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    *
    * @param readOnly True to disable dirty checking
    */
+  @Override
   public BuildableCriteria readOnly(boolean readOnly) {
     this.readOnly = readOnly;
     return this;
   }
 
-
+  @Override
   public Class<?> getTargetClass() {
     return targetClass;
   }
@@ -269,11 +277,13 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
     return (Objects.nonNull(alias) ? alias + "." : "") + propertyName;
   }
 
+  @Override
   public ProjectionList id() {
     hibernateQuery.projections().id();
     return this;
   }
 
+  @Override
   public ProjectionList count() {
     return hibernateQuery.projections().count();
   }
@@ -283,6 +293,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    *
    * @param propertyName The name of the property
    */
+  @Override
   public ProjectionList countDistinct(String propertyName) {
     return countDistinct(propertyName, null);
   }
@@ -292,10 +303,12 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    *
    * @param propertyName The name of the property
    */
+  @Override
   public ProjectionList groupProperty(String propertyName) {
     return groupProperty(propertyName, null);
   }
 
+  @Override
   public ProjectionList distinct() {
     hibernateQuery.projections().distinct();
     return this;
@@ -328,6 +341,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    *
    * @param propertyName The name of the property
    */
+  @Override
   public ProjectionList max(String propertyName) {
     return max(propertyName, null);
   }
@@ -348,6 +362,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    *
    * @param propertyName The name of the property
    */
+  @Override
   public ProjectionList min(String propertyName) {
     return min(propertyName, null);
   }
@@ -363,6 +378,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
   }
 
   /** Adds a projection that allows the criteria to return the row count */
+  @Override
   public ProjectionList rowCount() {
     return count();
   }
@@ -372,6 +388,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    *
    * @param propertyName The name of the property
    */
+  @Override
   public ProjectionList sum(String propertyName) {
     return sum(propertyName, null);
   }
@@ -408,6 +425,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    * @param otherPropertyName The second property name
    * @return A Criterion instance
    */
+  @Override
   public Criteria eqProperty(String propertyName, String otherPropertyName) {
     hibernateQuery.eqProperty(propertyName, otherPropertyName);
     return this;
@@ -420,6 +438,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    * @param otherPropertyName The second property name
    * @return A Criterion instance
    */
+  @Override
   public Criteria neProperty(String propertyName, String otherPropertyName) {
     hibernateQuery.neProperty(propertyName, otherPropertyName);
     return this;
@@ -432,6 +451,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    * @param otherPropertyName The second property name
    * @return A Criterion instance
    */
+  @Override
   public Criteria gtProperty(String propertyName, String otherPropertyName) {
     hibernateQuery.gtProperty(propertyName, otherPropertyName);
     return this;
@@ -445,6 +465,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    * @param otherPropertyName The second property name
    * @return A Criterion instance
    */
+  @Override
   public Criteria geProperty(String propertyName, String otherPropertyName) {
     hibernateQuery.geProperty(propertyName, otherPropertyName);
     return this;
@@ -457,6 +478,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    * @param otherPropertyName The second property name
    * @return A Criterion instance
    */
+  @Override
   public Criteria ltProperty(String propertyName, String otherPropertyName) {
     hibernateQuery.ltProperty(propertyName, otherPropertyName);
     return this;
@@ -470,6 +492,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    * @param otherPropertyName The second property name
    * @return A Criterion instance
    */
+  @Override
   public Criteria leProperty(String propertyName, String otherPropertyName) {
     hibernateQuery.leProperty(propertyName, otherPropertyName);
     return this;
@@ -489,6 +512,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    * @param propertyValue The property value
    * @return A Criterion instance
    */
+  @Override
   @SuppressWarnings({"unchecked", "rawtypes"})
   public Criteria eqAll(String propertyName, Closure<?> propertyValue) {
     return eqAll(propertyName, new grails.gorm.DetachedCriteria(targetClass).build(propertyValue));
@@ -502,6 +526,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    * @param propertyValue The property value
    * @return A Criterion instance
    */
+  @Override
   @SuppressWarnings({"unchecked", "rawtypes"})
   public Criteria gtAll(String propertyName, Closure<?> propertyValue) {
     return gtAll(propertyName, new grails.gorm.DetachedCriteria(targetClass).build(propertyValue));
@@ -515,6 +540,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    * @param propertyValue The property value
    * @return A Criterion instance
    */
+  @Override
   @SuppressWarnings({"unchecked", "rawtypes"})
   public Criteria ltAll(String propertyName, Closure<?> propertyValue) {
     return ltAll(propertyName, new grails.gorm.DetachedCriteria(targetClass).build(propertyValue));
@@ -528,6 +554,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    * @param propertyValue The property value
    * @return A Criterion instance
    */
+  @Override
   @SuppressWarnings({"unchecked", "rawtypes"})
   public Criteria geAll(String propertyName, Closure<?> propertyValue) {
     return geAll(propertyName, new grails.gorm.DetachedCriteria(targetClass).build(propertyValue));
@@ -541,6 +568,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    * @param propertyValue The property value
    * @return A Criterion instance
    */
+  @Override
   @SuppressWarnings({"unchecked", "rawtypes"})
   public Criteria leAll(String propertyName, Closure<?> propertyValue) {
     return leAll(propertyName, new grails.gorm.DetachedCriteria(targetClass).build(propertyValue));
@@ -554,6 +582,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    * @param propertyValue The property value
    * @return A Criterion instance
    */
+  @Override
   public Criteria eqAll(
       String propertyName, @SuppressWarnings("rawtypes") QueryableCriteria propertyValue) {
     hibernateQuery.eqAll(propertyName, propertyValue);
@@ -568,6 +597,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    * @param propertyValue The property value
    * @return A Criterion instance
    */
+  @Override
   public Criteria gtAll(
       String propertyName, @SuppressWarnings("rawtypes") QueryableCriteria propertyValue) {
     hibernateQuery.gtAll(propertyName, propertyValue);
@@ -657,6 +687,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    * @param propertyValue The property value
    * @return A Criterion instance
    */
+  @Override
   public Criteria ltAll(
       String propertyName, @SuppressWarnings("rawtypes") QueryableCriteria propertyValue) {
     hibernateQuery.ltAll(propertyName, propertyValue);
@@ -671,6 +702,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    * @param propertyValue The property value
    * @return A Criterion instance
    */
+  @Override
   public Criteria geAll(
       String propertyName, @SuppressWarnings("rawtypes") QueryableCriteria propertyValue) {
     hibernateQuery.geAll(propertyName, propertyValue);
@@ -685,6 +717,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    * @param propertyValue The property value
    * @return A Criterion instance
    */
+  @Override
   public Criteria leAll(
       String propertyName, @SuppressWarnings("rawtypes") QueryableCriteria propertyValue) {
     hibernateQuery.leAll(propertyName, propertyValue);
@@ -698,11 +731,13 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    * @param propertyValue The property value
    * @return A Criterion instance
    */
+  @Override
   public Criteria gt(String propertyName, Object propertyValue) {
     hibernateQuery.gt(propertyName, propertyValue);
     return this;
   }
 
+  @Override
   public Criteria lte(String s, Object o) {
     return le(s, o);
   }
@@ -714,6 +749,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    * @param propertyValue The property value
    * @return A Criterion instance
    */
+  @Override
   public Criteria ge(String propertyName, Object propertyValue) {
     hibernateQuery.ge(propertyName, propertyValue);
     return this;
@@ -726,6 +762,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    * @param propertyValue The property value
    * @return A Criterion instance
    */
+  @Override
   public Criteria lt(String propertyName, Object propertyValue) {
     hibernateQuery.lt(propertyName, propertyValue);
     return this;
@@ -738,11 +775,13 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    * @param propertyValue The property value
    * @return A Criterion instance
    */
+  @Override
   public Criteria le(String propertyName, Object propertyValue) {
     hibernateQuery.le(propertyName, propertyValue);
     return this;
   }
 
+  @Override
   public Criteria idEquals(Object o) {
     return idEq(o);
   }
@@ -759,21 +798,25 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
     return this;
   }
 
+  @Override
   public Criteria isEmpty(String property) {
     hibernateQuery.isEmpty(property);
     return this;
   }
 
+  @Override
   public Criteria isNotEmpty(String property) {
     hibernateQuery.isNotEmpty(property);
     return this;
   }
 
+  @Override
   public Criteria isNull(String property) {
     hibernateQuery.isNull(property);
     return this;
   }
 
+  @Override
   public Criteria isNotNull(String property) {
     hibernateQuery.isNotNull(property);
     return this;
@@ -804,10 +847,12 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    * @param propertyValue The property value
    * @return A Criterion instance
    */
+  @Override
   public Criteria eq(String propertyName, Object propertyValue) {
     return eq(propertyName, propertyValue, Collections.emptyMap());
   }
 
+  @Override
   public Criteria idEq(Object o) {
     return eq("id", o);
   }
@@ -847,6 +892,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    * @param propertyValue The like value
    * @return A Criterion instance
    */
+  @Override
   public Criteria like(String propertyName, Object propertyValue) {
     hibernateQuery.like(propertyName, propertyValue.toString());
     return this;
@@ -860,6 +906,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    * @param propertyValue The ilike value
    * @return A Criterion instance
    */
+  @Override
   public Criteria ilike(String propertyName, Object propertyValue) {
     hibernateQuery.ilike(propertyName, propertyValue.toString());
     return this;
@@ -872,6 +919,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    * @param values A collection of values
    * @return A Criterion instance
    */
+  @Override
   @SuppressWarnings("rawtypes")
   public Criteria in(String propertyName, Collection values) {
     hibernateQuery.in(propertyName, values.stream().toList());
@@ -879,13 +927,15 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
   }
 
   /** Delegates to in as in is a Groovy keyword */
+  @Override
   @SuppressWarnings("rawtypes")
   public Criteria inList(String propertyName, Collection values) {
     return in(propertyName, values);
   }
 
   /** Delegates to in as in is a Groovy keyword */
-  public Criteria inList(String propertyName, Object[] values) {
+  @Override
+  public Criteria inList(String propertyName, Object... values) {
     return in(propertyName, values);
   }
 
@@ -896,7 +946,8 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    * @param values A collection of values
    * @return A Criterion instance
    */
-  public Criteria in(String propertyName, Object[] values) {
+  @Override
+  public Criteria in(String propertyName, Object... values) {
     hibernateQuery.in(propertyName, List.of(values));
     return this;
   }
@@ -907,6 +958,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    * @param propertyName The property name to order by
    * @return A Order instance
    */
+  @Override
   public Criteria order(String propertyName) {
     order(new Query.Order(propertyName));
     return this;
@@ -930,6 +982,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    * @param directionString Either "asc" for ascending or "desc" for descending
    * @return A Order instance
    */
+  @Override
   public Criteria order(String propertyName, String directionString) {
     Query.Order.Direction direction =
         Query.Order.Direction.DESC.name().equalsIgnoreCase(directionString)
@@ -946,6 +999,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    * @param size The size to constrain by
    * @return A Criterion instance
    */
+  @Override
   public Criteria sizeEq(String propertyName, int size) {
     hibernateQuery.sizeEq(propertyName, size);
     return this;
@@ -958,6 +1012,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    * @param size The size to constrain by
    * @return A Criterion instance
    */
+  @Override
   public Criteria sizeGt(String propertyName, int size) {
     hibernateQuery.sizeGt(propertyName, size);
     return this;
@@ -971,6 +1026,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    * @param size The size to constrain by
    * @return A Criterion instance
    */
+  @Override
   public Criteria sizeGe(String propertyName, int size) {
     hibernateQuery.sizeGe(propertyName, size);
     return this;
@@ -984,6 +1040,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    * @param size The size to constrain by
    * @return A Criterion instance
    */
+  @Override
   public Criteria sizeLe(String propertyName, int size) {
     hibernateQuery.sizeLe(propertyName, size);
     return this;
@@ -996,6 +1053,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    * @param size The size to constrain by
    * @return A Criterion instance
    */
+  @Override
   public Criteria sizeLt(String propertyName, int size) {
     hibernateQuery.sizeLt(propertyName, size);
     return this;
@@ -1009,6 +1067,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    * @param propertyValue The ilike value
    * @return A Criterion instance
    */
+  @Override
   public org.grails.datastore.mapping.query.api.Criteria rlike(
       String propertyName, Object propertyValue) {
     hibernateQuery.rlike(propertyName, propertyValue.toString());
@@ -1022,6 +1081,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    * @param size The size to constrain by
    * @return A Criterion instance
    */
+  @Override
   public Criteria sizeNe(String propertyName, int size) {
     hibernateQuery.sizeNe(propertyName, size);
     return this;
@@ -1034,6 +1094,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    * @param propertyValue The property value
    * @return The criterion object
    */
+  @Override
   public Criteria ne(String propertyName, Object propertyValue) {
     hibernateQuery.ne(propertyName, propertyValue);
     return this;
@@ -1047,11 +1108,13 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    * @param hi The high value
    * @return A Criterion instance
    */
+  @Override
   public Criteria between(String propertyName, Object lo, Object hi) {
     hibernateQuery.between(propertyName, lo, hi);
     return this;
   }
 
+  @Override
   public Criteria gte(String s, Object o) {
     return ge(s, o);
   }
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/GrailsHibernateTemplate.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/GrailsHibernateTemplate.java
index c75a101bb5..f9a78142de 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/GrailsHibernateTemplate.java
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/GrailsHibernateTemplate.java
@@ -255,6 +255,7 @@ public class GrailsHibernateTemplate implements IHibernateTemplate {
     }
   }
 
+  @Override
   public SessionFactory getSessionFactory() {
     return sessionFactory;
   }
@@ -404,16 +405,19 @@ public class GrailsHibernateTemplate implements IHibernateTemplate {
             new CloseSuppressingInvocationHandler(session, this));
   }
 
+  @Override
   @Deprecated(since = "7.0", forRemoval = true)
   public <T> T get(final Class<T> entityClass, final Serializable id) throws DataAccessException {
     return doExecute(session -> session.find(entityClass, id), true);
   }
 
+  @Override
   @Deprecated(since = "7.0", forRemoval = true)
   public <T> T get(final Class<T> entityClass, final Serializable id, final LockMode mode) {
     return lock(entityClass, id, mode);
   }
 
+  @Override
   public void remove(final Object entity) throws DataAccessException {
     doExecute(
         session -> {
@@ -424,6 +428,7 @@ public class GrailsHibernateTemplate implements IHibernateTemplate {
   }
 
 
+  @Override
   public <T> T load(final Class<T> entityClass, final Serializable id) throws DataAccessException {
     return doExecute(session -> session.getReference(entityClass, id), true);
   }
@@ -446,10 +451,12 @@ public class GrailsHibernateTemplate implements IHibernateTemplate {
         true);
   }
 
+  @Override
   public boolean contains(final Object entity) throws DataAccessException {
     return doExecute(session -> session.contains(entity), true);
   }
 
+  @Override
   public void evict(final Object entity) throws DataAccessException {
     doExecute(
         session -> {
@@ -459,6 +466,7 @@ public class GrailsHibernateTemplate implements IHibernateTemplate {
         true);
   }
 
+  @Override
   public void lock(final Object entity, final LockMode lockMode) throws DataAccessException {
     doExecute(
         session -> {
@@ -468,6 +476,7 @@ public class GrailsHibernateTemplate implements IHibernateTemplate {
         true);
   }
 
+  @Override
   public void refresh(final Object entity) throws DataAccessException {
     refresh(entity, null);
   }
@@ -599,11 +608,13 @@ public class GrailsHibernateTemplate implements IHibernateTemplate {
    *
    * @see #FLUSH_AUTO
    */
+  @Override
   public void setFlushMode(int flushMode) {
     this.flushMode = flushMode;
   }
 
   /** Return if a flush should be forced after executing the callback code. */
+  @Override
   public int getFlushMode() {
     return flushMode;
   }
@@ -696,6 +707,7 @@ public class GrailsHibernateTemplate implements IHibernateTemplate {
     return translator.translate("Hibernate operation: " + msg, sql, sqlException);
   }
 
+  @Override
   public void persist(final Object entity) throws DataAccessException {
     doExecute(
         session -> {
@@ -705,10 +717,12 @@ public class GrailsHibernateTemplate implements IHibernateTemplate {
         true);
   }
 
+  @Override
   public Object merge(final Object entity) throws DataAccessException {
     return doExecute(session -> session.merge(entity), true);
   }
 
+  @Override
   public void flush() throws DataAccessException {
     doExecute(
         session -> {
@@ -718,6 +732,7 @@ public class GrailsHibernateTemplate implements IHibernateTemplate {
         true);
   }
 
+  @Override
   public void clear() throws DataAccessException {
     doExecute(
         session -> {
@@ -727,6 +742,7 @@ public class GrailsHibernateTemplate implements IHibernateTemplate {
         true);
   }
 
+  @Override
   public void deleteAll(final Collection<?> objects) {
     execute(
         (HibernateCallback<Void>)
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateDatastore.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateDatastore.java
index a15eeeefc9..ddf27fab84 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateDatastore.java
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateDatastore.java
@@ -519,6 +519,7 @@ public class HibernateDatastore extends AbstractDatastore
    * @param applicationContext The application context (may be null)
    * @param dataSourceName The data source name
    */
+  @SuppressWarnings("PMD.NullAssignment")
   protected HibernateDatastore(
       MappingContext mappingContext,
       SessionFactory sessionFactory,
@@ -587,9 +588,10 @@ public class HibernateDatastore extends AbstractDatastore
    * @param connectionName The connection name
    * @return The {@link HibernateDatastore}
    */
+  @Override
   public HibernateDatastore getDatastoreForConnection(String connectionName) {
-    if (connectionName.equals(Settings.SETTING_DATASOURCE)
-        || connectionName.equals(ConnectionSource.DEFAULT)) {
+    if (Settings.SETTING_DATASOURCE.equals(connectionName)
+        || ConnectionSource.DEFAULT.equals(connectionName)) {
       return this;
     } else {
       HibernateDatastore hibernateDatastore = this.datastoresByConnectionSource.get(connectionName);
@@ -780,7 +782,7 @@ public class HibernateDatastore extends AbstractDatastore
         try {
           connectionSources.close();
         } catch (IOException e) {
-          LOG.error("There was an error shutting down GORM for an entity: " + e.getMessage(), e);
+          LOG.error("There was an error shutting down GORM for an entity: {}", e.getMessage(), e);
         }
       } finally {
         MappingCacheHolder.getInstance().clear();
@@ -857,28 +859,17 @@ public class HibernateDatastore extends AbstractDatastore
     Action schemaAutoTooling = Action.interpretHbm2ddlSetting(dbCreate);
     if (schemaAutoTooling != Action.VALIDATE && schemaAutoTooling != Action.NONE) {
 
-      Connection connection = null;
-      try {
-        connection = defaultConnectionSource.getDataSource().getConnection();
+      try (Connection connection = defaultConnectionSource.getDataSource().getConnection()) {
         try {
           schemaHandler.useSchema(connection, schemaName);
         } catch (Exception e) {
           // schema doesn't exist
           schemaHandler.createSchema(connection, schemaName);
         }
-
+        schemaHandler.useDefaultSchema(connection);
       } catch (SQLException e) {
         throw new DatastoreConfigurationException(
-            String.format("Failed to create schema for name [%s]", schemaName));
-      } finally {
-        if (connection != null) {
-          try {
-            schemaHandler.useDefaultSchema(connection);
-            connection.close();
-          } catch (SQLException e) {
-            LOG.trace("Failed to reset to default schema: {}", e.getMessage());
-          }
-        }
+            String.format("Failed to create schema for name [%s]", schemaName), e);
       }
     }
 
@@ -1152,7 +1143,7 @@ public class HibernateDatastore extends AbstractDatastore
     try {
       destroy();
     } catch (Exception e) {
-      LOG.error("Error closing hibernate datastore: " + e.getMessage(), e);
+      LOG.error("Error closing hibernate datastore: {}", e.getMessage(), e);
     }
   }
 
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateSession.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateSession.java
index db4dc54ab3..37ef722632 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateSession.java
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateSession.java
@@ -86,7 +86,7 @@ public class HibernateSession extends AbstractAttributeStoringSession
       HibernateDatastore hibernateDatastore, SessionFactory sessionFactory) {
     datastore = hibernateDatastore;
     hibernateTemplate =
-        new GrailsHibernateTemplate(sessionFactory, (HibernateDatastore) getDatastore());
+        new GrailsHibernateTemplate(sessionFactory, datastore);
   }
 
   @Override
@@ -94,6 +94,7 @@ public class HibernateSession extends AbstractAttributeStoringSession
     return false;
   }
 
+  @Override
   public Serializable insert(Object o) {
     return persist(o);
   }
@@ -108,6 +109,7 @@ public class HibernateSession extends AbstractAttributeStoringSession
     connected = false; // don't actually do any disconnection here. This will be handled by OSVI
   }
 
+  @Override
   public Transaction beginTransaction() {
     throw new UnsupportedOperationException("Use HibernatePlatformTransactionManager instead");
   }
@@ -117,10 +119,12 @@ public class HibernateSession extends AbstractAttributeStoringSession
     throw new UnsupportedOperationException("Use HibernatePlatformTransactionManager instead");
   }
 
+  @Override
   public MappingContext getMappingContext() {
     return getDatastore().getMappingContext();
   }
 
+  @Override
   public Serializable persist(Object o) {
     hibernateTemplate.persist(o);
     try {
@@ -136,38 +140,47 @@ public class HibernateSession extends AbstractAttributeStoringSession
     return null;
   }
 
+  @Override
   public Object merge(Object o) {
     return hibernateTemplate.merge(o);
   }
 
+  @Override
   public void refresh(Object o) {
     hibernateTemplate.refresh(o);
   }
 
+  @Override
   public void attach(Object o) {
     hibernateTemplate.lock(o, LockMode.NONE);
   }
 
+  @Override
   public void flush() {
     hibernateTemplate.flush();
   }
 
+  @Override
   public void clear() {
     hibernateTemplate.clear();
   }
 
+  @Override
   public void clear(Object o) {
     hibernateTemplate.evict(o);
   }
 
+  @Override
   public boolean contains(Object o) {
     return hibernateTemplate.contains(o);
   }
 
+  @Override
   public void lock(Object o) {
     hibernateTemplate.lock(o, LockMode.PESSIMISTIC_WRITE);
   }
 
+  @Override
   public void unlock(Object o) {
     // do nothing
   }
@@ -178,6 +191,7 @@ public class HibernateSession extends AbstractAttributeStoringSession
    * @return the result
    */
   @Deprecated
+  @Override
   public List<Serializable> persist(Iterable objects) {
     List<Serializable> ids = new ArrayList<>();
     for (Object object : objects) {
@@ -187,18 +201,22 @@ public class HibernateSession extends AbstractAttributeStoringSession
     return ids;
   }
 
+  @Override
   public <T> T retrieve(Class<T> type, Serializable key) {
     return getHibernateTemplate().execute(session -> session.find(type, key));
   }
 
+  @Override
   public <T> T proxy(Class<T> type, Serializable key) {
     return hibernateTemplate.load(type, key);
   }
 
+  @Override
   public <T> T lock(Class<T> type, Serializable key) {
     return getHibernateTemplate().execute(session -> session.find(type, key, LockModeType.PESSIMISTIC_WRITE));
   }
 
+  @Override
   public void delete(Iterable objects) {
     Collection list = getIterableAsCollection(objects);
     hibernateTemplate.deleteAll(list);
@@ -215,18 +233,22 @@ public class HibernateSession extends AbstractAttributeStoringSession
     return list;
   }
 
+  @Override
   public void delete(Object obj) {
     hibernateTemplate.remove(obj);
   }
 
+  @Override
   public List retrieveAll(Class type, Serializable... keys) {
     return retrieveAll(type, Arrays.asList(keys));
   }
 
+  @Override
   public Persister getPersister(Object o) {
     return null;
   }
 
+  @Override
   public Transaction getTransaction() {
     throw new UnsupportedOperationException("Use HibernatePlatformTransactionManager instead");
   }
@@ -238,15 +260,18 @@ public class HibernateSession extends AbstractAttributeStoringSession
     return resource != null;
   }
 
+  @Override
   public Datastore getDatastore() {
     return datastore;
   }
 
+  @Override
   public boolean isDirty(Object o) {
     // not used, Hibernate manages dirty checking itself
     return true;
   }
 
+  @Override
   public Object getNativeInterface() {
     return hibernateTemplate;
   }
@@ -281,6 +306,7 @@ public class HibernateSession extends AbstractAttributeStoringSession
    * @param criteria The criteria
    * @return The total number of records deleted
    */
+  @Override
   @SuppressWarnings("PMD.DataflowAnomalyAnalysis")
   public long deleteAll(final QueryableCriteria criteria) {
     return getHibernateTemplate()
@@ -312,7 +338,7 @@ public class HibernateSession extends AbstractAttributeStoringSession
 
     List<?> parameters = jpaQueryInfo.getParameters();
     if (parameters != null) {
-      for (int i = 0, count = parameters.size(); i < count; i++) {
+      for (int i = 0; i < parameters.size(); i++) {
         query.setParameter(
             JpaQueryBuilder.PARAMETER_NAME_PREFIX + (i + 1), parameters.get(i));
       }
@@ -327,6 +353,7 @@ public class HibernateSession extends AbstractAttributeStoringSession
    * @param properties The properties
    * @return The total number of records updated
    */
+  @Override
   @SuppressWarnings("PMD.DataflowAnomalyAnalysis")
   public long updateAll(final QueryableCriteria criteria, final Map<String, Object> properties) {
     return getHibernateTemplate()
@@ -366,6 +393,7 @@ public class HibernateSession extends AbstractAttributeStoringSession
                 });
   }
 
+  @Override
   @SuppressWarnings({"PMD.DataflowAnomalyAnalysis", "unchecked"})
   public List retrieveAll(final Class type, final Iterable keys) {
     final PersistentEntity persistentEntity =
@@ -387,6 +415,7 @@ public class HibernateSession extends AbstractAttributeStoringSession
             });
   }
 
+  @Override
   public Query createQuery(Class type) {
     return createQuery(type, null);
   }
@@ -404,6 +433,7 @@ public class HibernateSession extends AbstractAttributeStoringSession
     return (GrailsHibernateTemplate) getNativeInterface();
   }
 
+  @Override
   public void setFlushMode(FlushModeType flushMode) {
     if (flushMode == FlushModeType.AUTO) {
       hibernateTemplate.setFlushMode(GrailsHibernateTemplate.FLUSH_AUTO);
@@ -412,6 +442,7 @@ public class HibernateSession extends AbstractAttributeStoringSession
     }
   }
 
+  @Override
   public FlushModeType getFlushMode() {
       if (hibernateTemplate.getFlushMode() == GrailsHibernateTemplate.FLUSH_COMMIT) {
           return FlushModeType.COMMIT;
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/IdentityEnumType.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/IdentityEnumType.java
index 6610b8b73a..47210825f2 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/IdentityEnumType.java
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/IdentityEnumType.java
@@ -77,6 +77,7 @@ public class IdentityEnumType implements UserType, ParameterizedType, Serializab
     return m;
   }
 
+  @Override
   @SuppressWarnings("unchecked")
   public void setParameterValues(Properties properties) {
     try {
@@ -86,14 +87,14 @@ public class IdentityEnumType implements UserType, ParameterizedType, Serializab
                   .getContextClassLoader()
                   .loadClass((String) properties.get(PARAM_ENUM_CLASS));
       if (LOG.isDebugEnabled()) {
-        LOG.debug(String.format("Building ID-mapping for Enum Class %s", enumClass.getName()));
+        LOG.debug("Building ID-mapping for Enum Class {}", enumClass.getName());
       }
       bidiMap = getBidiEnumMap(enumClass);
       type =
           (AbstractStandardBasicType<?>)
               typeConfiguration.getBasicTypeRegistry().getRegisteredType(bidiMap.keyType.getName());
       if (LOG.isDebugEnabled()) {
-        LOG.debug(String.format("Mapped Basic Type is %s", type));
+        LOG.debug("Mapped Basic Type is {}", type);
       }
       sqlTypes = type.getSqlTypeCodes(null);
     } catch (Exception e) {
@@ -101,8 +102,9 @@ public class IdentityEnumType implements UserType, ParameterizedType, Serializab
     }
   }
 
+  @Override
   public int[] getSqlTypes() {
-    return sqlTypes;
+    return sqlTypes != null ? sqlTypes.clone() : null;
   }
 
   @Override
@@ -110,6 +112,7 @@ public class IdentityEnumType implements UserType, ParameterizedType, Serializab
     return 0;
   }
 
+  @Override
   public Class<?> returnedClass() {
     return enumClass;
   }
@@ -124,34 +127,42 @@ public class IdentityEnumType implements UserType, ParameterizedType, Serializab
     return o.hashCode();
   }
 
+  @Override
   public Object deepCopy(Object o) throws HibernateException {
     return o;
   }
 
+  @Override
   public boolean isMutable() {
     return false;
   }
 
+  @Override
   public Serializable disassemble(Object o) throws HibernateException {
     return (Serializable) o;
   }
 
+  @Override
   public Object assemble(Serializable cached, Object owner) throws HibernateException {
     return cached;
   }
 
+  @Override
   public Object replace(Object orig, Object target, Object owner) throws HibernateException {
     return orig;
   }
 
+  @Override
   public long getDefaultSqlLength() {
     return UserType.super.getDefaultSqlLength();
   }
 
+  @Override
   public int getDefaultSqlPrecision() {
     return UserType.super.getDefaultSqlPrecision();
   }
 
+  @Override
   public int getDefaultSqlScale() {
     return UserType.super.getDefaultSqlScale();
   }
@@ -190,8 +201,7 @@ public class IdentityEnumType implements UserType, ParameterizedType, Serializab
         enumToKey.put((Enum) value, id);
         if (keytoEnum.containsKey(id)) {
           LOG.warn(
-              String.format(
-                  "Duplicate Enum ID '%s' detected for Enum %s!", id, enumClass.getName()));
+              "Duplicate Enum ID '{}' detected for Enum {}!", id, enumClass.getName());
         }
         keytoEnum.put(id, value);
       }
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java
index 7600503b27..c751eeb644 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java
@@ -22,6 +22,7 @@ import grails.gorm.DetachedCriteria;
 import groovy.lang.Closure;
 import jakarta.persistence.criteria.CriteriaQuery;
 import jakarta.persistence.criteria.JoinType;
+import java.util.Deque;
 import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
@@ -65,8 +66,8 @@ public class HibernateQuery extends Query {
   }
 
   private final Map<String, CriteriaAndAlias> createdAssociationPaths = new HashMap<>();
-  protected LinkedList<PersistentEntity> entityStack = new LinkedList<>();
-  protected LinkedList<Association> associationStack = new LinkedList<>();
+  protected Deque<PersistentEntity> entityStack = new LinkedList<>();
+  protected Deque<Association> associationStack = new LinkedList<>();
   protected DetachedCriteria<?> detachedCriteria;
   protected ProxyHandler proxyHandler = new HibernateProxyHandler();
 
@@ -145,6 +146,7 @@ public class HibernateQuery extends Query {
     return detachedCriteria.getCriteria();
   }
 
+  @Override
   public void add(Criterion criterion) {
     detachedCriteria.add(criterion);
   }
@@ -153,6 +155,7 @@ public class HibernateQuery extends Query {
     detachedCriteria.add(new Conjunction(detachedCriteria.getCriteria()));
   }
 
+  @Override
   public void add(Junction currentJunction, Criterion criterion) {
     Disjunction disjunction =
         (Disjunction)
@@ -617,6 +620,7 @@ public class HibernateQuery extends Query {
     return this;
   }
 
+  @Override
   public Query maxResults(int maxResults) {
     this.max = maxResults;
     return this;


(grails-core) 01/34: BRANCHES.md

Posted by bo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

borinquenkid pushed a commit to branch 8.0.x-hibernate7-dev
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit 92865b44c40ceb0c318c97d5a6afe6f95f480063
Author: Walter Duque de Estrada <wb...@mac.com>
AuthorDate: Thu Mar 5 15:33:59 2026 -0600

    BRANCHES.md
---
 BRANCHES.md | 237 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 237 insertions(+)

diff --git a/BRANCHES.md b/BRANCHES.md
new file mode 100644
index 0000000000..5bda5cf376
--- /dev/null
+++ b/BRANCHES.md
@@ -0,0 +1,237 @@
+| Branch | Date | Type |
+| --- | --- | --- |
+| origin/GRAILS-6737-Groovy-1.7.5 | 2010-09-17 | CLOSED |
+| origin/GRAILS-6278 | 2010-09-17 | CLOSED |
+| origin/GRAILS-5087 | 2012-12-07 | CLOSED |
+| origin/GRAILS-9997 | 2013-07-30 | CLOSED |
+| origin/GRAILS-10533 | 2013-10-14 | CLOSED |
+| origin/GRAILS-10512 | 2013-10-14 | CLOSED |
+| origin/GRAILS-10613 | 2013-10-15 | CLOSED |
+| origin/GRAILS-10660 | 2013-10-29 | CLOSED |
+| origin/GRAILS-10631 | 2013-11-05 | CLOSED |
+| origin/GRAILS-10728 | 2013-11-06 | CLOSED |
+| origin/GRAILS-10448 | 2013-11-06 | CLOSED |
+| origin/GRAILS-10780 | 2013-11-19 | CLOSED |
+| origin/GRAILS-10813 | 2013-11-21 | CLOSED |
+| origin/GRAILS-10838 | 2013-11-25 | CLOSED |
+| origin/GRAILS-10826 | 2013-11-26 | CLOSED |
+| origin/GRAILS-10835 | 2013-11-27 | CLOSED |
+| origin/GRAILS-10853 | 2013-12-02 | CLOSED |
+| origin/GRAILS-10868 | 2013-12-03 | CLOSED |
+| origin/GRAILS-10871 | 2013-12-03 | CLOSED |
+| origin/GRAILS-9664 | 2013-12-04 | CLOSED |
+| origin/GRAILS-10882 | 2013-12-09 | CLOSED |
+| origin/GRAILS-10852 | 2013-12-13 | CLOSED |
+| origin/GRAILS-10910 | 2013-12-13 | CLOSED |
+| origin/GRAILS-10908 | 2013-12-14 | CLOSED |
+| origin/GRAILS-10683b | 2013-12-23 | CLOSED |
+| origin/GRAILS-10897 | 2014-01-08 | CLOSED |
+| origin/GRAILS-8426 | 2014-01-10 | CLOSED |
+| origin/GRAILS-10973 | 2014-01-13 | CLOSED |
+| origin/GRAILS-11003 | 2014-01-22 | CLOSED |
+| origin/GRAILS-11011 | 2014-01-22 | CLOSED |
+| origin/GRAILS-11075 | 2014-02-04 | CLOSED |
+| origin/GRAILS-11093 | 2014-02-06 | CLOSED |
+| origin/GRAILS-11104 | 2014-02-11 | CLOSED |
+| origin/GRAILS-10683 | 2014-02-13 | CLOSED |
+| origin/GRAILS-11145 | 2014-02-26 | CLOSED |
+| origin/GRAILS-11197 | 2014-03-10 | CLOSED |
+| origin/GRAILS-9686 | 2014-03-14 | CLOSED |
+| origin/GRAILS-10031 | 2014-03-17 | CLOSED |
+| origin/GRAILS-11222 | 2014-03-18 | CLOSED |
+| origin/GRAILS-11238 | 2014-03-19 | CLOSED |
+| origin/GRAILS-11242 | 2014-03-24 | CLOSED |
+| origin/GRAILS-11204 | 2014-05-01 | CLOSED |
+| origin/GRAILS-6766 | 2014-05-01 | CLOSED |
+| origin/GRAILS-9996 | 2014-05-08 | CLOSED |
+| origin/GRAILS-10905 | 2014-05-08 | CLOSED |
+| origin/GRAILS-11448 | 2014-05-27 | CLOSED |
+| origin/GRAILS-11453 | 2014-05-28 | CLOSED |
+| origin/GRAILS-11462 | 2014-06-02 | CLOSED |
+| origin/GRAILS-11129 | 2014-06-10 | CLOSED |
+| origin/GRAILS-11505 | 2014-06-13 | CLOSED |
+| origin/GRAILS-11505B | 2014-06-17 | CLOSED |
+| origin/GRAILS-11505C | 2014-06-17 | CLOSED |
+| origin/GRAILS-11585 | 2014-07-16 | CLOSED |
+| origin/GRAILS-11576 | 2014-07-25 | CLOSED |
+| origin/GRAILS-11625 | 2014-08-04 | CLOSED |
+| origin/GRAILS-11543 | 2014-08-14 | CLOSED |
+| origin/GRAILS-11666 | 2014-08-18 | CLOSED |
+| origin/GRAILS-11661 | 2014-08-18 | CLOSED |
+| origin/GRAILS-11686 | 2014-08-26 | CLOSED |
+| origin/GRAILS-11680 | 2014-10-21 | CLOSED |
+| origin/GRAILS-11791 | 2014-10-23 | CLOSED |
+| origin/GRAILS-11748 | 2014-10-23 | CLOSED |
+| origin/GRAILS-11806 | 2014-10-30 | CLOSED |
+| origin/GRAILS-11638 | 2014-10-30 | CLOSED |
+| origin/GRAILS-11976 | 2015-02-09 | CLOSED |
+| origin/GRAILS-11973 | 2015-02-09 | CLOSED |
+| origin/GRAILS-11958 | 2015-02-09 | CLOSED |
+| origin/GRAILS-12112 | 2015-03-25 | CLOSED |
+| origin/issue_9183 | 2015-08-13 | CLOSED |
+| origin/issue10188 | 2016-10-27 | CLOSED |
+| origin/issue10282 | 2016-11-19 | CLOSED |
+| origin/GRAILS-10300-10315 | 2016-12-09 | CLOSED |
+| origin/issue10423 | 2017-01-24 | CLOSED |
+| origin/GRAILS-10392 | 2017-02-09 | CLOSED |
+| origin/issue10502 | 2017-02-27 | CLOSED |
+| origin/issue10600 | 2017-04-22 | CLOSED |
+| origin/issue-10844 | 2018-02-26 | CLOSED |
+| origin/issue-10844_take2 | 2020-11-05 | CLOSED |
+| origin/feature/scaffolding-5.1.0 | 2024-09-11 | CLOSED |
+| origin/renovate/major-jansi.version | 2024-10-24 | CLOSED |
+| origin/renovate/major-javahamcrest-monorepo | 2024-10-24 | CLOSED |
+| origin/add-grails-events-transform | 2024-12-23 | CLOSED |
+| origin/renovate/alpine-3.x | 2024-12-27 | CLOSED |
+| origin/renovate/actions-upload-artifact-4.x | 2025-02-21 | CLOSED |
+| origin/renovate/com.gradle.develocity-3.x | 2025-02-25 | CLOSED |
+| origin/renovate/io.micronaut.serde-micronaut-serde-jackson-2.x | 2025-03-03 | CLOSED |
+| origin/renovate/io.micronaut-micronaut-http-client-4.x | 2025-03-13 | CLOSED |
+| origin/issue-14804 | 2025-06-11 | CLOSED |
+| origin/retry-build-step | 2025-06-18 | CLOSED |
+| origin/renovate/micronautversion | 2025-07-12 | CLOSED |
+| origin/addition-micronaut-feature-test | 2025-08-06 | CLOSED |
+| origin/update-rest-transform-dependency | 2025-08-07 | CLOSED |
+| origin/JavaExec-argsFile | 2025-09-22 | CLOSED |
+| origin/java-25-support-test | 2025-09-24 | CLOSED |
+| origin/fix-starter-published-dependencies | 2025-10-04 | CLOSED |
+| origin/fix/null-constructor-arg-groovy4 | 2026-03-03 | CLOSED |
+| origin/issue_8974 | 2015-03-23 | MERGE |
+| origin/issue_610 | 2015-04-06 | MERGE |
+| origin/issue-11211 | 2019-01-03 | MERGE |
+| origin/patch-decouple-gradle | 2024-07-24 | MERGE |
+| origin/web-profile-jar-artifact | 2025-10-08 | MERGE |
+| origin/jrebelFeatureFix | 2025-10-29 | MERGE |
+| origin/chore/gsp_and_gson_dependencies_and_apply | 2025-11-12 | MERGE |
+| origin/fix/issue_15228-respond-errors | 2025-11-18 | MERGE |
+| origin/banner-versions | 2025-11-19 | MERGE |
+| origin/remove-webjars-locator-core-dep | 2025-11-26 | MERGE |
+| origin/merge-back-7.0.5 | 2026-01-12 | MERGE |
+| origin/invokeDynamicDisable | 2026-01-17 | MERGE |
+| origin/deps/update-java-gradle-groovy-versions | 2026-01-27 | MERGE |
+| origin/task/add-agents-md-15145 | 2026-01-30 | MERGE |
+| origin/matrei-patch-1 | 2026-02-12 | MERGE |
+| origin/fix/flaky-geb-tests | 2026-02-19 | MERGE |
+| origin/refactor/centralize-groovydoc-plugin | 2026-02-19 | MERGE |
+| origin/test/query-connection-routing | 2026-02-21 | MERGE |
+| origin/micronaut-fixes-2 | 2026-02-21 | MERGE |
+| origin/forgeReloadingChanges | 2026-02-23 | MERGE |
+| origin/database-cleanup-feature | 2026-02-25 | MERGE |
+| origin/fix-detachedcriteria-join-get-hibernate7 | 2026-02-25 | MERGE |
+| origin/fix-detachedcriteria-join-get | 2026-02-25 | MERGE |
+| origin/fix/where-query-bugs | 2026-02-26 | MERGE |
+| origin/fix/async-promise-spec-read-timeout | 2026-03-03 | MERGE |
+| origin/fix/groovy-joint-ci-stability | 2026-03-03 | MERGE |
+| origin/groovy2 | 2012-03-26 | OTHER |
+| origin/cs-bug-arrays | 2013-04-08 | OTHER |
+| origin/scb-encoding-support | 2013-04-10 | OTHER |
+| origin/grails9190 | 2013-05-15 | OTHER |
+| origin/reactor | 2013-05-31 | OTHER |
+| origin/expressionevaluationutils | 2013-09-22 | OTHER |
+| origin/troubleshootingmasterbranch | 2013-11-11 | OTHER |
+| origin/jefftestbranch | 2013-11-12 | OTHER |
+| origin/bindingformatimprovement | 2013-12-16 | OTHER |
+| origin/beanbuilder | 2014-01-16 | OTHER |
+| origin/typechecking | 2014-01-16 | OTHER |
+| origin/rule_refactoring | 2014-01-28 | OTHER |
+| origin/springloaded_115 | 2014-02-27 | OTHER |
+| origin/grails-web-splitting | 2014-03-22 | OTHER |
+| origin/annotation_collector_problem | 2014-03-25 | OTHER |
+| origin/binding_collection_problem | 2014-04-01 | OTHER |
+| origin/jsp-refactor | 2014-04-11 | OTHER |
+| origin/GROOVY-6836-ClassCastException | 2014-07-21 | OTHER |
+| origin/grails-shell | 2014-09-30 | OTHER |
+| origin/grails-shell-2 | 2014-10-02 | OTHER |
+| origin/grails-shell-3 | 2014-10-06 | OTHER |
+| origin/gsp-split2 | 2014-12-05 | OTHER |
+| origin/Groovy_242_stackmap_frame_error | 2015-03-19 | OTHER |
+| origin/token_replacement | 2015-03-30 | OTHER |
+| origin/owasp | 2015-05-20 | OTHER |
+| origin/command_object_init | 2016-02-25 | OTHER |
+| origin/dont_constrain_readonly_properties | 2016-03-02 | OTHER |
+| origin/json_issue | 2016-03-15 | OTHER |
+| origin/build_scan | 2017-07-27 | OTHER |
+| origin/plugin_issues | 2018-06-15 | OTHER |
+| origin/jackson-renderer-poc | 2018-11-23 | OTHER |
+| origin/gorm-entity | 2018-12-04 | OTHER |
+| origin/gradle-plugin-datastore-rest-client-removal | 2019-03-29 | OTHER |
+| origin/groovy2.5.11 | 2020-04-17 | OTHER |
+| origin/eric/scopeDefaultFix | 2020-07-21 | OTHER |
+| origin/puneetbehl/enableIncrementalGroovyCompile | 2021-08-06 | OTHER |
+| origin/mavenLocal | 2021-12-08 | OTHER |
+| origin/gradle/experiment4 | 2022-01-26 | OTHER |
+| origin/upgrade/apache-groovy | 2022-09-01 | OTHER |
+| origin/buxfix/12596-grails-520-create-app-throws-cannot-resolve-dependency-orgspringframeworkbootspring-boot-dependencies270-no-repositories-are-defined | 2022-09-14 | OTHER |
+| origin/merge-5_2_x | 2022-11-10 | OTHER |
+| origin/12082-micronaut-beans-do-not-receive-configuration-from-environments-block | 2022-12-06 | OTHER |
+| origin/cleanup/grails-shell | 2023-09-06 | OTHER |
+| origin/convert-ContainerRender-to-trait | 2024-12-10 | OTHER |
+| origin/renovate/pin-dependencies | 2025-03-07 | OTHER |
+| origin/groovy-debug-ast-logging | 2025-04-29 | OTHER |
+| origin/groovydoc-tool-rewrite | 2025-05-23 | OTHER |
+| origin/markup-issue | 2025-06-13 | OTHER |
+| origin/url-mapping-testing | 2025-06-14 | OTHER |
+| origin/feature/gradle9 | 2025-09-18 | OTHER |
+| origin/grails7-initial-neo4jUpdates | 2025-10-02 | OTHER |
+| origin/groovy-5-fixes | 2026-02-05 | OTHER |
+| origin/micronaut-fixes | 2026-02-18 | OTHER |
+| origin/configuration-command | 2026-02-19 | OTHER |
+| origin/renovate/micronautserdejacksonversion | 2025-03-03 | OPEN |
+| origin/renovate/major-apache-maven-resolver-monorepo | 2025-07-12 | OPEN |
+| origin/issue-11795 | 2025-08-18 | OPEN |
+| origin/fix/clarify-caffeine | 2025-09-23 | OPEN |
+| origin/issue15290 | 2025-12-16 | OPEN |
+| origin/dependabot/github_actions/gradle/actions-5 | 2026-02-03 | OPEN |
+| origin/dependabot/gradle/grails-forge/7.0.x/com.gradle.common-custom-user-data-gradle-plugin-2.4.0 | 2026-02-03 | OPEN |
+| origin/groovy-5 | 2026-02-04 | OPEN |
+| origin/dependabot/github_actions/actions/cache-5 | 2026-02-17 | OPEN |
+| origin/feat/publish-groovydoc-plugin | 2026-02-21 | OPEN |
+| origin/issue-13752-upgrade-jansi-jline | 2026-02-25 | OPEN |
+| origin/upgrade/gradle-9.3.1 | 2026-02-25 | OPEN |
+| origin/feat/gradle-managed-version-overrides | 2026-02-26 | OPEN |
+| origin/docs/configuration-hybrid | 2026-02-26 | OPEN |
+| origin/deprecate-for-removal | 2026-02-27 | OPEN |
+| origin/docs/spring-security-upgrade-instructions | 2026-02-28 | OPEN |
+| origin/conditionalPluginConfiguration | 2026-03-01 | OPEN |
+| origin/fix/negative-number-locale-15178 | 2026-03-02 | OPEN |
+| origin/fix/scaffolding-test-flaky-login | 2026-03-03 | OPEN |
+| origin/feature/taglib-method-actions | 2026-03-03 | OPEN |
+| origin/fix/dataservice-null-datastore-guard | 2026-03-03 | OPEN |
+| origin/fix/ersatz-roundtrip-connection-reset | 2026-03-03 | OPEN |
+| origin/feat/http-client-testing-support | 2026-03-05 | OPEN |
+| origin/1.1.x | 2009-11-26 | RELEASE |
+| origin/1.3.0.RC2 | 2010-04-23 | RELEASE |
+| origin/1.2.x | 2010-10-11 | RELEASE |
+| origin/1.3.x | 2012-06-01 | RELEASE |
+| origin/2.0.x | 2013-05-30 | RELEASE |
+| origin/2.1.x | 2013-09-21 | RELEASE |
+| origin/2.2.x | 2014-07-27 | RELEASE |
+| origin/2.3.x | 2015-06-17 | RELEASE |
+| origin/2.4.x | 2015-09-08 | RELEASE |
+| origin/3.0.x | 2016-07-27 | RELEASE |
+| origin/3.1.x | 2017-05-09 | RELEASE |
+| origin/3.1.x-issue-9058 | 2017-05-23 | RELEASE |
+| origin/3.2.x | 2019-10-10 | RELEASE |
+| origin/master | 2021-11-24 | RELEASE |
+| origin/4.0.x | 2022-06-03 | RELEASE |
+| origin/5.1.x | 2022-10-13 | RELEASE |
+| origin/5.0.x | 2022-11-25 | RELEASE |
+| origin/5.2.x | 2023-02-13 | RELEASE |
+| origin/2.5.x | 2023-12-17 | RELEASE |
+| origin/3.3.x | 2024-01-09 | RELEASE |
+| origin/4.1.x | 2024-01-26 | RELEASE |
+| origin/5.3.x | 2024-01-26 | RELEASE |
+| origin/6.1.x | 2024-02-27 | RELEASE |
+| origin/6.0.x | 2024-04-09 | RELEASE |
+| origin/5.4.x | 2024-09-11 | RELEASE |
+| origin/6.2.x | 2025-01-03 | RELEASE |
+| origin/gh-pages | 2025-01-07 | RELEASE |
+| origin/7.0.x-hibernate6 | 2025-10-15 | RELEASE |
+| origin/7.0.x-binding-error-14947-15147 | 2025-10-21 | RELEASE |
+| origin/7.1.x-hibernate6 | 2025-12-03 | RELEASE |
+| origin/7.1.x | 2026-02-27 | RELEASE |
+| origin/8.0.x | 2026-02-28 | RELEASE |
+| origin/8.0.x-hibernate7 | 2026-03-01 | RELEASE |
+| origin/7.0.x | 2026-03-04 | RELEASE |
+| origin | 2026-03-04 | RELEASE |
+| origin/8.0.x-hibernate7-dev | 2026-03-05 | RELEASE |


(grails-core) 11/34: hibernate7: PredicateGenerator now uses ConversionService to coerce accidental String to Number

Posted by bo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

borinquenkid pushed a commit to branch 8.0.x-hibernate7-dev
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit f44737e51c8878321f8b49837a4332263968df01
Author: Walter Duque de Estrada <wb...@mac.com>
AuthorDate: Fri Mar 6 07:30:04 2026 -0600

    hibernate7: PredicateGenerator now uses ConversionService to coerce accidental String to Number
---
 .../grails/orm/hibernate/query/HibernateQuery.java |  5 ++++-
 .../hibernate/query/JpaCriteriaQueryCreator.java   |  9 +++++++--
 .../orm/hibernate/query/PredicateGenerator.java    | 15 ++++++++++++++
 .../JpaCriteriaQueryCreatorSpec.groovy             | 19 +++++++++---------
 .../hibernatequery/PredicateGeneratorSpec.groovy   | 23 +++++++++++++++++++++-
 5 files changed, 58 insertions(+), 13 deletions(-)

diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java
index 21b8c06d62..61a47e48ea 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java
@@ -45,6 +45,7 @@ import org.hibernate.Session;
 import org.hibernate.SessionFactory;
 import org.hibernate.query.criteria.HibernateCriteriaBuilder;
 import org.hibernate.query.criteria.JpaCriteriaQuery;
+import org.springframework.core.convert.ConversionService;
 import org.springframework.dao.InvalidDataAccessApiUsageException;
 
 /**
@@ -410,7 +411,9 @@ public class HibernateQuery extends Query {
   }
 
   public JpaCriteriaQuery<?> getJpaCriteriaQuery() {
-    return new JpaCriteriaQueryCreator(projections, getCriteriaBuilder(), entity, detachedCriteria)
+    ConversionService conversionService =
+        getSession().getMappingContext().getConversionService();
+    return new JpaCriteriaQueryCreator(projections, getCriteriaBuilder(), entity, detachedCriteria, conversionService)
         .createQuery();
   }
 
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/JpaCriteriaQueryCreator.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/JpaCriteriaQueryCreator.java
index 60378b3545..201c0cabae 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/JpaCriteriaQueryCreator.java
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/JpaCriteriaQueryCreator.java
@@ -37,6 +37,8 @@ import org.hibernate.query.criteria.HibernateCriteriaBuilder;
 import org.hibernate.query.criteria.JpaCriteriaQuery;
 import org.hibernate.query.criteria.JpaExpression;
 
+import org.springframework.core.convert.ConversionService;
+
 @SuppressWarnings("PMD.DataflowAnomalyAnalysis")
 public class JpaCriteriaQueryCreator {
 
@@ -44,16 +46,19 @@ public class JpaCriteriaQueryCreator {
   private final HibernateCriteriaBuilder criteriaBuilder;
   private final PersistentEntity entity;
   private final DetachedCriteria<?> detachedCriteria;
+  private final ConversionService conversionService;
 
   public JpaCriteriaQueryCreator(
       Query.ProjectionList projections,
       HibernateCriteriaBuilder criteriaBuilder,
       PersistentEntity entity,
-      DetachedCriteria<?> detachedCriteria) {
+      DetachedCriteria<?> detachedCriteria,
+      ConversionService conversionService) {
     this.projections = projections;
     this.criteriaBuilder = criteriaBuilder;
     this.entity = entity;
     this.detachedCriteria = detachedCriteria;
+    this.conversionService = conversionService;
   }
 
   public JpaCriteriaQuery<?> createQuery() {
@@ -156,7 +161,7 @@ public class JpaCriteriaQueryCreator {
     List<Query.Criterion> criteriaList = detachedCriteria.getCriteria();
     if (!criteriaList.isEmpty()) {
       Predicate[] predicates =
-          new PredicateGenerator()
+          new PredicateGenerator(conversionService)
               .getPredicates(criteriaBuilder, cq, root, criteriaList, tablesByName, entity);
       cq.where(criteriaBuilder.and(predicates));
     }
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java
index 8488ef23d1..ed9c2b3b8d 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java
@@ -47,6 +47,7 @@ import org.hibernate.query.sqm.tree.domain.SqmPath;
 import org.hibernate.query.sqm.tree.predicate.SqmInListPredicate;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.core.convert.ConversionService;
 
 @Slf4j
 @SuppressWarnings({
@@ -63,6 +64,13 @@ import org.slf4j.LoggerFactory;
 public class PredicateGenerator {
   private static final Logger log = LoggerFactory.getLogger(PredicateGenerator.class);
 
+  private final ConversionService conversionService;
+
+
+  public PredicateGenerator(ConversionService conversionService) {
+    this.conversionService = conversionService;
+  }
+
   public Predicate[] getPredicates(
       HibernateCriteriaBuilder cb,
       CriteriaQuery<?> criteriaQuery,
@@ -472,6 +480,13 @@ public class PredicateGenerator {
   private Number getNumericValue(Query.PropertyCriterion criterion) {
     Object value = criterion.getValue();
     if (value instanceof Number num) return num;
+    if (value != null && conversionService.canConvert(value.getClass(), Number.class)) {
+      try {
+        return conversionService.convert(value, Number.class);
+      } catch (org.springframework.core.convert.ConversionException ignored) {
+        // fall through to ConfigurationException
+      }
+    }
     throw new ConfigurationException(
         String.format(
             "Operation '%s' on property '%s' only accepts a numeric value, but received a %s",
diff --git a/grails-data-hibernate7/core/src/test/groovy/grails/gorm/specs/hibernatequery/JpaCriteriaQueryCreatorSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/grails/gorm/specs/hibernatequery/JpaCriteriaQueryCreatorSpec.groovy
index 968e78f914..32686a2eed 100644
--- a/grails-data-hibernate7/core/src/test/groovy/grails/gorm/specs/hibernatequery/JpaCriteriaQueryCreatorSpec.groovy
+++ b/grails-data-hibernate7/core/src/test/groovy/grails/gorm/specs/hibernatequery/JpaCriteriaQueryCreatorSpec.groovy
@@ -7,6 +7,7 @@ import org.grails.datastore.mapping.query.Query
 import org.grails.orm.hibernate.query.JpaCriteriaQueryCreator
 import org.hibernate.query.criteria.HibernateCriteriaBuilder
 import org.hibernate.query.criteria.JpaCriteriaQuery
+import org.springframework.core.convert.support.DefaultConversionService
 
 class JpaCriteriaQueryCreatorSpec extends HibernateGormDatastoreSpec {
 
@@ -23,7 +24,7 @@ class JpaCriteriaQueryCreatorSpec extends HibernateGormDatastoreSpec {
         projections.property("firstName")
 
         
-        var creator = new JpaCriteriaQueryCreator(projections, criteriaBuilder, entity, detachedCriteria)
+        var creator = new JpaCriteriaQueryCreator(projections, criteriaBuilder, entity, detachedCriteria, new DefaultConversionService())
 
         when:
         JpaCriteriaQuery<?> query = creator.createQuery()
@@ -43,7 +44,7 @@ class JpaCriteriaQueryCreatorSpec extends HibernateGormDatastoreSpec {
         projections.property("lastName")
 
 
-        var creator = new JpaCriteriaQueryCreator(projections, criteriaBuilder, entity, detachedCriteria)
+        var creator = new JpaCriteriaQueryCreator(projections, criteriaBuilder, entity, detachedCriteria, new DefaultConversionService())
 
         when:
         JpaCriteriaQuery<?> query = creator.createQuery()
@@ -62,7 +63,7 @@ class JpaCriteriaQueryCreatorSpec extends HibernateGormDatastoreSpec {
         projections.count()
 
 
-        var creator = new JpaCriteriaQueryCreator(projections, criteriaBuilder, entity, detachedCriteria)
+        var creator = new JpaCriteriaQueryCreator(projections, criteriaBuilder, entity, detachedCriteria, new DefaultConversionService())
 
         when:
         JpaCriteriaQuery<?> query = creator.createQuery()
@@ -80,7 +81,7 @@ class JpaCriteriaQueryCreatorSpec extends HibernateGormDatastoreSpec {
         projections.countDistinct("firstName")
 
 
-        var creator = new JpaCriteriaQueryCreator(projections, criteriaBuilder, entity, detachedCriteria)
+        var creator = new JpaCriteriaQueryCreator(projections, criteriaBuilder, entity, detachedCriteria, new DefaultConversionService())
 
         when:
         JpaCriteriaQuery<?> query = creator.createQuery()
@@ -98,7 +99,7 @@ class JpaCriteriaQueryCreatorSpec extends HibernateGormDatastoreSpec {
         projections.id()
 
 
-        var creator = new JpaCriteriaQueryCreator(projections, criteriaBuilder, entity, detachedCriteria)
+        var creator = new JpaCriteriaQueryCreator(projections, criteriaBuilder, entity, detachedCriteria, new DefaultConversionService())
 
         when:
         JpaCriteriaQuery<?> query = creator.createQuery()
@@ -119,7 +120,7 @@ class JpaCriteriaQueryCreatorSpec extends HibernateGormDatastoreSpec {
         projections.sum("age")
 
 
-        var creator = new JpaCriteriaQueryCreator(projections, criteriaBuilder, entity, detachedCriteria)
+        var creator = new JpaCriteriaQueryCreator(projections, criteriaBuilder, entity, detachedCriteria, new DefaultConversionService())
 
         when:
         JpaCriteriaQuery<?> query = creator.createQuery()
@@ -141,7 +142,7 @@ class JpaCriteriaQueryCreatorSpec extends HibernateGormDatastoreSpec {
         projections.count()
 
 
-        var creator = new JpaCriteriaQueryCreator(projections, criteriaBuilder, entity, detachedCriteria)
+        var creator = new JpaCriteriaQueryCreator(projections, criteriaBuilder, entity, detachedCriteria, new DefaultConversionService())
 
         when:
         JpaCriteriaQuery<?> query = creator.createQuery()
@@ -160,7 +161,7 @@ class JpaCriteriaQueryCreatorSpec extends HibernateGormDatastoreSpec {
         var projections = new Query.ProjectionList()
 
 
-        var creator = new JpaCriteriaQueryCreator(projections, criteriaBuilder, entity, detachedCriteria)
+        var creator = new JpaCriteriaQueryCreator(projections, criteriaBuilder, entity, detachedCriteria, new DefaultConversionService())
 
         when:
         JpaCriteriaQuery<?> query = creator.createQuery()
@@ -180,7 +181,7 @@ class JpaCriteriaQueryCreatorSpec extends HibernateGormDatastoreSpec {
         projections.property("firstName")
 
 
-        var creator = new JpaCriteriaQueryCreator(projections, criteriaBuilder, entity, detachedCriteria)
+        var creator = new JpaCriteriaQueryCreator(projections, criteriaBuilder, entity, detachedCriteria, new DefaultConversionService())
 
         when:
         JpaCriteriaQuery<?> query = creator.createQuery()
diff --git a/grails-data-hibernate7/core/src/test/groovy/grails/gorm/specs/hibernatequery/PredicateGeneratorSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/grails/gorm/specs/hibernatequery/PredicateGeneratorSpec.groovy
index 6eb19d48fd..2fc7f6a795 100644
--- a/grails-data-hibernate7/core/src/test/groovy/grails/gorm/specs/hibernatequery/PredicateGeneratorSpec.groovy
+++ b/grails-data-hibernate7/core/src/test/groovy/grails/gorm/specs/hibernatequery/PredicateGeneratorSpec.groovy
@@ -12,6 +12,7 @@ import org.grails.datastore.mapping.query.Query
 import org.grails.orm.hibernate.query.JpaFromProvider
 import org.grails.orm.hibernate.query.PredicateGenerator
 import org.hibernate.query.criteria.HibernateCriteriaBuilder
+import org.springframework.core.convert.support.DefaultConversionService
 
 class PredicateGeneratorSpec extends HibernateGormDatastoreSpec {
 
@@ -23,7 +24,7 @@ class PredicateGeneratorSpec extends HibernateGormDatastoreSpec {
     PersistentEntity personEntity
 
     def setup() {
-        predicateGenerator = new PredicateGenerator()
+        predicateGenerator = new PredicateGenerator(new DefaultConversionService())
         cb = sessionFactory.getCriteriaBuilder()
         query = cb.createQuery(Person)
         root = query.from(Person)
@@ -481,4 +482,24 @@ class PredicateGeneratorSpec extends HibernateGormDatastoreSpec {
         then:
         predicates.length == 1
     }
+
+    def "test gt with String value is coerced to Number"() {
+        given:
+        List criteria = [new Query.GreaterThan("age", "20")]
+        when:
+        def predicates = predicateGenerator.getPredicates(cb, query, root, criteria, fromProvider, personEntity)
+        then:
+        noExceptionThrown()
+        predicates.length == 1
+    }
+
+    def "test lt with String value is coerced to Number"() {
+        given:
+        List criteria = [new Query.LessThan("age", "30")]
+        when:
+        def predicates = predicateGenerator.getPredicates(cb, query, root, criteria, fromProvider, personEntity)
+        then:
+        noExceptionThrown()
+        predicates.length == 1
+    }
 }


(grails-core) 28/34: hibernate7: more CodeNarc

Posted by bo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

borinquenkid pushed a commit to branch 8.0.x-hibernate7-dev
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit 613b2d8964dd2d802bd9d79ec39349f0195777f0
Author: Walter Duque de Estrada <wb...@mac.com>
AuthorDate: Sat Mar 7 19:34:13 2026 -0600

    hibernate7: more CodeNarc
---
 .../groovy/org/grails/orm/hibernate/HibernateGormInstanceApi.groovy    | 2 +-
 .../main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy | 3 +--
 .../groovy/org/grails/orm/hibernate/cfg/DiscriminatorConfig.groovy     | 1 +
 .../cfg/domainbinding/hibernate/HibernateMappingKeyword.groovy         | 1 +
 4 files changed, 4 insertions(+), 3 deletions(-)

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 195da3939c..fb9583d666 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
@@ -425,4 +425,4 @@ class HibernateGormInstanceApi<D> extends GormInstanceApi<D> {
     void setObjectToReadOnly(Object target) {
         GrailsHibernateUtil.setObjectToReadyOnly(target, sessionFactory)
     }
-}
\ No newline at end of file
+}
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy
index d6545ee4db..c56a484d2f 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy
@@ -268,7 +268,7 @@ class HibernateGormStaticApi<D> extends GormStaticApi<D> {
                 "${method}(CharSequence) only accepts a Groovy GString with interpolated parameters " +
                 "(e.g. ${method}(\"from Foo where bar = \${value}\")). " +
                 "Use the parameterized overload ${method}(CharSequence, Map) or ${method}(CharSequence, Collection, Map) " +
-                "to pass a plain String query safely."
+                'to pass a plain String query safely.'
             )
         }
     }
@@ -307,7 +307,6 @@ class HibernateGormStaticApi<D> extends GormStaticApi<D> {
         return "from ${persistentEntity.name} where $whereClause"
     }
 
-
     @Override
     List executeQuery(CharSequence query, Map namedParams, Map args) {
         doListInternal(query, namedParams, [], args, false)
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/DiscriminatorConfig.groovy b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/DiscriminatorConfig.groovy
index ee79e025a5..d52f26c7e5 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/DiscriminatorConfig.groovy
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/DiscriminatorConfig.groovy
@@ -13,6 +13,7 @@ import groovy.transform.builder.SimpleStrategy
 @CompileStatic
 @Builder(builderStrategy = SimpleStrategy, prefix = '')
 class DiscriminatorConfig {
+
     /**
      * The discriminator value
      */
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateMappingKeyword.groovy b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateMappingKeyword.groovy
index c745f28605..db7116bbf8 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateMappingKeyword.groovy
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateMappingKeyword.groovy
@@ -25,6 +25,7 @@ import groovy.transform.CompileStatic
  */
 @CompileStatic
 enum HibernateMappingKeyword {
+
     INCLUDES('includes'),
     HIBERNATE_CUSTOM_USER_TYPE('hibernateCustomUserType'),
     TABLE('table'),


(grails-core) 18/34: hibernate7: more Codenarc

Posted by bo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

borinquenkid pushed a commit to branch 8.0.x-hibernate7-dev
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit 97d831e2198b7f4a1fbe753a6db4f41fc458b9f9
Author: Walter Duque de Estrada <wb...@mac.com>
AuthorDate: Sat Mar 7 12:33:20 2026 -0600

    hibernate7: more Codenarc
---
 .../hibernate/mapping/MappingBuilder.groovy        |  2 +-
 .../org/grails/orm/hibernate/cfg/JoinTable.groovy  |  1 +
 .../org/grails/orm/hibernate/cfg/Mapping.groovy    | 97 +++++++++++-----------
 .../org/grails/orm/hibernate/cfg/NaturalId.groovy  |  2 +-
 .../grails/orm/hibernate/cfg/PropertyConfig.groovy | 82 +++++++++---------
 .../cfg/PropertyDefinitionDelegate.groovy          | 23 ++---
 .../org/grails/orm/hibernate/cfg/SortConfig.groovy |  1 +
 .../org/grails/orm/hibernate/cfg/Table.groovy      |  1 +
 8 files changed, 104 insertions(+), 105 deletions(-)

diff --git a/grails-data-hibernate7/core/src/main/groovy/grails/orm/hibernate/mapping/MappingBuilder.groovy b/grails-data-hibernate7/core/src/main/groovy/grails/gorm/hibernate/mapping/MappingBuilder.groovy
similarity index 97%
rename from grails-data-hibernate7/core/src/main/groovy/grails/orm/hibernate/mapping/MappingBuilder.groovy
rename to grails-data-hibernate7/core/src/main/groovy/grails/gorm/hibernate/mapping/MappingBuilder.groovy
index 1c663f48ea..83c82299bc 100644
--- a/grails-data-hibernate7/core/src/main/groovy/grails/orm/hibernate/mapping/MappingBuilder.groovy
+++ b/grails-data-hibernate7/core/src/main/groovy/grails/gorm/hibernate/mapping/MappingBuilder.groovy
@@ -50,7 +50,7 @@ class MappingBuilder {
 
         @Override
         Mapping build() {
-            if(mapping == null) {
+            if (mapping == null) {
                 mapping = Mapping.configureNew(definition)
             }
             return mapping
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/JoinTable.groovy b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/JoinTable.groovy
index cc08d9bbf9..1f861f156d 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/JoinTable.groovy
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/JoinTable.groovy
@@ -31,6 +31,7 @@ import groovy.transform.builder.SimpleStrategy
 @Builder(builderStrategy = SimpleStrategy, prefix = '')
 @CompileStatic
 class JoinTable extends Table {
+
     /**
      * The foreign key column
      */
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/Mapping.groovy b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/Mapping.groovy
index 80a4d021d1..e4cb7c3d8b 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/Mapping.groovy
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/Mapping.groovy
@@ -49,7 +49,7 @@ class Mapping extends Entity<PropertyConfig> {
             return null
         }
 
-        return type instanceof Class ? ((Class)type).name : type.toString()
+        return type instanceof Class ? ((Class) type).name : type.toString()
     }
 
     /**
@@ -97,7 +97,6 @@ class Mapping extends Entity<PropertyConfig> {
      */
     HibernateIdentity identity = new Identity()
 
-
     /**
      * Caching config
      */
@@ -139,7 +138,6 @@ class Mapping extends Entity<PropertyConfig> {
      */
     String comment
 
-
     boolean isJoinedSubclass() {
         return !tablePerHierarchy && !tablePerConcreteClass
     }
@@ -161,6 +159,7 @@ class Mapping extends Entity<PropertyConfig> {
     Map<String, PropertyConfig> getPropertyConfigs() {
         return columns
     }
+
     /**
      * Define the table name
      * @param name The table name
@@ -192,6 +191,7 @@ class Mapping extends Entity<PropertyConfig> {
         Table.configureExisting(table, tableConfig)
         return this
     }
+
     /**
      * Define the identity config
      * @param identityConfig The id config
@@ -199,11 +199,12 @@ class Mapping extends Entity<PropertyConfig> {
      */
     @Override
     Mapping id(Map identityConfig) {
-        if(identity instanceof Identity) {
-            Identity.configureExisting((Identity)identity, identityConfig)
+        if (identity instanceof Identity) {
+            Identity.configureExisting((Identity) identity, identityConfig)
         }
         return this
     }
+
     /**
      * Define the identity config
      * @param identityConfig The id config
@@ -211,8 +212,8 @@ class Mapping extends Entity<PropertyConfig> {
      */
     @Override
     Mapping id(@DelegatesTo(Identity) Closure identityConfig) {
-        if(identity instanceof Identity) {
-            Identity.configureExisting((Identity)identity, identityConfig)
+        if (identity instanceof Identity) {
+            Identity.configureExisting((Identity) identity, identityConfig)
         }
         return this
     }
@@ -222,7 +223,6 @@ class Mapping extends Entity<PropertyConfig> {
      * @param identityConfig The id config
      * @return This mapping
      */
-
     Mapping id(CompositeIdentity compositeIdentity) {
         this.identity = compositeIdentity
         return this
@@ -234,7 +234,7 @@ class Mapping extends Entity<PropertyConfig> {
      * @return This mapping
      */
     Mapping cache(@DelegatesTo(CacheConfig) Closure cacheConfig) {
-        if(this.cache == null) {
+        if (this.cache == null) {
             this.cache = new CacheConfig()
         }
         CacheConfig.configureExisting(cache, cacheConfig)
@@ -247,7 +247,7 @@ class Mapping extends Entity<PropertyConfig> {
      * @return This mapping
      */
     Mapping cache(Map cacheConfig) {
-        if(this.cache == null) {
+        if (this.cache == null) {
             this.cache = new CacheConfig()
         }
         CacheConfig.configureExisting(cache, cacheConfig)
@@ -260,7 +260,7 @@ class Mapping extends Entity<PropertyConfig> {
      * @return This mapping
      */
     Mapping cache(String usage) {
-        if(this.cache == null) {
+        if (this.cache == null) {
             this.cache = new CacheConfig()
         }
         this.cache.usage = usage
@@ -268,7 +268,6 @@ class Mapping extends Entity<PropertyConfig> {
         return this
     }
 
-
     /**
      * Configures sorting
      * @param name The name
@@ -276,7 +275,7 @@ class Mapping extends Entity<PropertyConfig> {
      * @return This mapping
      */
     Mapping sort(String name, String direction) {
-        if(name && direction) {
+        if (name && direction) {
             this.sort.name = name
             this.sort.direction = direction
         }
@@ -290,7 +289,7 @@ class Mapping extends Entity<PropertyConfig> {
      * @return This mapping
      */
     Mapping sort(Map nameAndDirections) {
-        if(nameAndDirections) {
+        if (nameAndDirections) {
             this.sort.namesAndDirections = nameAndDirections
         }
         return this
@@ -302,7 +301,7 @@ class Mapping extends Entity<PropertyConfig> {
      * @return This mapping
      */
     Mapping discriminator(@DelegatesTo(DiscriminatorConfig) Closure discriminatorDef) {
-        if(discriminator == null) {
+        if (discriminator == null) {
             discriminator = new DiscriminatorConfig()
         }
         discriminatorDef.setDelegate(discriminator)
@@ -317,7 +316,7 @@ class Mapping extends Entity<PropertyConfig> {
      * @return This mapping
      */
     Mapping discriminator(String value) {
-        if(discriminator == null) {
+        if (discriminator == null) {
             discriminator = new DiscriminatorConfig()
         }
         discriminator.value = value
@@ -330,28 +329,28 @@ class Mapping extends Entity<PropertyConfig> {
      * @return This mapping
      */
     Mapping discriminator(Map args) {
-        if(args != null) {
-            if(discriminator == null) {
+        if (args != null) {
+            if (discriminator == null) {
                 discriminator = new DiscriminatorConfig()
             }
 
             String value = args.remove('value')?.toString()
             discriminator.value = value
             if (args.column instanceof String) {
-                discriminator.column = new ColumnConfig(name:args.column.toString())
+                discriminator.column = new ColumnConfig(name: args.column.toString())
             }
             else if (args.column instanceof Map) {
                 ColumnConfig config = new ColumnConfig()
                 DataBinder dataBinder = new DataBinder(config)
-                dataBinder.bind(new MutablePropertyValues((Map)args.column))
+                dataBinder.bind(new MutablePropertyValues((Map) args.column))
                 discriminator.column = config
             }
             discriminator.type(args.remove('type'))
-            if(args.containsKey('insert')) {
-                discriminator.insertable( args.remove('insert') as Boolean )
+            if (args.containsKey('insert')) {
+                discriminator.insertable(args.remove('insert') as Boolean)
             }
-            if(args.containsKey('insertable')) {
-                discriminator.insertable( args.remove('insertable') as Boolean )
+            if (args.containsKey('insertable')) {
+                discriminator.insertable(args.remove('insertable') as Boolean)
             }
             discriminator.formula(args.remove('formula')?.toString())
         }
@@ -363,9 +362,9 @@ class Mapping extends Entity<PropertyConfig> {
      * @param propertyNames
      * @return
      */
-    CompositeIdentity composite(String...propertyNames) {
+    CompositeIdentity composite(String... propertyNames) {
         identity = new CompositeIdentity(propertyNames: propertyNames)
-        return (CompositeIdentity)identity
+        return (CompositeIdentity) identity
     }
 
     /**
@@ -403,11 +402,10 @@ class Mapping extends Entity<PropertyConfig> {
     @CompileStatic
     Mapping version(String versionColumn) {
         PropertyConfig pc = getOrInitializePropertyConfig(GormProperties.VERSION)
-        pc.columns << new ColumnConfig(name:versionColumn)
+        pc.columns << new ColumnConfig(name: versionColumn)
         return this
     }
 
-
     /**
      * Configure a property
      * @param name The name of the property
@@ -442,7 +440,7 @@ class Mapping extends Entity<PropertyConfig> {
      */
     @Override
     PropertyConfig property(@DelegatesTo(PropertyConfig) Closure propertyConfig) {
-        if(columns.containsKey('*')) {
+        if (columns.containsKey('*')) {
             PropertyConfig cloned = cloneGlobalConstraint()
             return PropertyConfig.configureExisting(cloned, propertyConfig)
         }
@@ -461,6 +459,7 @@ class Mapping extends Entity<PropertyConfig> {
     Entity version(@DelegatesTo(PropertyConfig) Closure versionConfig) {
         return super.version(versionConfig)
     }
+
     /**
      * Configure a new property
      * @param name The name of the property
@@ -468,8 +467,8 @@ class Mapping extends Entity<PropertyConfig> {
      * @return This mapping
      */
     @Override
-    PropertyConfig property( Map propertyConfig) {
-        if(columns.containsKey('*')) {
+    PropertyConfig property(Map propertyConfig) {
+        if (columns.containsKey('*')) {
             // apply global constraints constraints
             PropertyConfig cloned = cloneGlobalConstraint()
             return PropertyConfig.configureExisting(cloned, propertyConfig)
@@ -518,11 +517,11 @@ class Mapping extends Entity<PropertyConfig> {
 
     @Override
     def propertyMissing(String name, Object val) {
-        if(val instanceof Closure) {
-            property(name, (Closure)val)
+        if (val instanceof Closure) {
+            property(name, (Closure) val)
         }
-        else if(val instanceof PropertyConfig) {
-            columns[name] =((PropertyConfig)val)
+        else if (val instanceof PropertyConfig) {
+            columns[name] = ((PropertyConfig) val)
         }
         else {
             throw new MissingPropertyException(name, Mapping)
@@ -531,21 +530,21 @@ class Mapping extends Entity<PropertyConfig> {
 
     @Override
     def methodMissing(String name, Object args) {
-        if(args && args.getClass().isArray()) {
+        if (args && args.getClass().isArray()) {
             Object[] argsArray = (Object[]) args
-            if(argsArray[0] instanceof Closure) {
-                property(name, (Closure)argsArray[0])
+            if (argsArray[0] instanceof Closure) {
+                property(name, (Closure) argsArray[0])
             }
-            else if(argsArray[0] instanceof PropertyConfig) {
-                columns[name] = (PropertyConfig)argsArray[0]
+            else if (argsArray[0] instanceof PropertyConfig) {
+                columns[name] = (PropertyConfig) argsArray[0]
             }
-            else if(argsArray[0] instanceof Map) {
+            else if (argsArray[0] instanceof Map) {
                 PropertyConfig property = getOrInitializePropertyConfig(name)
                 Map namedArgs = (Map) argsArray[0]
-                if(argsArray[argsArray.length - 1] instanceof Closure) {
+                if (argsArray[argsArray.length - 1] instanceof Closure) {
                     PropertyConfig.configureExisting(
                             property,
-                            ((Closure)argsArray[argsArray.length - 1])
+                            ((Closure) argsArray[argsArray.length - 1])
                     )
                 }
                 PropertyConfig.configureExisting(property, namedArgs)
@@ -562,12 +561,12 @@ class Mapping extends Entity<PropertyConfig> {
     @Override
     protected PropertyConfig getOrInitializePropertyConfig(String name) {
         PropertyConfig pc = columns[name]
-        if(pc == null && columns.containsKey('*')) {
+        if (pc == null && columns.containsKey('*')) {
             // apply global constraints constraints
             PropertyConfig globalConstraints = columns.get('*')
-            if(globalConstraints != null) {
-                pc = (PropertyConfig)globalConstraints.clone()
-                if(pc.columns.size() == 1) {
+            if (globalConstraints != null) {
+                pc = (PropertyConfig) globalConstraints.clone()
+                if (pc.columns.size() == 1) {
                     pc.firstColumnIsColumnCopy = true
                 }
             }
@@ -594,6 +593,6 @@ class Mapping extends Entity<PropertyConfig> {
     }
 
     boolean hasCompositeIdentifier() {
-       return identity instanceof CompositeIdentity
-   }
+        return identity instanceof CompositeIdentity
+    }
 }
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/NaturalId.groovy b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/NaturalId.groovy
index dbc8ffdf04..9e73d9d1a2 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/NaturalId.groovy
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/NaturalId.groovy
@@ -18,7 +18,6 @@ package org.grails.orm.hibernate.cfg
 import groovy.transform.CompileStatic
 import groovy.transform.builder.Builder
 import groovy.transform.builder.SimpleStrategy
-import org.grails.orm.hibernate.cfg.domainbinding.util.UniqueNameGenerator
 import org.hibernate.mapping.PersistentClass
 import org.hibernate.mapping.UniqueKey
 
@@ -29,6 +28,7 @@ import org.hibernate.mapping.UniqueKey
 @CompileStatic
 @Builder(builderStrategy = SimpleStrategy, prefix = '')
 class NaturalId {
+
     /**
      * The property names that make up the natural id
      */
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/PropertyConfig.groovy b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/PropertyConfig.groovy
index fcd5adc14e..5803d5ed3c 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/PropertyConfig.groovy
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/PropertyConfig.groovy
@@ -45,7 +45,7 @@ class PropertyConfig extends Property {
     // Whether the first column is created from cloning this instance
     boolean firstColumnIsColumnCopy = false
 
-    boolean explicitSaveUpdateCascade;
+    boolean explicitSaveUpdateCascade
 
     /**
      * The Hibernate type or user type of the property. This can be
@@ -64,7 +64,6 @@ class PropertyConfig extends Property {
      */
     String sort
 
-
     /**
      * The default sort order
      */
@@ -75,7 +74,6 @@ class PropertyConfig extends Property {
      */
     Integer batchSize
 
-
     /**
      * Whether to ignore ObjectNotFoundException
      */
@@ -96,7 +94,7 @@ class PropertyConfig extends Property {
      *
      * @deprecated Use {@link #getUpdatable()} instead
      */
-    @Deprecated(since = "7.0", forRemoval = true)
+    @Deprecated(since = '7.0', forRemoval = true)
     boolean getUpdateable() {
         return updatable
     }
@@ -106,7 +104,7 @@ class PropertyConfig extends Property {
      *
      * @deprecated Use {@code updatable} instead
      */
-    @Deprecated(since = "7.0", forRemoval = true)
+    @Deprecated(since = '7.0', forRemoval = true)
     void setUpdateable(boolean updateable) {
         this.updatable = updateable
     }
@@ -122,12 +120,12 @@ class PropertyConfig extends Property {
      * @return This property config
      */
     PropertyConfig column(@DelegatesTo(ColumnConfig) Closure columnDef) {
-        if(columns.size() == 1 && firstColumnIsColumnCopy) {
+        if (columns.size() == 1 && firstColumnIsColumnCopy) {
             firstColumnIsColumnCopy = false
             ColumnConfig.configureExisting(columns[0], columnDef)
         }
         else {
-            columns.add( ColumnConfig.configureNew(columnDef) )
+            columns.add(ColumnConfig.configureNew(columnDef))
         }
         return this
     }
@@ -137,13 +135,13 @@ class PropertyConfig extends Property {
      * @param columnDef The column definition
      * @return This property config
      */
-    PropertyConfig column( Map columnDef ) {
-        if(columns.size() == 1 && firstColumnIsColumnCopy) {
+    PropertyConfig column(Map columnDef) {
+        if (columns.size() == 1 && firstColumnIsColumnCopy) {
             firstColumnIsColumnCopy = false
             ColumnConfig.configureExisting(columns[0], columnDef)
         }
         else {
-            columns.add( ColumnConfig.configureNew(columnDef) )
+            columns.add(ColumnConfig.configureNew(columnDef))
         }
         return this
     }
@@ -153,13 +151,13 @@ class PropertyConfig extends Property {
      * @param columnDef The column definition
      * @return This property config
      */
-    PropertyConfig column( String columnDef ) {
-        if(columns.size() == 1 && firstColumnIsColumnCopy) {
+    PropertyConfig column(String columnDef) {
+        if (columns.size() == 1 && firstColumnIsColumnCopy) {
             firstColumnIsColumnCopy = false
             columns[0].name = columnDef
         }
         else {
-            columns.add( ColumnConfig.configureNew(name: columnDef) )
+            columns.add(ColumnConfig.configureNew(name: columnDef))
         }
         return this
     }
@@ -174,7 +172,7 @@ class PropertyConfig extends Property {
      * @return This mapping
      */
     PropertyConfig cache(@DelegatesTo(CacheConfig) Closure cacheConfig) {
-        if(this.cache == null) {
+        if (this.cache == null) {
             this.cache = new CacheConfig()
         }
         CacheConfig.configureExisting(cache, cacheConfig)
@@ -187,7 +185,7 @@ class PropertyConfig extends Property {
      * @return This mapping
      */
     PropertyConfig cache(Map cacheConfig) {
-        if(this.cache == null) {
+        if (this.cache == null) {
             this.cache = new CacheConfig()
         }
         CacheConfig.configureExisting(cache, cacheConfig)
@@ -222,7 +220,7 @@ class PropertyConfig extends Property {
     @Override
     void setUnique(boolean unique) {
         super.setUnique(unique)
-        if(columns.size() == 1) {
+        if (columns.size() == 1) {
             columns[0].unique = unique
         }
     }
@@ -232,10 +230,10 @@ class PropertyConfig extends Property {
     PropertyConfig joinTable(Map joinTableDef) {
         DataBinder dataBinder = new DataBinder(joinTable)
         dataBinder.bind(new MutablePropertyValues(joinTableDef))
-        if(joinTableDef.key) {
+        if (joinTableDef.key) {
             joinTable.key(joinTableDef.key.toString())
         }
-        if(joinTableDef.column) {
+        if (joinTableDef.column) {
             joinTable.column(joinTableDef.column.toString())
         }
         return this
@@ -245,7 +243,7 @@ class PropertyConfig extends Property {
      * @param fetch The Hibernate {@link FetchMode}
      */
     void setFetch(FetchMode fetch) {
-        if(FetchMode.JOIN.equals(fetch)) {
+        if (FetchMode.JOIN.equals(fetch)) {
             super.setFetchStrategy(FetchType.EAGER)
         }
         else {
@@ -258,7 +256,7 @@ class PropertyConfig extends Property {
      */
     FetchMode getFetchMode() {
         FetchType strategy = super.getFetchStrategy()
-        if(strategy == null) {
+        if (strategy == null) {
             return FetchMode.DEFAULT
         }
         switch (strategy) {
@@ -294,7 +292,6 @@ class PropertyConfig extends Property {
         return configureExisting(property, config)
     }
 
-
     /**
      * Configures a new PropertyConfig instance
      *
@@ -322,9 +319,9 @@ class PropertyConfig extends Property {
         }
         else {
             cc = new ColumnConfig()
-            property.columns.add cc
+            property.columns.add(cc)
         }
-        if(config.column) {
+        if (config.column) {
             config.name = config.column
         }
         ColumnConfig.configureExisting(cc, config)
@@ -351,13 +348,13 @@ class PropertyConfig extends Property {
      */
     String getColumn() {
         checkHasSingleColumn()
-        if(columns.isEmpty()) return null
+        if (columns.isEmpty()) return null
         return columns[0].name
     }
 
     String getEnumType() {
         checkHasSingleColumn()
-        if(columns.isEmpty()) return "default"
+        if (columns.isEmpty()) return 'default'
         return columns[0].enumType
     }
 
@@ -368,7 +365,7 @@ class PropertyConfig extends Property {
      */
     String getSqlType() {
         checkHasSingleColumn()
-        if(columns.isEmpty()) return null
+        if (columns.isEmpty()) return null
         return columns[0].sqlType
     }
 
@@ -379,7 +376,7 @@ class PropertyConfig extends Property {
      */
     String getIndexName() {
         checkHasSingleColumn()
-        if(columns.isEmpty()) return null
+        if (columns.isEmpty()) return null
         return columns[0].index?.toString()
     }
 
@@ -390,11 +387,11 @@ class PropertyConfig extends Property {
      * column.
      */
     boolean isUnique() {
-        if(columns.size()>1) {
+        if (columns.size() > 1) {
             return super.isUnique()
         }
         else {
-            if(columns.isEmpty()) return super.isUnique()
+            if (columns.isEmpty()) return super.isUnique()
             return columns[0].unique
         }
     }
@@ -406,7 +403,7 @@ class PropertyConfig extends Property {
      */
     int getLength() {
         checkHasSingleColumn()
-        if(columns.isEmpty()) return -1
+        if (columns.isEmpty()) return -1
         return columns[0].length
     }
 
@@ -417,7 +414,7 @@ class PropertyConfig extends Property {
      */
     int getPrecision() {
         checkHasSingleColumn()
-        if(columns.isEmpty()) return -1
+        if (columns.isEmpty()) return -1
         return columns[0].precision
     }
 
@@ -428,7 +425,7 @@ class PropertyConfig extends Property {
      */
     int getScale() {
         checkHasSingleColumn()
-        if(columns.isEmpty()) {
+        if (columns.isEmpty()) {
             return super.getScale()
         }
         return columns[0].scale
@@ -437,15 +434,14 @@ class PropertyConfig extends Property {
     /**
      * @return The type name
      */
-     String getTypeName() {
-        return type?.with { it instanceof Class ? it.name : it.toString() };
+    String getTypeName() {
+        return type?.with { it instanceof Class ? it.name : it.toString() }
     }
 
-
     @Override
     void setScale(int scale) {
         checkHasSingleColumn()
-        if(!columns.isEmpty())  {
+        if (!columns.isEmpty())  {
             columns[0].scale = scale
         }
         else {
@@ -459,32 +455,32 @@ class PropertyConfig extends Property {
 
     protected void checkHasSingleColumn() {
         if (columns?.size() > 1) {
-            throw new RuntimeException("Cannot treat multi-column property as a single-column property")
+            throw new RuntimeException('Cannot treat multi-column property as a single-column property')
         }
     }
 
     @Override
     PropertyConfig clone() throws CloneNotSupportedException {
-        PropertyConfig pc = (PropertyConfig)super.clone()
+        PropertyConfig pc = (PropertyConfig) super.clone()
 
         pc.fetch = fetchMode
-        pc.indexColumn = indexColumn != null ? (PropertyConfig)indexColumn.clone() : null
+        pc.indexColumn = indexColumn != null ? (PropertyConfig) indexColumn.clone() : null
         pc.cache = cache != null ? cache.clone() : cache
         pc.joinTable = joinTable.clone()
-        if(typeParams != null) {
+        if (typeParams != null) {
             pc.typeParams = new Properties(typeParams)
         }
 
         List newColumns = new ArrayList<ColumnConfig>(columns.size())
         pc.columns = newColumns
-        for(c in columns) {
+        for (c in columns) {
             newColumns.add(c.clone())
         }
         return pc
     }
 
-    public boolean hasJoinKeyMapping() {
-        return  Optional.ofNullable(getJoinTable()).map(JoinTable::getKey).isPresent();
+    boolean hasJoinKeyMapping() {
+        joinTable?.key != null
     }
 
 }
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/PropertyDefinitionDelegate.groovy b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/PropertyDefinitionDelegate.groovy
index e28c19fb18..c08abc656b 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/PropertyDefinitionDelegate.groovy
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/PropertyDefinitionDelegate.groovy
@@ -16,6 +16,7 @@ import org.grails.datastore.mapping.model.DatastoreConfigurationException
  */
 @CompileStatic
 class PropertyDefinitionDelegate {
+
     PropertyConfig config
 
     private int index = 0
@@ -26,13 +27,13 @@ class PropertyDefinitionDelegate {
 
     ColumnConfig column(Map args) {
         // Check that this column has a name
-        if (!args["name"]) {
-            throw new DatastoreConfigurationException("Column definition must have a name!")
+        if (!args['name']) {
+            throw new DatastoreConfigurationException('Column definition must have a name!')
         }
 
         // Create a new column configuration based on the mapping for this column.
         ColumnConfig column
-        if(index < config.columns.size()) {
+        if (index < config.columns.size()) {
             // configure existing
             column = config.columns[0]
         }
@@ -41,14 +42,14 @@ class PropertyDefinitionDelegate {
             // Append the new column configuration to the property config.
             config.columns << column
         }
-        column.name = args["name"]
-        column.sqlType = args["sqlType"]
-        column.enumType = args["enumType"] ?: column.enumType
-        column.index = args["index"]
-        column.unique = args["unique"] ?: false
-        column.length = args["length"] ? args["length"] as Integer : -1
-        column.precision = args["precision"] ? args["precision"] as Integer  : -1
-        column.scale = args["scale"] ? args["scale"] as Integer : -1
+        column.name = args['name']
+        column.sqlType = args['sqlType']
+        column.enumType = args['enumType'] ?: column.enumType
+        column.index = args['index']
+        column.unique = args['unique'] ?: false
+        column.length = args['length'] ? args['length'] as Integer : -1
+        column.precision = args['precision'] ? args['precision'] as Integer  : -1
+        column.scale = args['scale'] ? args['scale'] as Integer : -1
 
         index++
         return column
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/SortConfig.groovy b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/SortConfig.groovy
index 683b57dc7e..145bf297cb 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/SortConfig.groovy
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/SortConfig.groovy
@@ -25,6 +25,7 @@ import groovy.transform.builder.SimpleStrategy
 @CompileStatic
 @Builder(builderStrategy = SimpleStrategy, prefix = '')
 class SortConfig {
+
     /**
      * The property to sort bu
      */
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/Table.groovy b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/Table.groovy
index 2afc1a7753..f1cd8ed0d2 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/Table.groovy
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/Table.groovy
@@ -30,6 +30,7 @@ import org.springframework.validation.DataBinder
 @Builder(builderStrategy = SimpleStrategy, prefix = '')
 @CompileStatic
 class Table {
+
     /**
      * The table name
      */


(grails-core) 34/34: hibernate7: added lock and fetchMode support to CriteriaMethodInvoker

Posted by bo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

borinquenkid pushed a commit to branch 8.0.x-hibernate7-dev
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit 91b95a39da5b6f01a2d233f6c46c87d6f4bf831d
Author: Walter Duque de Estrada <wb...@mac.com>
AuthorDate: Sun Mar 8 20:00:48 2026 -0500

    hibernate7:
    added lock and fetchMode support to CriteriaMethodInvoker
---
 .../groovy/grails/orm/CriteriaMethodInvoker.java   | 562 +++++++++++----------
 .../main/groovy/grails/orm/CriteriaMethods.java    |   4 +-
 .../grails/orm/HibernateCriteriaBuilder.java       |  45 +-
 .../grails/orm/CriteriaMethodInvokerSpec.groovy    |  31 +-
 .../orm/HibernateCriteriaBuilderDirectSpec.groovy  |  50 ++
 .../grails/orm/HibernateCriteriaBuilderSpec.groovy |  30 ++
 .../src/en/ref/Domain Classes/createCriteria.adoc  |   6 +-
 7 files changed, 432 insertions(+), 296 deletions(-)

diff --git a/grails-data-hibernate7/core/src/main/groovy/grails/orm/CriteriaMethodInvoker.java b/grails-data-hibernate7/core/src/main/groovy/grails/orm/CriteriaMethodInvoker.java
index 5b28247255..64ef644a23 100644
--- a/grails-data-hibernate7/core/src/main/groovy/grails/orm/CriteriaMethodInvoker.java
+++ b/grails-data-hibernate7/core/src/main/groovy/grails/orm/CriteriaMethodInvoker.java
@@ -20,331 +20,343 @@ package grails.orm;
 
 import grails.gorm.DetachedCriteria;
 import grails.gorm.PagedResultList;
+
 import groovy.lang.Closure;
 import groovy.lang.MetaMethod;
+
 import jakarta.persistence.criteria.JoinType;
 import jakarta.persistence.metamodel.Attribute;
 import jakarta.persistence.metamodel.EntityType;
 import jakarta.persistence.metamodel.Metamodel;
+
 import java.beans.PropertyDescriptor;
 import java.util.Collection;
 import java.util.Map;
+
 import org.grails.datastore.mapping.query.Query;
 import org.grails.orm.hibernate.query.HibernateQuery;
 import org.grails.orm.hibernate.query.HibernateQueryArgument;
+
 import org.springframework.beans.BeanUtils;
 
 public class CriteriaMethodInvoker {
 
-  private static final Object UNHANDLED = new Object();
+    private static final Object UNHANDLED = new Object();
 
-  private final HibernateCriteriaBuilder builder;
+    private final HibernateCriteriaBuilder builder;
 
-  public CriteriaMethodInvoker(HibernateCriteriaBuilder builder) {
-    this.builder = builder;
-  }
-
-  public Object invokeMethod(String name, Object... args) {
-    CriteriaMethods method = CriteriaMethods.fromName(name);
+    public CriteriaMethodInvoker(HibernateCriteriaBuilder builder) {
+        this.builder = builder;
+    }
 
-    Object result = tryCriteriaConstruction(method, args);
-    if (result != UNHANDLED) return result;
+    public Object invokeMethod(String name, Object... args) {
+        CriteriaMethods method = CriteriaMethods.fromName(name);
 
-    result = tryMetaMethod(name, args);
-    if (result != UNHANDLED) return result;
+        Object result = tryCriteriaConstruction(method, args);
+        if (result != UNHANDLED) return result;
 
-    result = tryAssociationOrJunction(name, method, args);
-    if (result != UNHANDLED) return result;
+        result = tryMetaMethod(name, args);
+        if (result != UNHANDLED) return result;
 
-    result = trySimpleCriteria(name, method, args);
-    if (result != UNHANDLED) return result;
+        result = tryAssociationOrJunction(name, method, args);
+        if (result != UNHANDLED) return result;
 
-    result = tryPropertyCriteria(method, args);
-    if (result != UNHANDLED) return result;
+        result = trySimpleCriteria(name, method, args);
+        if (result != UNHANDLED) return result;
 
-    return CriteriaMethods.fromName(name, HibernateCriteriaBuilder.class, args);
-  }
+        result = tryPropertyCriteria(method, args);
+        if (result != UNHANDLED) return result;
 
-  private Object tryCriteriaConstruction(CriteriaMethods method, Object... args) {
-    if (method == null || !isCriteriaConstructionMethod(method, args)) {
-      return UNHANDLED;
+        return CriteriaMethods.fromName(name, HibernateCriteriaBuilder.class, args);
     }
 
-    HibernateQuery hibernateQuery = builder.getHibernateQuery();
-    switch (method) {
-      case GET_CALL -> builder.setUniqueResult(true);
-      case SCROLL_CALL -> builder.setScroll(true);
-      case COUNT_CALL -> builder.setCount(true);
-      case LIST_DISTINCT_CALL -> builder.setDistinct(true);
-      default -> {}
-    }
+    private Object tryCriteriaConstruction(CriteriaMethods method, Object... args) {
+        if (method == null || !isCriteriaConstructionMethod(method, args)) {
+            return UNHANDLED;
+        }
 
-    // Check for pagination params
-    if (method == CriteriaMethods.LIST_CALL && args.length == 2) {
-      builder.setPaginationEnabledList(true);
-      if (args[0] instanceof Map<?, ?> map) {
-        if (map.get("max") instanceof Number max) {
-          hibernateQuery.maxResults(max.intValue());
+        HibernateQuery hibernateQuery = builder.getHibernateQuery();
+        switch (method) {
+            case GET_CALL -> builder.setUniqueResult(true);
+            case SCROLL_CALL -> builder.setScroll(true);
+            case COUNT_CALL -> builder.setCount(true);
+            case LIST_DISTINCT_CALL -> builder.setDistinct(true);
+            default -> {
+            }
         }
-        if (map.get("offset") instanceof Number offset) {
-          hibernateQuery.firstResult(offset.intValue());
+
+        // Check for pagination params
+        if (method == CriteriaMethods.LIST_CALL && args.length == 2) {
+            builder.setPaginationEnabledList(true);
+            if (args[0] instanceof Map<?, ?> map) {
+                if (map.get("max") instanceof Number max) {
+                    hibernateQuery.maxResults(max.intValue());
+                }
+                if (map.get("offset") instanceof Number offset) {
+                    hibernateQuery.firstResult(offset.intValue());
+                }
+            }
+            invokeClosureNode(args[1]);
+        } else {
+            invokeClosureNode(args[0]);
         }
-      }
-      invokeClosureNode(args[1]);
-    } else {
-      invokeClosureNode(args[0]);
-    }
 
-    Object result;
-    if (!builder.isUniqueResult()) {
-      if (builder.isDistinct()) {
-        hibernateQuery.distinct();
-        result = hibernateQuery.list();
-      } else if (builder.isCount()) {
-        hibernateQuery.projections().count();
-        result = hibernateQuery.singleResult();
-      } else if (builder.isPaginationEnabledList()) {
-        Map<?, ?> argMap = (Map<?, ?>) args[0];
-        final String sortField = (String) argMap.get(HibernateQueryArgument.SORT.value());
-        if (sortField != null) {
-          final boolean ignoreCase =
-              !(argMap.get(HibernateQueryArgument.IGNORE_CASE.value()) instanceof Boolean b) || b;
-          final String orderParam = (String) argMap.get(HibernateQueryArgument.ORDER.value());
-          final Query.Order.Direction direction =
-              Query.Order.Direction.DESC.name().equalsIgnoreCase(orderParam)
-                  ? Query.Order.Direction.DESC
-                  : Query.Order.Direction.ASC;
-          Query.Order order;
-            order = new Query.Order(sortField, direction);
-            if (ignoreCase) {
-                order.ignoreCase();
-          }
-            hibernateQuery.order(order);
+        Object result;
+        if (!builder.isUniqueResult()) {
+            if (builder.isDistinct()) {
+                hibernateQuery.distinct();
+                result = hibernateQuery.list();
+            } else if (builder.isCount()) {
+                hibernateQuery.projections().count();
+                result = hibernateQuery.singleResult();
+            } else if (builder.isPaginationEnabledList()) {
+                Map<?, ?> argMap = (Map<?, ?>) args[0];
+                final String sortField = (String) argMap.get(HibernateQueryArgument.SORT.value());
+                if (sortField != null) {
+                    final boolean ignoreCase =
+                            !(argMap.get(HibernateQueryArgument.IGNORE_CASE.value()) instanceof Boolean b) || b;
+                    final String orderParam = (String) argMap.get(HibernateQueryArgument.ORDER.value());
+                    final Query.Order.Direction direction =
+                            Query.Order.Direction.DESC.name().equalsIgnoreCase(orderParam)
+                                    ? Query.Order.Direction.DESC
+                                    : Query.Order.Direction.ASC;
+                    Query.Order order;
+                    order = new Query.Order(sortField, direction);
+                    if (ignoreCase) {
+                        order.ignoreCase();
+                    }
+                    hibernateQuery.order(order);
+                }
+                result = new PagedResultList<>(hibernateQuery);
+            } else if (builder.isScroll()) {
+                result = hibernateQuery.scroll();
+            } else {
+                result = hibernateQuery.list();
+            }
+        } else {
+            result = hibernateQuery.singleResult();
         }
-        result = new PagedResultList<>(hibernateQuery);
-      } else if (builder.isScroll()) {
-        result = hibernateQuery.scroll();
-      } else {
-        result = hibernateQuery.list();
-      }
-    } else {
-      result = hibernateQuery.singleResult();
-    }
-    if (!builder.isParticipate()) {
-      builder.closeSession();
+        if (!builder.isParticipate()) {
+            builder.closeSession();
+        }
+        return result;
     }
-    return result;
-  }
 
-  private Object tryMetaMethod(String name, Object... args) {
-    MetaMethod metaMethod = builder.getMetaClass().getMetaMethod(name, args);
-    if (metaMethod != null) {
-      return metaMethod.invoke(builder, args);
+    private Object tryMetaMethod(String name, Object... args) {
+        MetaMethod metaMethod = builder.getMetaClass().getMetaMethod(name, args);
+        if (metaMethod != null) {
+            return metaMethod.invoke(builder, args);
+        }
+        return UNHANDLED;
     }
-    return UNHANDLED;
-  }
 
-  @SuppressWarnings("PMD.DataflowAnomalyAnalysis")
-  private Object tryAssociationOrJunction(String name, CriteriaMethods method, Object... args) {
-    if (!isAssociationQueryMethod(args) && !isAssociationQueryWithJoinSpecificationMethod(args)) {
-      return UNHANDLED;
+    @SuppressWarnings("PMD.DataflowAnomalyAnalysis")
+    private Object tryAssociationOrJunction(String name, CriteriaMethods method, Object... args) {
+        if (!isAssociationQueryMethod(args) && !isAssociationQueryWithJoinSpecificationMethod(args)) {
+            return UNHANDLED;
+        }
+
+        final boolean hasMoreThanOneArg = args.length > 1;
+        final Closure<?> callable = hasMoreThanOneArg ? (Closure<?>) args[1] : (Closure<?>) args[0];
+        final HibernateQuery hibernateQuery = builder.getHibernateQuery();
+
+        if (method != null) {
+            switch (method) {
+                case AND:
+                    hibernateQuery.and(callable);
+                    return name;
+                case OR:
+                    hibernateQuery.or(callable);
+                    return name;
+                case NOT:
+                    hibernateQuery.not(callable);
+                    return name;
+                case PROJECTIONS:
+                    if (args.length == 1 && (args[0] instanceof Closure)) {
+                        invokeClosureNode(callable);
+                        return name;
+                    }
+                    break;
+                default:
+                    break;
+            }
+        }
+
+        final PropertyDescriptor pd = BeanUtils.getPropertyDescriptor(builder.getTargetClass(), name);
+        if (pd != null && pd.getReadMethod() != null) {
+            final Metamodel metamodel = builder.getSessionFactory().getMetamodel();
+            final EntityType<?> entityType = metamodel.entity(builder.getTargetClass());
+            final Attribute<?, ?> attribute = entityType.getAttribute(name);
+
+            if (attribute.isAssociation()) {
+                Class<?> oldTargetClass = builder.getTargetClass();
+                builder.setTargetClass(builder.getClassForAssociationType(attribute));
+                JoinType joinType;
+                if (hasMoreThanOneArg) {
+                    joinType = builder.convertFromInt((Integer) args[0]);
+                } else if (builder.getTargetClass().equals(oldTargetClass)) {
+                    joinType = JoinType.LEFT; // default to left join if joining on the same table
+                } else {
+                    joinType = builder.convertFromInt(0);
+                }
+
+                hibernateQuery.join(name, joinType);
+                hibernateQuery.in(name, new DetachedCriteria<>(builder.getTargetClass()).build(callable));
+                builder.setTargetClass(oldTargetClass);
+
+                return name;
+            }
+        }
+        return UNHANDLED;
     }
 
-    final boolean hasMoreThanOneArg = args.length > 1;
-    final Closure<?> callable = hasMoreThanOneArg ? (Closure<?>) args[1] : (Closure<?>) args[0];
-    final HibernateQuery hibernateQuery = builder.getHibernateQuery();
-
-    if (method != null) {
-      switch (method) {
-        case AND:
-          hibernateQuery.and(callable);
-          return name;
-        case OR:
-          hibernateQuery.or(callable);
-          return name;
-        case NOT:
-          hibernateQuery.not(callable);
-          return name;
-        case PROJECTIONS:
-          if (args.length == 1 && (args[0] instanceof Closure)) {
-            invokeClosureNode(callable);
-            return name;
-          }
-          break;
-        default:
-          break;
-      }
+    @SuppressWarnings("PMD.DataflowAnomalyAnalysis")
+    protected Object trySimpleCriteria(String name, CriteriaMethods method, Object... args) {
+        if (args.length != 1 || args[0] == null) {
+            return UNHANDLED;
+        }
+
+        if (method != null) {
+            switch (method) {
+                case ID_EQUALS:
+                    return builder.eq("id", args[0]);
+                case CACHE:
+                    if (args[0] instanceof Boolean b) {
+                        builder.cache(b);
+                    }
+                    return name;
+                case READ_ONLY:
+                    if (args[0] instanceof Boolean b) {
+                        builder.readOnly(b);
+                    }
+                    return name;
+                case SINGLE_RESULT:
+                    return builder.singleResult();
+                case IS_NULL, IS_NOT_NULL, IS_EMPTY, IS_NOT_EMPTY:
+                    if (!(args[0] instanceof String)) {
+                        builder.throwRuntimeException(
+                                new IllegalArgumentException(
+                                        "call to ["
+                                                + name
+                                                + "] with value ["
+                                                + args[0]
+                                                + "] requires a String value."));
+                    }
+                    final String value = (String) args[0];
+                    switch (method) {
+                        case IS_NULL -> builder.getHibernateQuery().isNull(value);
+                        case IS_NOT_NULL -> builder.getHibernateQuery().isNotNull(value);
+                        case IS_EMPTY -> builder.getHibernateQuery().isEmpty(value);
+                        case IS_NOT_EMPTY -> builder.getHibernateQuery().isNotEmpty(value);
+                        default -> {
+                        }
+                    }
+                    return name;
+                default:
+                    break;
+            }
+        }
+        return UNHANDLED;
     }
 
-    final PropertyDescriptor pd = BeanUtils.getPropertyDescriptor(builder.getTargetClass(), name);
-    if (pd != null && pd.getReadMethod() != null) {
-      final Metamodel metamodel = builder.getSessionFactory().getMetamodel();
-      final EntityType<?> entityType = metamodel.entity(builder.getTargetClass());
-      final Attribute<?, ?> attribute = entityType.getAttribute(name);
-
-      if (attribute.isAssociation()) {
-        Class<?> oldTargetClass = builder.getTargetClass();
-        builder.setTargetClass(builder.getClassForAssociationType(attribute));
-        JoinType joinType;
-        if (hasMoreThanOneArg) {
-          joinType = builder.convertFromInt((Integer) args[0]);
-        } else if (builder.getTargetClass().equals(oldTargetClass)) {
-          joinType = JoinType.LEFT; // default to left join if joining on the same table
-        } else {
-          joinType = builder.convertFromInt(0);
+    @SuppressWarnings("PMD.AvoidLiteralsInIfCondition")
+    protected Object tryPropertyCriteria(CriteriaMethods method, Object... args) {
+        if (method == CriteriaMethods.FETCH_MODE) {
+            if (args.length == 2 && args[0] instanceof String s && args[1] instanceof org.hibernate.FetchMode fm) {
+                builder.fetchMode(s, fm);
+                return "fetchMode";
+            }
         }
 
-        hibernateQuery.join(name, joinType);
-        hibernateQuery.in(name, new DetachedCriteria<>(builder.getTargetClass()).build(callable));
-        builder.setTargetClass(oldTargetClass);
+        if (method == null || args.length < 2 || !(args[0] instanceof String propertyName)) {
+            return UNHANDLED;
+        }
 
-        return name;
-      }
+        switch (method) {
+            case RLIKE:
+                return builder.rlike(propertyName, args[1]);
+            case BETWEEN:
+                if (args.length >= 3) {
+                    return builder.between(propertyName, args[1], args[2]);
+                }
+                break;
+            case EQUALS:
+                if (args.length == 3 && args[2] instanceof Map<?, ?> map) {
+                    return builder.eq(propertyName, args[1], map);
+                }
+                return builder.eq(propertyName, args[1]);
+            case EQUALS_PROPERTY:
+                return builder.eqProperty(propertyName, args[1].toString());
+            case GREATER_THAN:
+                return builder.gt(propertyName, args[1]);
+            case GREATER_THAN_PROPERTY:
+                return builder.gtProperty(propertyName, args[1].toString());
+            case GREATER_THAN_OR_EQUAL:
+                return builder.ge(propertyName, args[1]);
+            case GREATER_THAN_OR_EQUAL_PROPERTY:
+                return builder.geProperty(propertyName, args[1].toString());
+            case ILIKE:
+                return builder.ilike(propertyName, args[1]);
+            case IN:
+                if (args[1] instanceof Collection) {
+                    return builder.in(propertyName, (Collection<?>) args[1]);
+                } else if (args[1] instanceof Object[]) {
+                    return builder.in(propertyName, (Object[]) args[1]);
+                }
+                break;
+            case LESS_THAN:
+                return builder.lt(propertyName, args[1]);
+            case LESS_THAN_PROPERTY:
+                return builder.ltProperty(propertyName, args[1].toString());
+            case LESS_THAN_OR_EQUAL:
+                return builder.le(propertyName, args[1]);
+            case LESS_THAN_OR_EQUAL_PROPERTY:
+                return builder.leProperty(propertyName, args[1].toString());
+            case LIKE:
+                return builder.like(propertyName, args[1]);
+            case NOT_EQUAL:
+                return builder.ne(propertyName, args[1]);
+            case NOT_EQUAL_PROPERTY:
+                return builder.neProperty(propertyName, args[1].toString());
+            case SIZE_EQUALS:
+                if (args[1] instanceof Number) {
+                    return builder.sizeEq(propertyName, ((Number) args[1]).intValue());
+                }
+                break;
+            default:
+                break;
+        }
+        return UNHANDLED;
     }
-    return UNHANDLED;
-  }
 
-  @SuppressWarnings("PMD.DataflowAnomalyAnalysis")
-  protected Object trySimpleCriteria(String name, CriteriaMethods method, Object... args) {
-    if (args.length != 1 || args[0] == null) {
-      return UNHANDLED;
+    private boolean isAssociationQueryMethod(Object... args) {
+        return args.length == 1 && args[0] instanceof Closure;
     }
 
-    if (method != null) {
-      switch (method) {
-        case ID_EQUALS:
-          return builder.eq("id", args[0]);
-        case CACHE:
-          if (args[0] instanceof Boolean b) {
-            builder.cache(b);
-          }
-          return name;
-        case READ_ONLY:
-          if (args[0] instanceof Boolean b) {
-            builder.readOnly(b);
-          }
-          return name;
-        case IS_NULL, IS_NOT_NULL, IS_EMPTY, IS_NOT_EMPTY:
-          if (!(args[0] instanceof String)) {
-            builder.throwRuntimeException(
-                new IllegalArgumentException(
-                    "call to ["
-                        + name
-                        + "] with value ["
-                        + args[0]
-                        + "] requires a String value."));
-          }
-          final String value = (String) args[0];
-          switch (method) {
-            case IS_NULL ->
-                builder.getHibernateQuery().isNull(value);
-            case IS_NOT_NULL ->
-                builder.getHibernateQuery().isNotNull(value);
-            case IS_EMPTY ->
-                builder.getHibernateQuery().isEmpty(value);
-            case IS_NOT_EMPTY ->
-                builder.getHibernateQuery().isNotEmpty(value);
-            default -> {}
-          }
-          return name;
-        default:
-          break;
-      }
+    private boolean isAssociationQueryWithJoinSpecificationMethod(Object... args) {
+        return args.length == 2 && (args[0] instanceof Number) && (args[1] instanceof Closure);
     }
-    return UNHANDLED;
-  }
 
-  @SuppressWarnings("PMD.AvoidLiteralsInIfCondition")
-  protected Object tryPropertyCriteria(CriteriaMethods method, Object... args) {
-    if (method == null || args.length < 2 || !(args[0] instanceof String propertyName)) {
-      return UNHANDLED;
+    private boolean isCriteriaConstructionMethod(CriteriaMethods method, Object... args) {
+        return (method == CriteriaMethods.LIST_CALL
+                && args.length == 2
+                && args[0] instanceof Map<?, ?>
+                && args[1] instanceof Closure)
+                || (method == CriteriaMethods.ROOT_CALL
+                || method == CriteriaMethods.ROOT_DO_CALL
+                || method == CriteriaMethods.LIST_CALL
+                || method == CriteriaMethods.LIST_DISTINCT_CALL
+                || method == CriteriaMethods.GET_CALL
+                || method == CriteriaMethods.COUNT_CALL
+                || (method == CriteriaMethods.SCROLL_CALL
+                && args.length == 1
+                && args[0] instanceof Closure));
     }
 
-    switch (method) {
-      case RLIKE:
-        return builder.rlike(propertyName, args[1]);
-      case BETWEEN:
-        if (args.length >= 3) {
-          return builder.between(propertyName, args[1], args[2]);
-        }
-        break;
-      case EQUALS:
-        if (args.length == 3 && args[2] instanceof Map<?, ?> map) {
-          return builder.eq(propertyName, args[1], map);
-        }
-        return builder.eq(propertyName, args[1]);
-      case EQUALS_PROPERTY:
-        return builder.eqProperty(propertyName, args[1].toString());
-      case GREATER_THAN:
-        return builder.gt(propertyName, args[1]);
-      case GREATER_THAN_PROPERTY:
-        return builder.gtProperty(propertyName, args[1].toString());
-      case GREATER_THAN_OR_EQUAL:
-        return builder.ge(propertyName, args[1]);
-      case GREATER_THAN_OR_EQUAL_PROPERTY:
-        return builder.geProperty(propertyName, args[1].toString());
-      case ILIKE:
-        return builder.ilike(propertyName, args[1]);
-      case IN:
-        if (args[1] instanceof Collection) {
-          return builder.in(propertyName, (Collection<?>) args[1]);
-        } else if (args[1] instanceof Object[]) {
-          return builder.in(propertyName, (Object[]) args[1]);
-        }
-        break;
-      case LESS_THAN:
-        return builder.lt(propertyName, args[1]);
-      case LESS_THAN_PROPERTY:
-        return builder.ltProperty(propertyName, args[1].toString());
-      case LESS_THAN_OR_EQUAL:
-        return builder.le(propertyName, args[1]);
-      case LESS_THAN_OR_EQUAL_PROPERTY:
-        return builder.leProperty(propertyName, args[1].toString());
-      case LIKE:
-        return builder.like(propertyName, args[1]);
-      case NOT_EQUAL:
-        return builder.ne(propertyName, args[1]);
-      case NOT_EQUAL_PROPERTY:
-        return builder.neProperty(propertyName, args[1].toString());
-      case SIZE_EQUALS:
-        if (args[1] instanceof Number) {
-          return builder.sizeEq(propertyName, ((Number) args[1]).intValue());
-        }
-        break;
-      default:
-        break;
+    private void invokeClosureNode(Object args) {
+        Closure<?> callable = (Closure<?>) args;
+        callable.setDelegate(builder);
+        callable.setResolveStrategy(Closure.DELEGATE_FIRST);
+        callable.call();
     }
-    return UNHANDLED;
-  }
-
-  private boolean isAssociationQueryMethod(Object... args) {
-    return args.length == 1 && args[0] instanceof Closure;
-  }
-
-  private boolean isAssociationQueryWithJoinSpecificationMethod(Object... args) {
-    return args.length == 2 && (args[0] instanceof Number) && (args[1] instanceof Closure);
-  }
-
-  private boolean isCriteriaConstructionMethod(CriteriaMethods method, Object... args) {
-    return (method == CriteriaMethods.LIST_CALL
-            && args.length == 2
-            && args[0] instanceof Map<?, ?>
-            && args[1] instanceof Closure)
-        || (method == CriteriaMethods.ROOT_CALL
-            || method == CriteriaMethods.ROOT_DO_CALL
-            || method == CriteriaMethods.LIST_CALL
-            || method == CriteriaMethods.LIST_DISTINCT_CALL
-            || method == CriteriaMethods.GET_CALL
-            || method == CriteriaMethods.COUNT_CALL
-            || (method == CriteriaMethods.SCROLL_CALL
-                && args.length == 1
-                && args[0] instanceof Closure));
-  }
-
-  private void invokeClosureNode(Object args) {
-    Closure<?> callable = (Closure<?>) args;
-    callable.setDelegate(builder);
-    callable.setResolveStrategy(Closure.DELEGATE_FIRST);
-    callable.call();
-  }
 }
diff --git a/grails-data-hibernate7/core/src/main/groovy/grails/orm/CriteriaMethods.java b/grails-data-hibernate7/core/src/main/groovy/grails/orm/CriteriaMethods.java
index 46d0f4b35f..ab98bae51e 100644
--- a/grails-data-hibernate7/core/src/main/groovy/grails/orm/CriteriaMethods.java
+++ b/grails-data-hibernate7/core/src/main/groovy/grails/orm/CriteriaMethods.java
@@ -59,7 +59,9 @@ public enum CriteriaMethods {
   SCROLL_CALL("scroll"),
   PROJECTIONS("projections"),
   CACHE("cache"),
-  READ_ONLY("readOnly");
+  READ_ONLY("readOnly"),
+  FETCH_MODE("fetchMode"),
+  SINGLE_RESULT("singleResult");
 
   private final String name;
 
diff --git a/grails-data-hibernate7/core/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java b/grails-data-hibernate7/core/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java
index 62221c4df1..3cc4a2d0f7 100644
--- a/grails-data-hibernate7/core/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java
+++ b/grails-data-hibernate7/core/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java
@@ -44,6 +44,8 @@ import org.grails.orm.hibernate.GrailsHibernateTemplate;
 import org.grails.orm.hibernate.query.HibernateQuery;
 import org.hibernate.FetchMode;
 import org.hibernate.SessionFactory;
+import org.springframework.orm.hibernate5.SessionHolder;
+import org.springframework.transaction.support.TransactionSynchronizationManager;
 
 /**
  * Implements the GORM criteria DSL for Hibernate 7+. The builder exposes a Groovy-closure DSL that
@@ -66,9 +68,24 @@ import org.hibernate.SessionFactory;
  *             }
  *             maxResults(10)
  *             order("holderLastName", "desc")
+ *             cache(true)
+ *             readOnly(true)
  *         }
  * </pre>
  *
+ * <h2>Advanced Features</h2>
+ *
+ * <p>The builder supports several advanced Hibernate features:
+ *
+ * <ul>
+ *   <li><b>Pessimistic Locking:</b> Use {@code lock(true)} to obtain a pessimistic write lock.
+ *   <li><b>Query Caching:</b> Use {@code cache(true)} to enable query caching for the results.
+ *   <li><b>Read-Only Mode:</b> Use {@code readOnly(true)} to disable dirty checking for loaded
+ *       entities.
+ *   <li><b>Fetch Mode:</b> Use {@code fetchMode("association", FetchMode.JOIN)} to specify Eager/Lazy
+ *       fetching strategies.
+ * </ul>
+ *
  * <h2>Programmatic instantiation</h2>
  *
  * <p>The builder requires a {@link SessionFactory}, the target persistent class, and the {@link
@@ -104,8 +121,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
   private Class<?> targetClass;
   private CriteriaQuery<?> criteriaQuery;
   private boolean uniqueResult = false;
-  //TODO Transactional behaviour is currently not supported, but we need to track whether the criteria should participate in a transaction or not
-  private boolean participate;
+  private final boolean participate;
 
   @SuppressWarnings("PMD.AvoidFieldNameMatchingMethodName")
   private boolean scroll;
@@ -117,11 +133,6 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
   private int defaultFlushMode;
   private final org.hibernate.query.criteria.HibernateCriteriaBuilder cb;
   private final HibernateQuery hibernateQuery;
-  private boolean shouldLock;
-  private boolean shouldCache;
-
-  @SuppressWarnings("PMD.AvoidFieldNameMatchingMethodName")
-  private boolean readOnly;
 
   @SuppressWarnings("PMD.AvoidFieldNameMatchingMethodName")
   private boolean distinct = false;
@@ -133,6 +144,13 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
     setDatastore(datastore);
     this.sessionFactory = sessionFactory;
     this.cb = sessionFactory.getCriteriaBuilder();
+    if (TransactionSynchronizationManager.hasResource(sessionFactory)) {
+      this.participate = true;
+    } else {
+      this.participate = false;
+      org.hibernate.Session session = sessionFactory.openSession();
+      TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session));
+    }
     HibernateSession session = (HibernateSession) datastore.connect();
     hibernateQuery =
         new HibernateQuery(
@@ -208,7 +226,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    * @param shouldLock True if it should
    */
   public void lock(boolean shouldLock) {
-    this.shouldLock = shouldLock;
+    hibernateQuery.lock(shouldLock);
   }
 
   /**
@@ -229,7 +247,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    */
   @Override
   public BuildableCriteria cache(boolean shouldCache) {
-    this.shouldCache = shouldCache;
+    hibernateQuery.cache(shouldCache);
     return this;
   }
 
@@ -245,7 +263,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    */
   @Override
   public BuildableCriteria readOnly(boolean readOnly) {
-    this.readOnly = readOnly;
+    hibernateQuery.setReadOnly(readOnly);
     return this;
   }
 
@@ -1272,6 +1290,13 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
 
   /** Closes the session if it is copen */
   public void closeSession() {
+    if (!participate) {
+      SessionHolder sessionHolder =
+          (SessionHolder) TransactionSynchronizationManager.unbindResource(sessionFactory);
+      if (sessionHolder.getSession().isOpen()) {
+        sessionHolder.getSession().close();
+      }
+    }
     hibernateQuery.getSession().disconnect();
   }
 
diff --git a/grails-data-hibernate7/core/src/test/groovy/grails/orm/CriteriaMethodInvokerSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/grails/orm/CriteriaMethodInvokerSpec.groovy
index 978c64532c..02b713486d 100644
--- a/grails-data-hibernate7/core/src/test/groovy/grails/orm/CriteriaMethodInvokerSpec.groovy
+++ b/grails-data-hibernate7/core/src/test/groovy/grails/orm/CriteriaMethodInvokerSpec.groovy
@@ -3,13 +3,18 @@ package grails.orm
 import groovy.lang.Closure
 import groovy.lang.MissingMethodException
 import org.grails.orm.hibernate.query.HibernateQuery
+import org.grails.orm.hibernate.HibernateSession
+import org.hibernate.Session
 import org.hibernate.SessionFactory
+import org.springframework.orm.hibernate5.SessionHolder
+import org.springframework.transaction.support.TransactionSynchronizationManager
 import spock.lang.Specification
 
 class CriteriaMethodInvokerSpec extends Specification {
 
     HibernateCriteriaBuilder builder = Mock(HibernateCriteriaBuilder)
     HibernateQuery query = Mock(HibernateQuery)
+    SessionFactory sessionFactory = Mock(SessionFactory)
     CriteriaMethodInvoker invoker = new CriteriaMethodInvoker(builder)
 
     def setup() {
@@ -195,6 +200,22 @@ class CriteriaMethodInvokerSpec extends Specification {
         1 * builder.readOnly(true)
     }
 
+    void "trySimpleCriteria: singleResult delegates to builder.singleResult"() {
+        when:
+        invoker.trySimpleCriteria('singleResult', CriteriaMethods.SINGLE_RESULT, [42L] as Object[])
+
+        then:
+        1 * builder.singleResult()
+    }
+
+    void "tryPropertyCriteria: fetchMode delegates to builder.fetchMode"() {
+        when:
+        invoker.tryPropertyCriteria(CriteriaMethods.FETCH_MODE, ["transactions", org.hibernate.FetchMode.JOIN] as Object[])
+
+        then:
+        1 * builder.fetchMode("transactions", org.hibernate.FetchMode.JOIN)
+    }
+
     void "trySimpleCriteria: isNull with String delegates to hibernateQuery.isNull"() {
         when:
         invoker.trySimpleCriteria('isNull', CriteriaMethods.IS_NULL, ['branch'] as Object[])
@@ -435,17 +456,9 @@ class CriteriaMethodInvokerSpec extends Specification {
         result != null  // UNHANDLED sentinel
         0 * builder._
     }
-
-    void "tryPropertyCriteria: non-String first arg returns UNHANDLED"() {
-        when:
-        def result = invoker.tryPropertyCriteria(CriteriaMethods.EQUALS, [42, 'Fred'] as Object[])
-
-        then:
-        result != null  // UNHANDLED sentinel
-        0 * builder._
-    }
 }
 
+
 class InvokerAccount {
     String firstName
     Set<InvokerTransaction> transactions
diff --git a/grails-data-hibernate7/core/src/test/groovy/grails/orm/HibernateCriteriaBuilderDirectSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/grails/orm/HibernateCriteriaBuilderDirectSpec.groovy
index f876c89167..218c7292e5 100644
--- a/grails-data-hibernate7/core/src/test/groovy/grails/orm/HibernateCriteriaBuilderDirectSpec.groovy
+++ b/grails-data-hibernate7/core/src/test/groovy/grails/orm/HibernateCriteriaBuilderDirectSpec.groovy
@@ -4,6 +4,9 @@ import grails.gorm.annotation.Entity
 import grails.gorm.specs.HibernateGormDatastoreSpec
 import jakarta.persistence.criteria.JoinType
 import org.grails.datastore.mapping.query.Query
+import org.hibernate.Session
+import org.springframework.orm.hibernate5.SessionHolder
+import org.springframework.transaction.support.TransactionSynchronizationManager
 import spock.lang.Shared
 import java.math.RoundingMode
 
@@ -573,6 +576,53 @@ class HibernateCriteriaBuilderDirectSpec extends HibernateGormDatastoreSpec {
         when: builder.targetClass = DirectTransaction
         then: builder.targetClass == DirectTransaction
     }
+
+    void "test closeSession unbinds and closes session when not participating"() {
+        given:
+        def sf = manager.hibernateDatastore.sessionFactory
+        // Unbind anything before starting
+        TransactionSynchronizationManager.unbindResourceIfPossible(sf)
+        
+        Session nativeSession = sf.openSession()
+        // Builder created without bound resource -> participate = false
+        HibernateCriteriaBuilder b = new HibernateCriteriaBuilder(DirectAccount, sf, manager.hibernateDatastore)
+        // Now bind it so closeSession has something to unbind
+        TransactionSynchronizationManager.unbindResourceIfPossible(sf)
+        TransactionSynchronizationManager.bindResource(sf, new SessionHolder(nativeSession))
+
+        when:
+        b.closeSession()
+
+        then:
+        !TransactionSynchronizationManager.hasResource(sf)
+        !nativeSession.isOpen()
+    }
+
+    void "test closeSession does not unbind or close session when participating"() {
+        given:
+        def sf = manager.hibernateDatastore.sessionFactory
+        // Unbind anything before starting
+        TransactionSynchronizationManager.unbindResourceIfPossible(sf)
+
+        Session nativeSession = sf.openSession()
+        TransactionSynchronizationManager.unbindResourceIfPossible(sf)
+        TransactionSynchronizationManager.bindResource(sf, new SessionHolder(nativeSession))
+        // Builder created with bound resource -> participate = true
+        HibernateCriteriaBuilder b = new HibernateCriteriaBuilder(DirectAccount, sf, manager.hibernateDatastore)
+
+        when:
+        b.closeSession()
+
+        then:
+        TransactionSynchronizationManager.hasResource(sf)
+        nativeSession.isOpen()
+
+        cleanup:
+        TransactionSynchronizationManager.unbindResourceIfPossible(sf)
+        if (nativeSession?.isOpen()) {
+            nativeSession.close()
+        }
+    }
 }
 
 @Entity
diff --git a/grails-data-hibernate7/core/src/test/groovy/grails/orm/HibernateCriteriaBuilderSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/grails/orm/HibernateCriteriaBuilderSpec.groovy
index fa297dea84..f204c0db83 100644
--- a/grails-data-hibernate7/core/src/test/groovy/grails/orm/HibernateCriteriaBuilderSpec.groovy
+++ b/grails-data-hibernate7/core/src/test/groovy/grails/orm/HibernateCriteriaBuilderSpec.groovy
@@ -483,6 +483,36 @@ class HibernateCriteriaBuilderSpec extends HibernateGormDatastoreSpec {
         cleanup:
         results?.close()
     }
+
+    void "fetchMode applies joining or selection strategy"() {
+        when:
+        def results = c.list {
+            fetchMode("transactions", org.hibernate.FetchMode.JOIN)
+            eq("firstName", "Fred")
+        }
+        then:
+        results.size() == 1
+        results[0].firstName == "Fred"
+
+        when:
+        results = c.list {
+            fetchMode("transactions", org.hibernate.FetchMode.SELECT)
+            eq("firstName", "Fred")
+        }
+        then:
+        results.size() == 1
+        results[0].firstName == "Fred"
+    }
+
+    void "singleResult returns exactly one row"() {
+        when:
+        c.eq("firstName", "Fred")
+        def result = c.singleResult()
+
+        then:
+        result != null
+        result.firstName == "Fred"
+    }
 }
 
 @Entity
diff --git a/grails-doc/src/en/ref/Domain Classes/createCriteria.adoc b/grails-doc/src/en/ref/Domain Classes/createCriteria.adoc
index 49451e7013..7a5a4a98f5 100644
--- a/grails-doc/src/en/ref/Domain Classes/createCriteria.adoc	
+++ b/grails-doc/src/en/ref/Domain Classes/createCriteria.adoc	
@@ -84,6 +84,7 @@ Method reference:
 |Method|Description
 |*list*|The default method; returns all matching rows.
 |*get*|Returns a unique result, i.e. just one row. The criteria has to be formed that way, that it only queries one row. This method is not to be confused with a limit to just the first row.
+|*singleResult*|Alias for *get*.
 |*scroll*|Returns a scrollable result set
 |*listDistinct*|If subqueries or associations are used, one may end up with the same row multiple times in the result set. In Hibernate one would do a "CriteriaSpecification.DISTINCT_ROOT_ENTITY". In Grails one can do it by just using this method.
 |===
@@ -151,7 +152,10 @@ With dynamic finders, you have access to options such as `max`, `sort`, etc. The
 |*order*(String, String)|Specifies both the sort column (the first argument) and the sort order (either 'asc' or 'desc').|`order "age", "desc"`
 |*firstResult*(int)|Specifies the offset for the results. A value of 0 will return all records up to the maximum specified.|`firstResult 20`
 |*maxResults*(int)|Specifies the maximum number of records to return.|`maxResults 10`
-|*cache*(boolean)|Indicates if the query should be cached (if the query cache is enabled).|`cache 'true'`
+|*cache*(boolean)|Indicates if the query should be cached (if the query cache is enabled).|`cache true`
+|*readOnly*(boolean)|Indicates if the entities returned by the query should be read-only (no dirty checking).|`readOnly true`
+|*lock*(boolean)|Indicates if a pessimistic write lock should be obtained.|`lock true`
+|*fetchMode*(String, FetchMode)|Specifies the fetching strategy for an association.|`fetchMode "transactions", FetchMode.JOIN`
 |===
 
 Criteria also support the notion of projections. A projection is used to change the nature of the results. For example the following query uses a projection to count the number of distinct `branch` names that exist for each `Account`:


(grails-core) 07/34: hibernate7: cleanup GrailsHibernateUtil

Posted by bo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

borinquenkid pushed a commit to branch 8.0.x-hibernate7-dev
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit 769a062fcdc073ee3a4f5145f9bc2c69863fece2
Author: Walter Duque de Estrada <wb...@mac.com>
AuthorDate: Thu Mar 5 21:08:44 2026 -0600

    hibernate7: cleanup GrailsHibernateUtil
---
 .../orm/hibernate/cfg/GrailsHibernateUtil.java     |  16 ++-
 .../hibernate/cfg/GrailsHibernateUtilSpec.groovy   | 114 +++++++++++++++++++++
 .../secondpass/ListSecondPassBinderSpec.groovy     | 100 +++++++++++++++---
 3 files changed, 209 insertions(+), 21 deletions(-)

diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsHibernateUtil.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsHibernateUtil.java
index ef13486c3c..8282172c76 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsHibernateUtil.java
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsHibernateUtil.java
@@ -95,9 +95,8 @@ public class GrailsHibernateUtil extends HibernateRuntimeUtils {
   /** @deprecated Use {@link org.grails.orm.hibernate.query.HibernateQueryArgument#LOCK} */
   @Deprecated(since = "8.0", forRemoval = true)
   public static final String ARGUMENT_LOCK = HibernateQueryArgument.LOCK.value();
-  public static final Class<?>[] EMPTY_CLASS_ARRAY = {};
 
-  private static HibernateProxyHandler proxyHandler = new HibernateProxyHandler();
+  private static final HibernateProxyHandler proxyHandler = new HibernateProxyHandler();
 
   /**
    * Sets the target object to read-only using the given SessionFactory instance. This avoids
@@ -182,9 +181,8 @@ public class GrailsHibernateUtil extends HibernateRuntimeUtils {
    */
   @Deprecated
   public static void ensureCorrectGroovyMetaClass(Object target, Class<?> persistentClass) {
-    if (target instanceof GroovyObject) {
-      GroovyObject go = ((GroovyObject) target);
-      if (!go.getMetaClass().getTheClass().equals(persistentClass)) {
+    if (target instanceof GroovyObject go) {
+        if (!go.getMetaClass().getTheClass().equals(persistentClass)) {
         go.setMetaClass(GroovySystem.getMetaClassRegistry().getMetaClass(persistentClass));
       }
     }
@@ -247,7 +245,7 @@ public class GrailsHibernateUtil extends HibernateRuntimeUtils {
     return StringHelper.unqualify(qualifiedName);
   }
 
-  public static boolean isDomainClass(Class clazz) {
+  public static boolean isDomainClass(Class<?> clazz) {
     if (GormEntity.class.isAssignableFrom(clazz)) {
       return true;
     }
@@ -257,9 +255,9 @@ public class GrailsHibernateUtil extends HibernateRuntimeUtils {
       return false;
     }
 
-    if (((Class<?>) clazz).isEnum()) return false;
+    if (clazz.isEnum()) return false;
 
-    Annotation[] allAnnotations = ((Class<?>) clazz).getAnnotations();
+    Annotation[] allAnnotations = clazz.getAnnotations();
     for (Annotation annotation : allAnnotations) {
       Class<? extends Annotation> type = annotation.annotationType();
       String annName = type.getName();
@@ -271,7 +269,7 @@ public class GrailsHibernateUtil extends HibernateRuntimeUtils {
       }
     }
 
-    Class<?> testClass = (Class<?>) clazz;
+    Class<?> testClass = clazz;
     while (testClass != null
         && !testClass.equals(GroovyObject.class)
         && !testClass.equals(Object.class)) {
diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/GrailsHibernateUtilSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/GrailsHibernateUtilSpec.groovy
new file mode 100644
index 0000000000..a3e9c390b4
--- /dev/null
+++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/GrailsHibernateUtilSpec.groovy
@@ -0,0 +1,114 @@
+/*
+ *  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.orm.hibernate.cfg
+
+import grails.gorm.annotation.Entity
+import grails.gorm.specs.HibernateGormDatastoreSpec
+import org.grails.datastore.mapping.model.config.GormProperties
+import org.hibernate.proxy.HibernateProxy
+import org.hibernate.proxy.LazyInitializer
+import spock.lang.Unroll
+
+class GrailsHibernateUtilSpec extends HibernateGormDatastoreSpec {
+
+    @Unroll
+    def "test isDomainClass for #clazz.simpleName"() {
+        expect:
+        GrailsHibernateUtil.isDomainClass(clazz) == expected
+
+        where:
+        clazz              | expected
+        GHUBook            | true
+        GHUNonDomain       | false
+        String             | false
+        GHUAnnotatedEntity | true
+    }
+
+    def "test incrementVersion"() {
+        given:
+        def book = new GHUBook(version: 1L)
+
+        when:
+        GrailsHibernateUtil.incrementVersion(book)
+
+        then:
+        book.version == 2L
+    }
+
+    def "test incrementVersion with non-long version"() {
+        given:
+        def obj = new GHUNonDomain()
+
+        when:
+        GrailsHibernateUtil.incrementVersion(obj)
+
+        then:
+        noExceptionThrown()
+    }
+
+    def "test qualify and unqualify"() {
+        expect:
+        GrailsHibernateUtil.qualify("org.test", "MyClass") == "org.test.MyClass"
+        GrailsHibernateUtil.unqualify("org.test.MyClass") == "MyClass"
+    }
+
+    def "test isNotEmpty"() {
+        expect:
+        GrailsHibernateUtil.isNotEmpty("test")
+        !GrailsHibernateUtil.isNotEmpty("")
+        !GrailsHibernateUtil.isNotEmpty(null)
+    }
+
+    def "test unwrapIfProxy with non-proxy"() {
+        given:
+        def obj = new Object()
+
+        expect:
+        GrailsHibernateUtil.unwrapIfProxy(obj).is(obj)
+        GrailsHibernateUtil.unwrapIfProxy(null) == null
+    }
+
+    def "test unwrapIfProxy with EntityProxy"() {
+        given:
+        def implementation = new Object()
+        def proxy = [
+            getTarget: { implementation },
+            isInitialized: { true }
+        ] as org.grails.datastore.mapping.proxy.EntityProxy
+
+        expect:
+        GrailsHibernateUtil.unwrapIfProxy(proxy).is(implementation)
+    }
+}
+
+@Entity
+class GHUBook {
+    Long id
+    Long version
+    String title
+}
+
+class GHUNonDomain {
+    String name
+}
+
+@grails.persistence.Entity
+class GHUAnnotatedEntity {
+    Long id
+}
diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/ListSecondPassBinderSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/ListSecondPassBinderSpec.groovy
index 5b6fd92cc8..1b3f1b68a8 100644
--- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/ListSecondPassBinderSpec.groovy
+++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/ListSecondPassBinderSpec.groovy
@@ -1,8 +1,12 @@
 package org.grails.orm.hibernate.cfg.domainbinding.secondpass
 
 import grails.gorm.specs.HibernateGormDatastoreSpec
+import org.grails.orm.hibernate.cfg.PersistentEntityNamingStrategy
+import org.grails.orm.hibernate.cfg.domainbinding.binder.SimpleValueColumnBinder
 import org.grails.orm.hibernate.cfg.domainbinding.hibernate.GrailsHibernatePersistentEntity
 import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateToManyProperty
+import org.hibernate.boot.spi.InFlightMetadataCollector
+import org.hibernate.boot.spi.MetadataBuildingContext
 import org.hibernate.mapping.OneToMany
 import org.hibernate.mapping.RootClass
 import org.hibernate.boot.spi.MetadataBuildingContext
@@ -50,8 +54,7 @@ import org.grails.orm.hibernate.cfg.domainbinding.binder.SingleTableSubclassBind
 
 class ListSecondPassBinderSpec extends HibernateGormDatastoreSpec {
 
-    protected Map getBinders(GrailsDomainBinder binder) {
-        def collector = getCollector()
+    protected Map getBinders(GrailsDomainBinder binder, InFlightMetadataCollector collector = getCollector()) {
         MetadataBuildingContext metadataBuildingContext = binder.getMetadataBuildingContext()
         PersistentEntityNamingStrategy namingStrategy = binder.getNamingStrategy()
         JdbcEnvironment jdbcEnvironment = binder.getJdbcEnvironment()
@@ -85,7 +88,7 @@ class ListSecondPassBinderSpec extends HibernateGormDatastoreSpec {
                 simpleValueColumnFetcher
                 ,
                 collectionHolder,
-                getCollector()
+                collector
         )
         PropertyFromValueCreator propertyFromValueCreator = new PropertyFromValueCreator()
         ComponentUpdater componentUpdater = new ComponentUpdater(propertyFromValueCreator)
@@ -114,18 +117,18 @@ class ListSecondPassBinderSpec extends HibernateGormDatastoreSpec {
         IdentityBinder identityBinder = new IdentityBinder(simpleIdBinder, compositeIdBinder)
         VersionBinder versionBinder = new VersionBinder(metadataBuildingContext, simpleValueBinder, propertyBinderHelper, BasicValue::new)
 
-        ClassBinder classBinder = new ClassBinder(getCollector())
+        ClassBinder classBinder = new ClassBinder(collector)
         ClassPropertiesBinder classPropertiesBinder = new ClassPropertiesBinder(propertyBinder, propertyFromValueCreator)
-        MultiTenantFilterBinder multiTenantFilterBinder = new MultiTenantFilterBinder(new org.grails.orm.hibernate.cfg.domainbinding.util.GrailsPropertyResolver(), new org.grails.orm.hibernate.cfg.domainbinding.util.MultiTenantFilterDefinitionBinder(), getCollector(), defaultColumnNameFetcher)
-        JoinedSubClassBinder joinedSubClassBinder = new JoinedSubClassBinder(metadataBuildingContext, namingStrategy, new org.grails.orm.hibernate.cfg.domainbinding.binder.SimpleValueColumnBinder(), columnNameForPropertyAndPathFetcher, classBinder, getCollector())
-        UnionSubclassBinder unionSubclassBinder = new UnionSubclassBinder(metadataBuildingContext, namingStrategy, classBinder, getCollector())
+        MultiTenantFilterBinder multiTenantFilterBinder = new MultiTenantFilterBinder(new org.grails.orm.hibernate.cfg.domainbinding.util.GrailsPropertyResolver(), new org.grails.orm.hibernate.cfg.domainbinding.util.MultiTenantFilterDefinitionBinder(), collector, defaultColumnNameFetcher)
+        JoinedSubClassBinder joinedSubClassBinder = new JoinedSubClassBinder(metadataBuildingContext, namingStrategy, new org.grails.orm.hibernate.cfg.domainbinding.binder.SimpleValueColumnBinder(), columnNameForPropertyAndPathFetcher, classBinder, collector)
+        UnionSubclassBinder unionSubclassBinder = new UnionSubclassBinder(metadataBuildingContext, namingStrategy, classBinder, collector)
         SingleTableSubclassBinder singleTableSubclassBinder = new SingleTableSubclassBinder(classBinder)
 
         SubclassMappingBinder subclassMappingBinder = new SubclassMappingBinder(metadataBuildingContext, joinedSubClassBinder, unionSubclassBinder, singleTableSubclassBinder, classPropertiesBinder)
-        SubClassBinder subClassBinder = new SubClassBinder(binder.getMappingCacheHolder(), subclassMappingBinder, multiTenantFilterBinder, "dataSource", getCollector())
-        RootPersistentClassCommonValuesBinder rootPersistentClassCommonValuesBinder = new RootPersistentClassCommonValuesBinder(metadataBuildingContext, namingStrategy, identityBinder, versionBinder, classBinder, classPropertiesBinder, getCollector())
+        SubClassBinder subClassBinder = new SubClassBinder(binder.getMappingCacheHolder(), subclassMappingBinder, multiTenantFilterBinder, "dataSource", collector)
+        RootPersistentClassCommonValuesBinder rootPersistentClassCommonValuesBinder = new RootPersistentClassCommonValuesBinder(metadataBuildingContext, namingStrategy, identityBinder, versionBinder, classBinder, classPropertiesBinder, collector)
         DiscriminatorPropertyBinder discriminatorPropertyBinder = new DiscriminatorPropertyBinder(metadataBuildingContext, binder.getMappingCacheHolder(), new org.grails.orm.hibernate.cfg.domainbinding.binder.ConfiguredDiscriminatorBinder(new org.grails.orm.hibernate.cfg.domainbinding.binder.SimpleValueColumnBinder(), new ColumnConfigToColumnBinder()), new org.grails.orm.hibernate.cfg.domainbinding.binder.DefaultDiscriminatorBinder(new org.grails.orm.hibernate.cfg.domainbinding.binder.Si [...]
-        RootBinder rootBinder = new RootBinder("default", multiTenantFilterBinder, subClassBinder, rootPersistentClassCommonValuesBinder, discriminatorPropertyBinder, getCollector())
+        RootBinder rootBinder = new RootBinder("default", multiTenantFilterBinder, subClassBinder, rootPersistentClassCommonValuesBinder, discriminatorPropertyBinder, collector)
 
         return [
             propertyBinder: propertyBinder,
@@ -146,7 +149,7 @@ class ListSecondPassBinderSpec extends HibernateGormDatastoreSpec {
     }
 
     protected void bindRoot(GrailsDomainBinder binder, GrailsHibernatePersistentEntity entity, InFlightMetadataCollector mappings, String sessionFactoryBeanName) {
-        def binders = getBinders(binder)
+        def binders = getBinders(binder, mappings)
         binders.rootBinder.bindRoot(entity)
     }
 
@@ -154,7 +157,9 @@ class ListSecondPassBinderSpec extends HibernateGormDatastoreSpec {
         manager.addAllDomainClasses([
             org.apache.grails.data.testing.tck.domains.Pet,
             org.apache.grails.data.testing.tck.domains.Person,
-            org.apache.grails.data.testing.tck.domains.PetType
+            org.apache.grails.data.testing.tck.domains.PetType,
+            LSBAuthor,
+            LSBBook
         ])
     }
 
@@ -181,4 +186,75 @@ class ListSecondPassBinderSpec extends HibernateGormDatastoreSpec {
         collection.element instanceof OneToMany
         (collection.element as OneToMany).referencedEntityName == petEntity.name
     }
+
+    void "test bidirectional list binding"() {
+        given:
+        def binder = getGrailsDomainBinder()
+        def collector = getCollector()
+        def metadataBuildingContext = binder.getMetadataBuildingContext()
+        def binders = getBinders(binder, collector)
+        def collectionBinder = binders.collectionBinder
+        def listBinder = collectionBinder.listSecondPassBinder
+
+        def authorEntity = getPersistentEntity(LSBAuthor) as GrailsHibernatePersistentEntity
+        def bookEntity = getPersistentEntity(LSBBook) as GrailsHibernatePersistentEntity
+        def booksProp = authorEntity.getPropertyByName("books") as HibernateToManyProperty
+
+        def rootClass = new RootClass(metadataBuildingContext)
+        rootClass.setEntityName(authorEntity.name)
+        rootClass.setJpaEntityName(authorEntity.name)
+        rootClass.setTable(collector.addTable(null, null, "LSB_AUTHOR", null, false, metadataBuildingContext))
+        collector.addEntityBinding(rootClass)
+
+        def bookRootClass = new RootClass(metadataBuildingContext)
+        bookRootClass.setEntityName(bookEntity.name)
+        bookRootClass.setJpaEntityName(bookEntity.name)
+        bookRootClass.setTable(collector.addTable(null, null, "LSB_BOOK", null, false, metadataBuildingContext))
+        collector.addEntityBinding(bookRootClass)
+
+        def authorValue = new org.hibernate.mapping.ManyToOne(metadataBuildingContext, bookRootClass.getTable())
+        authorValue.setReferencedEntityName(authorEntity.name)
+        def authorCol = new org.hibernate.mapping.Column("author_id")
+        authorCol.setValue(authorValue)
+        authorValue.addColumn(authorCol)
+        def authorProp = new org.hibernate.mapping.Property()
+        authorProp.setName("author")
+        authorProp.setValue(authorValue)
+        bookRootClass.addProperty(authorProp)
+
+        def persistentClasses = [
+            (authorEntity.name): rootClass,
+            (bookEntity.name): bookRootClass
+        ]
+
+        def list = new org.hibernate.mapping.List(metadataBuildingContext, rootClass)
+        list.setRole("${authorEntity.name}.books".toString())
+        list.setCollectionTable(rootClass.getTable())
+
+        def element = new org.hibernate.mapping.ManyToOne(metadataBuildingContext, list.getCollectionTable())
+        element.setReferencedEntityName(LSBBook.name)
+        list.setElement(element)
+
+        when:
+        listBinder.bindListSecondPass(booksProp, persistentClasses, list)
+
+        then:
+        noExceptionThrown()
+        list.index != null
+        list.baseIndex == 0
+    }
+}
+
+@grails.gorm.annotation.Entity
+class LSBAuthor {
+    Long id
+    List<LSBBook> books
+    static hasMany = [books: LSBBook]
+}
+
+@grails.gorm.annotation.Entity
+class LSBBook {
+    Long id
+    LSBAuthor author
+    static belongsTo = [author: LSBAuthor]
 }


(grails-core) 13/34: hibernate7: Refactoring HibernateGormStaticApi

Posted by bo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

borinquenkid pushed a commit to branch 8.0.x-hibernate7-dev
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit 45b9743bf489376d2474986e29570401d170f370
Author: Walter Duque de Estrada <wb...@mac.com>
AuthorDate: Fri Mar 6 11:10:09 2026 -0600

    hibernate7: Refactoring HibernateGormStaticApi
---
 gradle/code-style-config.gradle                    |  8 +--
 grails-data-hibernate7/core/build.gradle           |  1 +
 .../orm/hibernate/HibernateGormStaticApi.groovy    | 71 +++++++++-------------
 .../orm/hibernate/query/HibernateHqlQuery.java     | 10 ++-
 4 files changed, 42 insertions(+), 48 deletions(-)

diff --git a/gradle/code-style-config.gradle b/gradle/code-style-config.gradle
index d7a74d652d..4db843a1f8 100644
--- a/gradle/code-style-config.gradle
+++ b/gradle/code-style-config.gradle
@@ -55,17 +55,17 @@ spotless {
     }
 }
 
-// Do not run Code Style checks if the property 'skipCodeStyle' is defined
+// Do not run Code Style checks unless the property 'runCodeStyle' is defined
 tasks.withType(Pmd).configureEach {
     group = 'verification'
-    onlyIf { !project.hasProperty('skipCodeStyle') }
+    onlyIf { project.hasProperty('runCodeStyle') }
 }
 tasks.withType(CodeNarc).configureEach {
     group = 'verification'
-    onlyIf { !project.hasProperty('skipCodeStyle') }
+    onlyIf { project.hasProperty('runCodeStyle') }
 }
 tasks.matching { it.name.startsWith('spotless') }.configureEach {
-    onlyIf { !project.hasProperty('skipCodeStyle') }
+    onlyIf { project.hasProperty('runCodeStyle') }
 }
 
 tasks.register('codeStyle') {
diff --git a/grails-data-hibernate7/core/build.gradle b/grails-data-hibernate7/core/build.gradle
index c7c3d230c1..76242d7cfd 100644
--- a/grails-data-hibernate7/core/build.gradle
+++ b/grails-data-hibernate7/core/build.gradle
@@ -161,6 +161,7 @@ spotbugs {
 }
 
 tasks.withType(com.github.spotbugs.snom.SpotBugsTask).configureEach {
+    onlyIf { project.hasProperty('runCodeStyle') }
     reports {
         xml.enabled = false
         html.enabled = true     // → nice HTML report in build/reports/spotbugs
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy
index f65b874bbe..49c7e7ad91 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy
@@ -17,7 +17,6 @@ package org.grails.orm.hibernate
 
 import org.hibernate.jpa.AvailableHints
 
-import org.grails.datastore.mapping.model.PersistentProperty
 
 import grails.orm.HibernateCriteriaBuilder
 import groovy.transform.CompileStatic
@@ -179,21 +178,23 @@ class HibernateGormStaticApi<D> extends GormStaticApi<D> {
 
     @Override
     List<D> getAll() {
-        createHibernateQuery().list()
+        doListInternal("from ${persistentEntity.name}".toString(), [:], [], [:], false)
     }
 
-    protected HibernateQuery createHibernateQuery() {
-        new HibernateQuery(hibernateSession, persistentEntity)
-    }
 
     @Override
     Integer count() {
-        createHibernateQuery().count().singleResult() as Integer
+        String entity = persistentEntity.name
+        doSingleInternal("select count(*) from $entity" as String, [:], [], [:], false) as Integer
     }
 
     @Override
     boolean exists(Serializable id) {
-        !createHibernateQuery().idEq(convertIdentifier(id)).list().isEmpty()
+        def converted = convertIdentifier(id)
+        if (converted == null) return false
+        String entity = persistentEntity.name
+        String idName = persistentEntity.identity.name
+        (doSingleInternal("select count(*) from $entity where $idName = :id" as String, [id: converted], [], [:], false) as Long) > 0
     }
 
     @Override
@@ -295,15 +296,20 @@ class HibernateGormStaticApi<D> extends GormStaticApi<D> {
 
 
 
+    @Override
+    D findWhere(Map queryMap, Map args) {
+        if (!queryMap) return null
+        String entity = persistentEntity.name
+        String where = queryMap.keySet().collect { "$it = :$it" }.join(' and ')
+        doSingleInternal("from $entity where $where" as String, queryMap as Map, [], args, false)
+    }
+
     @Override
     List<D> findAllWhere(Map queryMap, Map args) {
         if (!queryMap) return null
-        def hibernateQuery = new HibernateQuery(hibernateSession, persistentEntity)
-        queryMap.each {key,value -> hibernateQuery.eq(key.toString(),value)}
-        firePreQueryEvent()
-        def result = hibernateQuery.list()
-        firePostQueryEvent(result)
-        result as List<D>
+        String entity = persistentEntity.name
+        String where = queryMap.keySet().collect { "$it = :$it" }.join(' and ')
+        doListInternal("from $entity where $where" as String, queryMap as Map, [], args, false)
     }
 
     @Override
@@ -376,15 +382,15 @@ class HibernateGormStaticApi<D> extends GormStaticApi<D> {
         doListInternal(query, [:], positionalParams, args, false)
     }
 
-    @Override
-    D findWhere(Map queryMap, Map args) {
-        if (!queryMap) return null
-        def hibernateQuery = new HibernateQuery(hibernateSession, persistentEntity)
-        queryMap.each {key,value -> hibernateQuery.eq(key.toString(),value)}
-        firePreQueryEvent()
-        def result = hibernateQuery.singleResult()
-        firePostQueryEvent(result)
-        result as D
+    private List<D> getAllInternal(List ids) {
+        if (!ids) return []
+        String idName = persistentEntity.identity.name
+        String entity = persistentEntity.name
+        Class<?> idType = persistentEntity.identity.type
+        List convertedIds = ids.collect { HibernateRuntimeUtils.convertValueToType(it, idType, conversionService) }
+        List<D> results = doListInternal("from $entity where $idName in (:ids)" as String, [ids: convertedIds], [], [:], false)
+        Map<Object, D> byId = results.collectEntries { [(it[idName]): it] }
+        ids.collect { byId[it] }
     }
 
     List<D> getAll(List ids) {
@@ -400,27 +406,6 @@ class HibernateGormStaticApi<D> extends GormStaticApi<D> {
         getAllInternal(ids as List)
     }
 
-    private List<D> getAllInternal(List ids) {
-        if (!ids) return []
-
-        hibernateTemplate.execute { Session session ->
-            PersistentProperty identity = persistentEntity.identity
-            Class<?> identityType = identity.type
-            String identityName = identity.name
-            List<Object> convertedIds = ids.collect { HibernateRuntimeUtils.convertValueToType(it, identityType, conversionService) }
-            CriteriaBuilder cb = session.getCriteriaBuilder()
-            CriteriaQuery<D> cq = cb.createQuery((Class<D>)persistentEntity.javaClass)
-            Root<D> root = cq.from((Class<D>)persistentEntity.javaClass)
-            cq.select(root).where(root.get("id").in(convertedIds))
-            firePreQueryEvent()
-
-            List<D> results = session.createQuery(cq).resultList
-            firePostQueryEvent(results)
-            Map<Object, D> idsMap = results.collectEntries { [it[identityName], it] }
-            ids.collect { idsMap[it] }
-        } as List<D>
-    }
-
 
 
 
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateHqlQuery.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateHqlQuery.java
index d658935b36..b912872c29 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateHqlQuery.java
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateHqlQuery.java
@@ -114,13 +114,21 @@ public class HibernateHqlQuery extends Query {
       var q =
           ctx.isNative()
               ? session.createNativeQuery(ctx.hql(), ctx.targetClass())
-              : session.createQuery(ctx.hql(), ctx.targetClass());
+              : isScalarSelect(ctx.hql())
+                  ? session.createQuery(ctx.hql())
+                  : session.createQuery(ctx.hql(), ctx.targetClass());
       var result = new HibernateHqlQuery(hibernateSession, entity, q);
       result.setFlushMode(session.getHibernateFlushMode());
       return result;
     }
   }
 
+  /** Returns true if the HQL starts with a {@code select} clause that doesn't project the entity. */
+  private static boolean isScalarSelect(String hql) {
+    String trimmed = hql.stripLeading().toLowerCase();
+    return trimmed.startsWith("select") && !trimmed.startsWith("select e ") && !trimmed.startsWith("select e,");
+  }
+
   /**
    * Full factory — opens a session via the {@link GrailsHibernateTemplate}, builds the query from
    * the prepared {@link HqlQueryContext}, then applies settings and parameters.


(grails-core) 20/34: hibernate7: more Codenarc

Posted by bo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

borinquenkid pushed a commit to branch 8.0.x-hibernate7-dev
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit 03aaad881355ea0939b14850238488670d061064
Author: Walter Duque de Estrada <wb...@mac.com>
AuthorDate: Sat Mar 7 13:03:00 2026 -0600

    hibernate7: more Codenarc
---
 .../hibernate/HibernateMappingBuilder.groovy       |  5 +-
 .../hibernate/HibernateMappingKeyword.groovy       | 75 ++++++++++++++++++++++
 .../mapping/HibernateMappingBuilderTests.groovy    | 20 +++---
 3 files changed, 90 insertions(+), 10 deletions(-)

diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateMappingBuilder.groovy b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateMappingBuilder.groovy
index 1ecfed48dd..8ad9b0fd05 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateMappingBuilder.groovy
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateMappingBuilder.groovy
@@ -462,9 +462,10 @@ class HibernateMappingBuilder implements MappingConfigurationBuilder<Mapping, Pr
         Object firstArg = hasArgs ? argsArray[0] : null
         Object lastArg = argc > 0 ? argsArray[argc - 1] : null
 
-        if (name == 'user-type' && hasArgs && firstArg instanceof Map) {
+        HibernateMappingKeyword keyword = HibernateMappingKeyword.fromString(name)
+        if (keyword == HibernateMappingKeyword.USER_TYPE && hasArgs && firstArg instanceof Map) {
             hibernateCustomUserType((Map<String, Object>) firstArg)
-        } else if (name == 'importFrom' && hasArgs && firstArg instanceof Class) {
+        } else if (keyword == HibernateMappingKeyword.IMPORT_FROM && hasArgs && firstArg instanceof Class) {
             List<Closure> constraintsToImport = ClassPropertyFetcher.getStaticPropertyValuesFromInheritanceHierarchy(
                 (Class) firstArg, GormProperties.CONSTRAINTS, Closure)
             if (constraintsToImport) {
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateMappingKeyword.groovy b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateMappingKeyword.groovy
new file mode 100644
index 0000000000..c745f28605
--- /dev/null
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateMappingKeyword.groovy
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2024 the original author or authors.
+ *
+ * Licensed 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
+ *
+ *      http://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.orm.hibernate.cfg.domainbinding.hibernate
+
+import groovy.transform.CompileStatic
+
+/**
+ * Enum representing the supported keywords in the Hibernate ORM mapping DSL.
+ *
+ * @author walter.duquedeestrada
+ * @since 7.0
+ */
+@CompileStatic
+enum HibernateMappingKeyword {
+    INCLUDES('includes'),
+    HIBERNATE_CUSTOM_USER_TYPE('hibernateCustomUserType'),
+    TABLE('table'),
+    DISCRIMINATOR('discriminator'),
+    AUTO_IMPORT('autoImport'),
+    SORT('sort'),
+    AUTOWIRE('autowire'),
+    DYNAMIC_UPDATE('dynamicUpdate'),
+    DYNAMIC_INSERT('dynamicInsert'),
+    BATCH_SIZE('batchSize'),
+    ORDER('order'),
+    AUTO_TIMESTAMP('autoTimestamp'),
+    VERSION('version'),
+    TENANT_ID('tenantId'),
+    CACHE('cache'),
+    TABLE_PER_HIERARCHY('tablePerHierarchy'),
+    TABLE_PER_SUBCLASS('tablePerSubclass'),
+    TABLE_PER_CONCRETE_CLASS('tablePerConcreteClass'),
+    ID('id'),
+    PROPERTY('property'),
+    COLUMNS('columns'),
+    DATASOURCE('datasource'),
+    DATASOURCES('datasources'),
+    COMMENT('comment'),
+    USER_TYPE('user-type'),
+    IMPORT_FROM('importFrom')
+
+    private final String keyword
+
+    HibernateMappingKeyword(String keyword) {
+        this.keyword = keyword
+    }
+
+    String getKeyword() {
+        return keyword
+    }
+
+    @Override
+    String toString() {
+        return keyword
+    }
+
+    private static final Map<String, HibernateMappingKeyword> KEYWORDS = values().collectEntries { [it.keyword, it] }
+
+    static HibernateMappingKeyword fromString(String name) {
+        return KEYWORDS[name]
+    }
+}
diff --git a/grails-data-hibernate7/core/src/test/groovy/grails/gorm/hibernate/mapping/HibernateMappingBuilderTests.groovy b/grails-data-hibernate7/core/src/test/groovy/grails/gorm/hibernate/mapping/HibernateMappingBuilderTests.groovy
index 2e34e104fa..efa5a72013 100644
--- a/grails-data-hibernate7/core/src/test/groovy/grails/gorm/hibernate/mapping/HibernateMappingBuilderTests.groovy
+++ b/grails-data-hibernate7/core/src/test/groovy/grails/gorm/hibernate/mapping/HibernateMappingBuilderTests.groovy
@@ -18,6 +18,8 @@
  */
 package grails.gorm.hibernate.mapping
 
+import java.sql.Clob
+
 import org.grails.orm.hibernate.cfg.CompositeIdentity
 import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernateMappingBuilder
 import org.grails.orm.hibernate.cfg.PropertyConfig
@@ -658,11 +660,13 @@ class HibernateMappingBuilderTests {
             version false
             id composite:['one','two'], compositeClass:HibernateMappingBuilder
         }
+        def compositeId = mapping.identity
+
+        assert compositeId instanceof CompositeIdentity
 
-        assert mapping.identity instanceof CompositeIdentity
-        assertEquals "one", mapping.identity.propertyNames[0]
-        assertEquals "two", mapping.identity.propertyNames[1]
-        assertEquals HibernateMappingBuilder, mapping.identity.compositeClass
+        assertEquals( "one",  compositeId.propertyNames[0])
+        assertEquals "two", compositeId.propertyNames[1]
+        assertEquals HibernateMappingBuilder, compositeId.compositeClass
     }
 
     @Test
@@ -705,7 +709,7 @@ class HibernateMappingBuilderTests {
                 firstName  column:'First_Name',
                         lazy:true,
                         unique:true,
-                        type: java.sql.Clob,
+                        type: Clob,
                         length:255,
                         index:'foo',
                         sqlType: 'text'
@@ -717,7 +721,7 @@ class HibernateMappingBuilderTests {
         assertEquals "First_Name",mapping.columns.firstName.column
         assertTrue mapping.columns.firstName.lazy
         assertTrue mapping.columns.firstName.unique
-        assertEquals java.sql.Clob,mapping.columns.firstName.type
+        assertEquals Clob,mapping.columns.firstName.type
         assertEquals 255,mapping.columns.firstName.length
         assertEquals 'foo',mapping.columns.firstName.getIndexName()
         assertEquals "text",mapping.columns.firstName.sqlType
@@ -733,7 +737,7 @@ class HibernateMappingBuilderTests {
             firstName  column:'First_Name',
                     lazy:true,
                     unique:true,
-                    type: java.sql.Clob,
+                    type: Clob,
                     length:255,
                     index:'foo',
                     sqlType: 'text'
@@ -744,7 +748,7 @@ class HibernateMappingBuilderTests {
         assertEquals "First_Name",mapping.columns.firstName.column
         assertTrue mapping.columns.firstName.lazy
         assertTrue mapping.columns.firstName.unique
-        assertEquals java.sql.Clob,mapping.columns.firstName.type
+        assertEquals Clob,mapping.columns.firstName.type
         assertEquals 255,mapping.columns.firstName.length
         assertEquals 'foo',mapping.columns.firstName.getIndexName()
         assertEquals "text",mapping.columns.firstName.sqlType


(grails-core) 14/34: hibernate7: removing GrailsHibernateQueryUtils.java

Posted by bo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

borinquenkid pushed a commit to branch 8.0.x-hibernate7-dev
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit 2544aea26e76cce351afd5ae304ca9f580d309c3
Author: Walter Duque de Estrada <wb...@mac.com>
AuthorDate: Fri Mar 6 12:45:41 2026 -0600

    hibernate7: removing GrailsHibernateQueryUtils.java
---
 .../orm/hibernate/HibernateGormStaticApi.groovy    | 196 ++++-------
 .../hibernate/query/GrailsHibernateQueryUtils.java | 372 ---------------------
 .../orm/hibernate/query/HibernateHqlQuery.java     |  94 +++++-
 .../grails/orm/hibernate/query/HibernateQuery.java |   2 +-
 .../orm/hibernate/query/HqlListQueryBuilder.java   | 154 +++++++++
 .../orm/hibernate/query/HqlQueryDelegate.java      |   2 +
 .../orm/hibernate/query/PagedResultList.java       |  67 +++-
 .../orm/hibernate/query/SelectQueryDelegate.java   |   6 +
 .../query/GrailsHibernateQueryUtilsSpec.groovy     |  80 +----
 9 files changed, 371 insertions(+), 602 deletions(-)

diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy
index 49c7e7ad91..d6cad39943 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy
@@ -17,25 +17,24 @@ package org.grails.orm.hibernate
 
 import org.hibernate.jpa.AvailableHints
 
-
 import grails.orm.HibernateCriteriaBuilder
 import groovy.transform.CompileStatic
 import groovy.util.logging.Slf4j
+import jakarta.persistence.criteria.CriteriaBuilder
+import jakarta.persistence.criteria.CriteriaQuery
 import jakarta.persistence.criteria.Expression
 import jakarta.persistence.criteria.Root
 import org.grails.datastore.gorm.GormEnhancer
 import org.grails.datastore.gorm.GormStaticApi
-import org.grails.datastore.gorm.finders.DynamicFinder
 import org.grails.datastore.gorm.finders.FinderMethod
 import org.grails.datastore.mapping.core.connections.ConnectionSourcesProvider
 import org.grails.datastore.mapping.query.api.BuildableCriteria as GrailsCriteria
 import org.grails.datastore.mapping.query.event.PostQueryEvent
 import org.grails.datastore.mapping.query.event.PreQueryEvent
 import org.grails.datastore.mapping.proxy.ProxyHandler
-import org.grails.orm.hibernate.query.GrailsHibernateQueryUtils
 import org.grails.orm.hibernate.query.HibernateHqlQuery
-import org.grails.orm.hibernate.query.HqlQueryContext
 import org.grails.orm.hibernate.query.HibernateQuery
+import org.grails.orm.hibernate.query.HqlQueryContext
 import org.grails.orm.hibernate.query.PagedResultList
 import org.grails.orm.hibernate.support.HibernateRuntimeUtils
 
@@ -46,8 +45,6 @@ import org.hibernate.query.Query
 
 import org.springframework.core.convert.ConversionService
 import org.springframework.transaction.PlatformTransactionManager
-import jakarta.persistence.criteria.CriteriaBuilder
-import jakarta.persistence.criteria.CriteriaQuery
 
 /**
  * The implementation of the GORM static method contract for Hibernate
@@ -64,7 +61,6 @@ class HibernateGormStaticApi<D> extends GormStaticApi<D> {
     protected final HibernateSession hibernateSession
     protected ProxyHandler proxyHandler
     protected SessionFactory sessionFactory
-    protected GrailsHibernateQueryUtils queryUtils
     protected Class identityType
     protected ClassLoader classLoader
     private HibernateGormInstanceApi<D> instanceApi
@@ -75,7 +71,6 @@ class HibernateGormStaticApi<D> extends GormStaticApi<D> {
         this.hibernateTemplate = new GrailsHibernateTemplate(datastore.getSessionFactory(), datastore)
         this.conversionService = datastore.mappingContext.conversionService
         this.proxyHandler = datastore.mappingContext.proxyHandler
-        this.queryUtils = new GrailsHibernateQueryUtils()
         this.hibernateSession = new HibernateSession(
                 (HibernateDatastore)datastore,
                 hibernateTemplate.getSessionFactory()
@@ -295,7 +290,6 @@ class HibernateGormStaticApi<D> extends GormStaticApi<D> {
     }
 
 
-
     @Override
     D findWhere(Map queryMap, Map args) {
         if (!queryMap) return null
@@ -317,21 +311,35 @@ class HibernateGormStaticApi<D> extends GormStaticApi<D> {
         doListInternal(query, namedParams, [], args, false)
     }
 
-    @SuppressWarnings('GroovyAssignabilityCheck')
-    private HibernateHqlQuery prepareHqlQuery(CharSequence hql, boolean isNative, boolean isUpdate,
-                                              Map namedParams, Collection positionalParams, Map args) {
-        def ctx = HqlQueryContext.prepare(hql, isNative, isUpdate, namedParams, persistentEntity)
-        return HibernateHqlQuery.createHqlQuery(
-                (HibernateDatastore) datastore,
-                sessionFactory,
-                persistentEntity,
-                ctx,
-                args,
-                positionalParams,
-                getHibernateTemplate()
-        )
+    @Override
+    List executeQuery(CharSequence query, Collection positionalParams, Map args) {
+        return doListInternal(query, [:], positionalParams, args, false)
+    }
+
+    @Override
+    List<D> findAll(CharSequence query, Collection positionalParams, Map args) {
+        doListInternal(query, [:], positionalParams, args, false)
     }
 
+    private List<D> getAllInternal(List ids) {
+        if (!ids) return []
+        String idName = persistentEntity.identity.name
+        String entity = persistentEntity.name
+        Class<?> idType = persistentEntity.identity.type
+        List convertedIds = ids.collect { HibernateRuntimeUtils.convertValueToType(it, idType, conversionService) }
+        List<D> results = doListInternal("from $entity where $idName in (:ids)" as String, [ids: convertedIds], [], [:], false)
+        Map<Object, D> byId = results.collectEntries { [(it[idName]): it] }
+        ids.collect { byId[it] }
+    }
+
+
+    @Override
+    List<D> getAll(Serializable... ids) {
+        getAllInternal(ids as List)
+    }
+
+
+
     private List<D> doListInternal(CharSequence hql,
                                    Map namedParams,
                                    Collection positionalParams,
@@ -357,6 +365,16 @@ class HibernateGormStaticApi<D> extends GormStaticApi<D> {
         return (D) sm
     }
 
+    @Override
+    Integer executeUpdate(CharSequence query, Map params, Map args) {
+        doInternalExecuteUpdate(query,params,[],args)
+    }
+
+    @Override
+    Integer executeUpdate(CharSequence query, Collection indexedParams, Map args) {
+        doInternalExecuteUpdate(query,[:],indexedParams,args)
+    }
+
     private Integer doInternalExecuteUpdate(CharSequence hql,
                                             Map namedParams,
                                             Collection positionalParams,
@@ -368,47 +386,22 @@ class HibernateGormStaticApi<D> extends GormStaticApi<D> {
         return (Integer) execute
     }
 
-
-
-
-
-    @Override
-    List executeQuery(CharSequence query, Collection positionalParams, Map args) {
-        return doListInternal(query, [:], positionalParams, args, false)
-    }
-
-    @Override
-    List<D> findAll(CharSequence query, Collection positionalParams, Map args) {
-        doListInternal(query, [:], positionalParams, args, false)
-    }
-
-    private List<D> getAllInternal(List ids) {
-        if (!ids) return []
-        String idName = persistentEntity.identity.name
-        String entity = persistentEntity.name
-        Class<?> idType = persistentEntity.identity.type
-        List convertedIds = ids.collect { HibernateRuntimeUtils.convertValueToType(it, idType, conversionService) }
-        List<D> results = doListInternal("from $entity where $idName in (:ids)" as String, [ids: convertedIds], [], [:], false)
-        Map<Object, D> byId = results.collectEntries { [(it[idName]): it] }
-        ids.collect { byId[it] }
-    }
-
-    List<D> getAll(List ids) {
-        getAllInternal(ids)
-    }
-
-    List<D> getAll(Long... ids) {
-        getAllInternal(ids as List)
-    }
-
-    @Override
-    List<D> getAll(Serializable... ids) {
-        getAllInternal(ids as List)
+    @SuppressWarnings('GroovyAssignabilityCheck')
+    private HibernateHqlQuery prepareHqlQuery(CharSequence hql, boolean isNative, boolean isUpdate,
+                                              Map namedParams, Collection positionalParams, Map args) {
+        def ctx = HqlQueryContext.prepare(hql, isNative, isUpdate, namedParams, persistentEntity)
+        return HibernateHqlQuery.createHqlQuery(
+                (HibernateDatastore) datastore,
+                sessionFactory,
+                persistentEntity,
+                ctx,
+                args,
+                positionalParams,
+                getHibernateTemplate()
+        )
     }
 
 
-
-
     protected Serializable convertIdentifier(Serializable id) {
         def identity = persistentEntity.identity
         if(identity != null) {
@@ -435,62 +428,23 @@ class HibernateGormStaticApi<D> extends GormStaticApi<D> {
     }
 
 
-
-
-
-
-
-
     @Override
     List<D> list(Map params = Collections.emptyMap()) {
-        hibernateTemplate.execute { Session session ->
-            CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder()
-            CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(persistentEntity.javaClass)
-            var queryRoot = criteriaQuery.from(persistentEntity.javaClass)
-            queryUtils.populateArgumentsForCriteria(
-                    persistentEntity,
-                    criteriaQuery,
-                    queryRoot,
-                    criteriaBuilder,
-                    params
-                    ,
-                    true
-            )
-            Query query = session.createQuery(criteriaQuery)
-
-            queryUtils.populateArgumentsForCriteria(
-                    persistentEntity,
-                    query,
-                    params,
-                    datastore.mappingContext.conversionService
-
-            )
-
-
-            HibernateHqlQuery hibernateQuery = new HibernateHqlQuery(
-                    new HibernateSession((HibernateDatastore)datastore, sessionFactory),
-                    persistentEntity,
-                    query
-            )
-            hibernateTemplate.applySettings(query)
-
-            params = params ? new HashMap(params) : Collections.emptyMap()
-            if(params.containsKey(DynamicFinder.ARGUMENT_MAX)) {
-                criteriaQuery = criteriaBuilder.createQuery(Object.class)
-                queryRoot = criteriaQuery.from(persistentEntity.javaClass)
-                return new PagedResultList(
-                        hibernateTemplate,
-                        persistentEntity,
-                        hibernateQuery,
-                        criteriaQuery,
-                        queryRoot,
-                        criteriaBuilder
-                )
-            }
-            else {
-                return hibernateQuery.list()
-            }
+        firePreQueryEvent()
+        HibernateHqlQuery hqlQuery = HibernateHqlQuery.forList(
+                (HibernateDatastore) datastore,
+                sessionFactory,
+                persistentEntity,
+                params,
+                getHibernateTemplate(),
+                datastore.mappingContext.conversionService
+        )
+        if (params.containsKey('max')) {
+            return new PagedResultList(getHibernateTemplate(), persistentEntity, hqlQuery)
         }
+        List<D> result = (List<D>) hqlQuery.list()
+        firePostQueryEvent(result)
+        result
     }
 
     @Override
@@ -510,22 +464,6 @@ class HibernateGormStaticApi<D> extends GormStaticApi<D> {
         return builder
     }
 
-    @Override
-    D lock(Serializable id) {
-        (D)hibernateTemplate.lock((Class)persistentClass, convertIdentifier(id), LockMode.PESSIMISTIC_WRITE)
-    }
-
-    @Override
-    Integer executeUpdate(CharSequence query, Map params, Map args) {
-        doInternalExecuteUpdate(query,params,[],args)
-    }
-
-    @Override
-    Integer executeUpdate(CharSequence query, Collection indexedParams, Map args) {
-        doInternalExecuteUpdate(query,[:],indexedParams,args)
-    }
-
-
 
     protected void firePostQueryEvent(Object result) {
         def hibernateQuery = new HibernateQuery(new HibernateSession((HibernateDatastore) datastore, sessionFactory), persistentEntity)
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/GrailsHibernateQueryUtils.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/GrailsHibernateQueryUtils.java
deleted file mode 100644
index 29fd4de8b3..0000000000
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/GrailsHibernateQueryUtils.java
+++ /dev/null
@@ -1,372 +0,0 @@
-/*
- *  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.orm.hibernate.query;
-
-import jakarta.persistence.LockModeType;
-import jakarta.persistence.criteria.*;
-import java.util.Arrays;
-import java.util.Comparator;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Optional;
-import org.grails.datastore.mapping.config.Property;
-import org.grails.datastore.mapping.model.PersistentEntity;
-import org.grails.datastore.mapping.model.PersistentProperty;
-import org.grails.datastore.mapping.model.types.Association;
-import org.grails.datastore.mapping.model.types.Embedded;
-import org.grails.datastore.mapping.reflect.ClassUtils;
-import org.grails.orm.hibernate.cfg.Mapping;
-import org.grails.orm.hibernate.cfg.MappingCacheHolder;
-import org.hibernate.FetchMode;
-import org.hibernate.FlushMode;
-import org.hibernate.query.Query;
-import org.hibernate.query.QueryFlushMode;
-import org.hibernate.query.sqm.tree.domain.SqmBasicValuedSimplePath;
-import org.hibernate.query.sqm.tree.expression.SqmFunction;
-import org.springframework.core.convert.ConversionService;
-
-/**
- * Utility methods for configuring Hibernate queries
- *
- * @author Graeme Rocher
- * @since 4.0
- */
-@SuppressWarnings("PMD.DataflowAnomalyAnalysis")
-public class GrailsHibernateQueryUtils {
-
-  /**
-   * Populates criteria arguments for the given target class and arguments map
-   *
-   * @param entity The {@link PersistentEntity} instance
-   * @param query  The criteria instance
-   * @param argMap The arguments map
-   */
-  public void populateArgumentsForCriteria(
-      PersistentEntity entity,
-      CriteriaQuery<?> query,
-      Root<?> queryRoot,
-      CriteriaBuilder criteriaBuilder,
-      Map<String, Object> argMap,
-      boolean useDefaultMapping) {
-    Object fetchObj = argMap.get(HibernateQueryArgument.FETCH.value());
-    if (fetchObj instanceof Map<?, ?> fetch) {
-      for (Object o : fetch.keySet()) {
-        String associationName = (String) o;
-
-        final FetchMode fetchMode = getFetchMode(fetch.get(associationName));
-        if (fetchMode == FetchMode.JOIN) {
-          queryRoot.join(associationName);
-        }
-      }
-    }
-
-    final Object sortObj = argMap.get(HibernateQueryArgument.SORT.value());
-    if (sortObj != null) {
-      final boolean ignoreCase =
-          !(argMap.get(HibernateQueryArgument.IGNORE_CASE.value()) instanceof Boolean b) || b;
-      if (sortObj instanceof Map<?, ?> sortMap) {
-        for (Object sort : sortMap.keySet()) {
-          final String order =
-              HibernateQueryArgument.ORDER_DESC.value().equalsIgnoreCase((String) sortMap.get(sort))
-                  ? HibernateQueryArgument.ORDER_DESC.value()
-                  : HibernateQueryArgument.ORDER_ASC.value();
-          addOrderPossiblyNested(
-              query, queryRoot, criteriaBuilder, entity, (String) sort, order, ignoreCase);
-        }
-      } else {
-        final String sort = (String) sortObj;
-        final String order =
-            HibernateQueryArgument.ORDER_DESC.value().equalsIgnoreCase(
-                    (String) argMap.get(HibernateQueryArgument.ORDER.value()))
-                ? HibernateQueryArgument.ORDER_DESC.value()
-                : HibernateQueryArgument.ORDER_ASC.value();
-        addOrderPossiblyNested(query, queryRoot, criteriaBuilder, entity, sort, order, ignoreCase);
-      }
-    } else if (useDefaultMapping) {
-      Class<?> theClass = entity.getJavaClass();
-      Mapping m = MappingCacheHolder.getInstance().getMapping(theClass);
-      if (m != null) {
-        Map<String, String> sortMap = m.getSort().getNamesAndDirections();
-        for (Map.Entry<String, String> entry : sortMap.entrySet()) {
-          String sort = entry.getKey();
-          final String order =
-              HibernateQueryArgument.ORDER_DESC.value().equalsIgnoreCase(entry.getValue())
-                  ? HibernateQueryArgument.ORDER_DESC.value()
-                  : HibernateQueryArgument.ORDER_ASC.value();
-          addOrderPossiblyNested(
-              query, queryRoot, criteriaBuilder, entity, sort, order, true);
-        }
-      }
-    }
-  }
-
-  /**
-   * Populates criteria arguments for the given target class and arguments map
-   *
-   * @param entity The {@link PersistentEntity} instance
-   * @param query  The criteria instance
-   * @param argMap The arguments map
-   */
-  public void populateArgumentsForCriteria(
-      PersistentEntity entity,
-      Query<?> query,
-      Map<String, Object> argMap,
-      ConversionService conversionService) {
-    final Integer maxParam =
-        argMap.containsKey(HibernateQueryArgument.MAX.value())
-            ? conversionService.convert(argMap.get(HibernateQueryArgument.MAX.value()), Integer.class)
-            : null;
-    final Integer offsetParam =
-        argMap.containsKey(HibernateQueryArgument.OFFSET.value())
-            ? conversionService.convert(argMap.get(HibernateQueryArgument.OFFSET.value()), Integer.class)
-            : null;
-    if (argMap.containsKey(HibernateQueryArgument.FETCH_SIZE.value())) {
-      Integer fetchSize = conversionService.convert(argMap.get(HibernateQueryArgument.FETCH_SIZE.value()), Integer.class);
-      if (fetchSize != null) {
-        query.setFetchSize(fetchSize);
-      }
-    }
-    if (argMap.containsKey(HibernateQueryArgument.TIMEOUT.value())) {
-      Integer timeout = conversionService.convert(argMap.get(HibernateQueryArgument.TIMEOUT.value()), Integer.class);
-      if (timeout != null) {
-        query.setTimeout(timeout);
-      }
-    }
-    if (argMap.containsKey(HibernateQueryArgument.FLUSH_MODE.value())) {
-      query.setQueryFlushMode(convertQueryFlushMode(argMap.get(HibernateQueryArgument.FLUSH_MODE.value())));
-    }
-    if (argMap.containsKey(HibernateQueryArgument.READ_ONLY.value())) {
-      query.setReadOnly(ClassUtils.getBooleanFromMap(HibernateQueryArgument.READ_ONLY.value(), argMap));
-    }
-
-    final int max = maxParam == null ? -1 : maxParam;
-    final int offset = offsetParam == null ? -1 : offsetParam;
-    if (max > -1) {
-      query.setMaxResults(max);
-    }
-    if (offset > -1) {
-      query.setFirstResult(offset);
-    }
-    if (ClassUtils.getBooleanFromMap(HibernateQueryArgument.LOCK.value(), argMap)) {
-      query.setLockMode(LockModeType.PESSIMISTIC_WRITE);
-      query.setCacheable(false);
-    } else {
-      if (argMap.containsKey(HibernateQueryArgument.CACHE.value())) {
-        query.setCacheable(ClassUtils.getBooleanFromMap(HibernateQueryArgument.CACHE.value(), argMap));
-      } else {
-        cacheCriteriaByMapping(entity.getJavaClass(), query);
-      }
-    }
-  }
-
-  /**
-   * Add order to criteria, creating necessary subCriteria if nested sort property (ie.
-   * sort:'nested.property').
-   */
-  protected void addOrderPossiblyNested(
-      CriteriaQuery<?> query,
-      From<?, ?> queryRoot,
-      CriteriaBuilder criteriaBuilder,
-      PersistentEntity entity,
-      String sort,
-      String order,
-      boolean ignoreCase) {
-    int firstDotPos = sort.indexOf(".");
-    if (firstDotPos == -1) {
-      final PersistentProperty<? extends Property> property =
-          (PersistentProperty<? extends Property>) entity.getPropertyByName(sort);
-      ignoreCase = isIgnoreCaseProperty(ignoreCase, property);
-      addOrder(entity, query, queryRoot, criteriaBuilder, sort, order, ignoreCase);
-    } else { // nested property
-      String sortHead = sort.substring(0, firstDotPos);
-      String sortTail = sort.substring(firstDotPos + 1);
-      final PersistentProperty<? extends Property> property =
-          (PersistentProperty<? extends Property>) entity.getPropertyByName(sortHead);
-      if (property instanceof Embedded) {
-        // embedded objects cannot reference entities (at time of writing), so no more recursion
-        // needed
-        final PersistentProperty<? extends Property> associatedProperty =
-            (PersistentProperty<? extends Property>)
-                ((Embedded<?>) property).getAssociatedEntity().getPropertyByName(sortTail);
-        ignoreCase = isIgnoreCaseProperty(ignoreCase, associatedProperty);
-        addOrder(entity, query, queryRoot, criteriaBuilder, sort, order, ignoreCase);
-      } else if (property instanceof Association<? extends Property> a) {
-          final Join join = queryRoot.join(sortHead);
-        PersistentEntity associatedEntity = a.getAssociatedEntity();
-          addOrderPossiblyNested(
-            query,
-            join,
-            criteriaBuilder,
-            associatedEntity,
-            sortTail,
-            order,
-            ignoreCase); // Recurse on nested sort
-      }
-    }
-  }
-
-  protected boolean isIgnoreCaseProperty(
-      boolean ignoreCase, PersistentProperty<? extends Property> persistentProperty) {
-    if (ignoreCase && persistentProperty != null && persistentProperty.getType() != String.class) {
-      ignoreCase = false;
-    }
-    return ignoreCase;
-  }
-
-  /** Add order directly to criteria. */
-  protected void addOrder(
-      PersistentEntity entity,
-      CriteriaQuery<?> query,
-      From<?, ?> queryRoot,
-      CriteriaBuilder criteriaBuilder,
-      String sort,
-      String order,
-      boolean ignoreCase) {
-    var compositeIdSortOptional =
-        Optional.ofNullable(entity.getCompositeIdentity()).stream()
-            .flatMap(Arrays::stream)
-            .filter(Objects::nonNull)
-            .filter(id -> sort.equalsIgnoreCase(id.getName()))
-            .findFirst();
-
-    if (compositeIdSortOptional.isPresent()) {
-      Comparator<Order> orderComparator =
-              new Comparator<>() {
-                  @Override
-                  public int compare(Order o1, Order o2) {
-                      String name1 = getOrderName(o1);
-                      String name2 = getOrderName(o2);
-
-                      boolean name1IsSort = name1.equalsIgnoreCase(sort);
-                      boolean name2IsSort = name2.equalsIgnoreCase(sort);
-
-                      if (name1IsSort && !name2IsSort) {
-                          return -1; // o1 (the sort property) comes first
-                      }
-                      if (!name1IsSort && name2IsSort) {
-                          return 1; // o2 (the sort property) comes first
-                      }
-                      return 0; // Maintain original order for other properties
-                  }
-
-                  private static String getOrderName(Order o1) {
-                      return ((SqmBasicValuedSimplePath<?>)
-                              ((SqmFunction<?>) o1.getExpression()).getArguments().get(0))
-                              .getNavigablePath()
-                              .getLocalName();
-                  }
-              };
-      Order[] orders =
-          Arrays.stream(entity.getCompositeIdentity())
-              .map(PersistentProperty::getName)
-              .map(
-                  name ->
-                  {
-                    Path x = queryRoot.get(name);
-                    return ignoreCase ? criteriaBuilder.upper(x) : queryRoot.get(name);
-                  })
-              .map(
-                  path ->
-                      HibernateQueryArgument.ORDER_DESC.value().equals(order)
-                          ? criteriaBuilder.desc(path)
-                          : criteriaBuilder.asc(path))
-              .sorted(orderComparator)
-              .toArray(Order[]::new);
-      query.orderBy(orders);
-
-    } else if (entity.getIdentity() != null
-        && sort.equalsIgnoreCase(entity.getIdentity().getName())) {
-      Expression<?> path = queryRoot;
-
-      if (ignoreCase) {
-        path = criteriaBuilder.upper((Expression<String>) path);
-      }
-      if (HibernateQueryArgument.ORDER_DESC.value().equals(order)) {
-        query.orderBy(criteriaBuilder.desc(path));
-      } else {
-        query.orderBy(criteriaBuilder.asc(path));
-      }
-    } else {
-      Expression<?> path = queryRoot.get(sort);
-
-      if (ignoreCase) {
-        path = criteriaBuilder.upper((Expression<String>) path);
-      }
-      if (HibernateQueryArgument.ORDER_DESC.value().equals(order)) {
-        query.orderBy(criteriaBuilder.desc(path));
-      } else {
-        query.orderBy(criteriaBuilder.asc(path));
-      }
-    }
-  }
-
-  /**
-   * Configures the criteria instance to cache based on the configured mapping.
-   *
-   * @param targetClass The target class
-   * @param criteria The criteria
-   */
-  protected void cacheCriteriaByMapping(Class<?> targetClass, Query<?> criteria) {
-    Mapping m = MappingCacheHolder.getInstance().getMapping(targetClass);
-    if (m != null && m.getCache() != null && m.getCache().getEnabled()) {
-      criteria.setCacheable(true);
-    }
-  }
-
-  protected static FlushMode convertFlushMode(Object object) {
-    if (object == null) {
-      return null;
-    }
-    if (object instanceof FlushMode flushMode) {
-      return flushMode;
-    }
-    try {
-      return FlushMode.valueOf(object.toString());
-    } catch (IllegalArgumentException e) {
-      return FlushMode.COMMIT;
-    }
-  }
-
-  public static QueryFlushMode convertQueryFlushMode(Object object) {
-    FlushMode fm = convertFlushMode(object);
-    if (fm == null) return QueryFlushMode.DEFAULT;
-    return switch (fm) {
-      case ALWAYS -> QueryFlushMode.FLUSH;
-      case MANUAL, COMMIT -> QueryFlushMode.NO_FLUSH;
-      default -> QueryFlushMode.DEFAULT;
-    };
-  }
-
-  /**
-   * Retrieves the fetch mode for the specified instance; otherwise returns the default FetchMode.
-   *
-   * @param object The object, converted to a string
-   * @return The FetchMode
-   */
-  public FetchMode getFetchMode(Object object) {
-    String name = object != null ? object.toString() : "default";
-    if (name.equalsIgnoreCase(FetchMode.JOIN.toString()) || name.equalsIgnoreCase("eager")) {
-      return FetchMode.JOIN;
-    }
-    if (name.equalsIgnoreCase(FetchMode.SELECT.toString()) || name.equalsIgnoreCase("lazy")) {
-      return FetchMode.SELECT;
-    }
-    return FetchMode.DEFAULT;
-  }
-}
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateHqlQuery.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateHqlQuery.java
index b912872c29..116715fa02 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateHqlQuery.java
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateHqlQuery.java
@@ -19,6 +19,7 @@
 package org.grails.orm.hibernate.query;
 
 import jakarta.persistence.FlushModeType;
+import jakarta.persistence.LockModeType;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
@@ -39,7 +40,9 @@ import org.grails.orm.hibernate.HibernateSession;
 import org.grails.orm.hibernate.exceptions.GrailsQueryException;
 import org.hibernate.FlushMode;
 import org.hibernate.SessionFactory;
+import org.hibernate.query.QueryFlushMode;
 import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.core.convert.ConversionService;
 
 /**
  * A query implementation for HQL queries.
@@ -167,6 +170,31 @@ public class HibernateHqlQuery extends Query {
             : FlushModeType.COMMIT);
   }
 
+  public void populateQuerySettings(Map<?, ?> args, ConversionService conversionService) {
+    ifPresent(args, HibernateQueryArgument.MAX.value(), v -> delegate.setMaxResults(toInt(v, conversionService)));
+    ifPresent(args, HibernateQueryArgument.OFFSET.value(), v -> delegate.setFirstResult(toInt(v, conversionService)));
+    ifPresent(args, HibernateQueryArgument.CACHE.value(), v -> delegate.setCacheable(toBool(v)));
+    ifPresent(args, HibernateQueryArgument.FETCH_SIZE.value(), v -> delegate.setFetchSize(toInt(v, conversionService)));
+    ifPresent(args, HibernateQueryArgument.TIMEOUT.value(), v -> delegate.setTimeout(toInt(v, conversionService)));
+    ifPresent(args, HibernateQueryArgument.READ_ONLY.value(), v -> delegate.setReadOnly(toBool(v)));
+    ifPresent(args, HibernateQueryArgument.FLUSH_MODE.value(), v -> delegate.setQueryFlushMode(convertQueryFlushMode(v)));
+    if (toBoolFromMap(args, HibernateQueryArgument.LOCK.value())) {
+      delegate.setLockMode(LockModeType.PESSIMISTIC_WRITE);
+      delegate.setCacheable(false);
+    } else {
+      if (!args.containsKey(HibernateQueryArgument.CACHE.value())) {
+        org.grails.orm.hibernate.cfg.Mapping m =
+            org.grails.orm.hibernate.cfg.MappingCacheHolder.getInstance()
+                .getMapping(getEntity().getJavaClass());
+        if (m != null && m.getCache() != null && m.getCache().getEnabled()) {
+          delegate.setCacheable(true);
+        }
+      }
+    }
+  }
+
+  /** @deprecated Use {@link #populateQuerySettings(Map, ConversionService)} */
+  @Deprecated
   public void populateQuerySettings(Map<?, ?> args) {
     ifPresent(args, HibernateQueryArgument.MAX.value(), v -> delegate.setMaxResults(toInt(v)));
     ifPresent(args, HibernateQueryArgument.OFFSET.value(), v -> delegate.setFirstResult(toInt(v)));
@@ -174,10 +202,58 @@ public class HibernateHqlQuery extends Query {
     ifPresent(args, HibernateQueryArgument.FETCH_SIZE.value(), v -> delegate.setFetchSize(toInt(v)));
     ifPresent(args, HibernateQueryArgument.TIMEOUT.value(), v -> delegate.setTimeout(toInt(v)));
     ifPresent(args, HibernateQueryArgument.READ_ONLY.value(), v -> delegate.setReadOnly(toBool(v)));
-    ifPresent(
-        args,
-        HibernateQueryArgument.FLUSH_MODE.value(),
-        v -> delegate.setQueryFlushMode(GrailsHibernateQueryUtils.convertQueryFlushMode(v)));
+    ifPresent(args, HibernateQueryArgument.FLUSH_MODE.value(), v -> delegate.setQueryFlushMode(convertQueryFlushMode(v)));
+  }
+
+  /**
+   * Factory for {@code list(Map params)} — builds HQL with ORDER BY / JOIN FETCH from the params
+   * map, applies pagination settings, and wraps in a ready-to-execute {@link HibernateHqlQuery}.
+   */
+  @SuppressWarnings({"unchecked", "rawtypes"})
+  public static HibernateHqlQuery forList(
+      HibernateDatastore dataStore,
+      SessionFactory sessionFactory,
+      PersistentEntity entity,
+      Map<?, ?> params,
+      GrailsHibernateTemplate template,
+      ConversionService conversionService) {
+    HqlListQueryBuilder builder = new HqlListQueryBuilder(entity, params);
+    String hql = builder.buildListHql();
+    HqlQueryContext ctx = HqlQueryContext.prepare(hql, false, false, Collections.emptyMap(), entity);
+    HibernateHqlQuery hqlQuery =
+        template.execute(session -> buildQuery(session, dataStore, sessionFactory, entity, ctx));
+    org.hibernate.query.Query<?> q = hqlQuery.selectQuery();
+    if (q != null) template.applySettings(q);
+    Map<String, Object> mutableParams = params instanceof Map ? new HashMap<>((Map<String, Object>) params) : Collections.emptyMap();
+    hqlQuery.populateQuerySettings(mutableParams, conversionService);
+    return hqlQuery;
+  }
+
+  /**
+   * Builds the count HQL string used by {@link PagedResultList} when paging is requested.
+   */
+  public static String buildCountHql(PersistentEntity entity) {
+    return new HqlListQueryBuilder(entity, Collections.emptyMap()).buildCountHql();
+  }
+
+  public static QueryFlushMode convertQueryFlushMode(Object object) {
+    FlushMode fm = convertFlushMode(object);
+    if (fm == null) return QueryFlushMode.DEFAULT;
+    return switch (fm) {
+      case ALWAYS -> QueryFlushMode.FLUSH;
+      case MANUAL, COMMIT -> QueryFlushMode.NO_FLUSH;
+      default -> QueryFlushMode.DEFAULT;
+    };
+  }
+
+  private static FlushMode convertFlushMode(Object object) {
+    if (object == null) return null;
+    if (object instanceof FlushMode flushMode) return flushMode;
+    try {
+      return FlushMode.valueOf(object.toString());
+    } catch (IllegalArgumentException e) {
+      return FlushMode.COMMIT;
+    }
   }
 
   public void populateQueryWithNamedArguments(Map<?, ?> namedArgs) {
@@ -237,10 +313,20 @@ public class HibernateHqlQuery extends Query {
     return Integer.parseInt(v.toString());
   }
 
+  private static int toInt(Object v, ConversionService cs) {
+    if (v instanceof Integer i) return i;
+    return cs.convert(v, Integer.class);
+  }
+
   private static boolean toBool(Object v) {
     return Boolean.parseBoolean(v.toString());
   }
 
+  private static boolean toBoolFromMap(Map<?, ?> map, String key) {
+    Object v = map.get(key);
+    return v instanceof Boolean b ? b : v != null && Boolean.parseBoolean(v.toString());
+  }
+
   private static void ifPresent(
       Map<?, ?> map, String key, java.util.function.Consumer<Object> action) {
     Object v = map.get(key);
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java
index 61a47e48ea..985dc3d2ae 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java
@@ -481,7 +481,7 @@ public class HibernateQuery extends Query {
   }
 
   public void setHibernateFlushMode(FlushMode flushMode) {
-    this.flushMode = GrailsHibernateQueryUtils.convertQueryFlushMode(flushMode);
+    this.flushMode = HibernateHqlQuery.convertQueryFlushMode(flushMode);
   }
 
   public void setReadOnly(Boolean readOnly) {
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HqlListQueryBuilder.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HqlListQueryBuilder.java
new file mode 100644
index 0000000000..aaf3ce740b
--- /dev/null
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HqlListQueryBuilder.java
@@ -0,0 +1,154 @@
+/*
+ *  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.orm.hibernate.query;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import org.grails.datastore.gorm.finders.DynamicFinder;
+import org.grails.datastore.mapping.model.PersistentEntity;
+import org.grails.datastore.mapping.model.PersistentProperty;
+import org.grails.datastore.mapping.model.types.Association;
+import org.grails.datastore.mapping.model.types.Embedded;
+import org.grails.orm.hibernate.cfg.Mapping;
+import org.grails.orm.hibernate.cfg.MappingCacheHolder;
+
+/**
+ * Translates a GORM query-argument map into an HQL string for {@code list()}.
+ *
+ * <p>Handles {@code fetch} (JOIN FETCH), {@code sort} / {@code order} / {@code ignoreCase}
+ * (ORDER BY), and default sort from the entity's {@link Mapping}. The resulting HQL is a plain
+ * string so it passes through {@link HqlQueryContext} without GString interpolation.
+ */
+@SuppressWarnings("PMD.DataflowAnomalyAnalysis")
+class HqlListQueryBuilder {
+
+  private final PersistentEntity entity;
+  private final Map<?, ?> params;
+
+  HqlListQueryBuilder(PersistentEntity entity, Map<?, ?> params) {
+    this.entity = entity;
+    this.params = params;
+  }
+
+  /** Builds the SELECT HQL for the list query (no count). */
+  String buildListHql() {
+    String alias = "e";
+    StringBuilder hql = new StringBuilder("from ").append(entity.getName()).append(" ").append(alias);
+    appendJoinFetch(hql, alias);
+    appendOrderBy(hql, alias);
+    return hql.toString();
+  }
+
+  /** Builds the scalar count HQL for {@link PagedResultList}. */
+  String buildCountHql() {
+    return "select count(distinct e) from " + entity.getName() + " e";
+  }
+
+  // ─── JOIN FETCH ──────────────────────────────────────────────────────────
+
+  private void appendJoinFetch(StringBuilder hql, String alias) {
+    Object fetchObj = params.get(HibernateQueryArgument.FETCH.value());
+    if (!(fetchObj instanceof Map<?, ?> fetchMap)) return;
+    for (Object key : fetchMap.keySet()) {
+      String assocName = key.toString();
+      Object mode = fetchMap.get(key);
+      if (isJoinFetch(mode)) {
+        hql.append(" join fetch ").append(alias).append(".").append(assocName);
+      }
+    }
+  }
+
+  private static boolean isJoinFetch(Object mode) {
+    if (mode == null) return false;
+    String s = mode.toString();
+    return s.equalsIgnoreCase("join") || s.equalsIgnoreCase("eager");
+  }
+
+  // ─── ORDER BY ────────────────────────────────────────────────────────────
+
+  private void appendOrderBy(StringBuilder hql, String alias) {
+    List<String> clauses = new ArrayList<>();
+    Object sortObj = params.get(HibernateQueryArgument.SORT.value());
+    boolean ignoreCase = isIgnoreCase();
+
+    if (sortObj instanceof Map<?, ?> sortMap) {
+      for (Object sortKey : sortMap.keySet()) {
+        String prop = sortKey.toString();
+        String dir = direction((String) sortMap.get(sortKey));
+        clauses.add(orderClause(alias, prop, dir, ignoreCase && isStringProp(prop)));
+      }
+    } else if (sortObj instanceof String sort) {
+      String dir = direction((String) params.get(HibernateQueryArgument.ORDER.value()));
+      clauses.add(orderClause(alias, sort, dir, ignoreCase && isStringProp(sort)));
+    } else {
+      // fall back to default mapping sort
+      Mapping m = MappingCacheHolder.getInstance().getMapping(entity.getJavaClass());
+      if (m != null) {
+        m.getSort().getNamesAndDirections().forEach((prop, dir) ->
+            clauses.add(orderClause(alias, (String) prop, direction((String) dir), isStringProp((String) prop))));
+      }
+    }
+
+    if (!clauses.isEmpty()) {
+      hql.append(" order by ").append(String.join(", ", clauses));
+    }
+  }
+
+  private String orderClause(String alias, String prop, String dir, boolean upper) {
+    String path = alias + "." + prop;
+    return upper ? "upper(" + path + ") " + dir : path + " " + dir;
+  }
+
+  private static String direction(String raw) {
+    return HibernateQueryArgument.ORDER_DESC.value().equalsIgnoreCase(raw)
+        ? HibernateQueryArgument.ORDER_DESC.value()
+        : HibernateQueryArgument.ORDER_ASC.value();
+  }
+
+  private boolean isIgnoreCase() {
+    Object ic = params.get(HibernateQueryArgument.IGNORE_CASE.value());
+    return !(ic instanceof Boolean b) || b;
+  }
+
+  private boolean isStringProp(String name) {
+    // handle nested path: only check the leaf property's type
+    int dot = name.lastIndexOf('.');
+    String leaf = dot == -1 ? name : name.substring(dot + 1);
+    String head = dot == -1 ? null : name.substring(0, dot);
+    PersistentEntity owner = resolveOwner(head);
+    if (owner == null) return false;
+    PersistentProperty<?> prop = owner.getPropertyByName(leaf);
+    return prop != null && prop.getType() == String.class;
+  }
+
+  private PersistentEntity resolveOwner(String path) {
+    if (path == null) return entity;
+    PersistentProperty<?> prop = entity.getPropertyByName(path);
+    if (prop instanceof Embedded<?> emb) return emb.getAssociatedEntity();
+    if (prop instanceof Association<?> assoc) return assoc.getAssociatedEntity();
+    return null;
+  }
+
+  /** Returns true when the params indicate a paged query (i.e. {@code max} is set). */
+  @SuppressWarnings("rawtypes")
+  static boolean isPaged(Map params) {
+    return params.containsKey(DynamicFinder.ARGUMENT_MAX);
+  }
+}
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HqlQueryDelegate.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HqlQueryDelegate.java
index 42e60fe36d..a2e909082a 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HqlQueryDelegate.java
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HqlQueryDelegate.java
@@ -63,6 +63,8 @@ interface HqlQueryDelegate {
 
   default void setReadOnly(boolean b) {}
 
+  default void setLockMode(jakarta.persistence.LockModeType lockModeType) {}
+
   /** Sets a named collection parameter. For mutation queries, falls back to {@link #setParameter}. */
   default void setParameterList(String name, Collection<?> values) {}
 
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/PagedResultList.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/PagedResultList.java
index 4eb9e87528..d03c9eb702 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/PagedResultList.java
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/PagedResultList.java
@@ -32,12 +32,18 @@ public class PagedResultList extends grails.gorm.PagedResultList {
 
   private static final long serialVersionUID = 1L;
 
+  private final PersistentEntity entity;
+  private transient GrailsHibernateTemplate hibernateTemplate;
+
+  // CriteriaQuery-based count (legacy path)
   private final CriteriaQuery criteriaQuery;
   private final Root queryRoot;
   private final CriteriaBuilder criteriaBuilder;
-  private final PersistentEntity entity;
-  private transient GrailsHibernateTemplate hibernateTemplate;
 
+  // HQL-based count (new path)
+  private final String countHql;
+
+  /** Legacy constructor — count via CriteriaQuery. */
   public PagedResultList(
       GrailsHibernateTemplate template,
       PersistentEntity entity,
@@ -46,11 +52,26 @@ public class PagedResultList extends grails.gorm.PagedResultList {
       Root queryRoot,
       CriteriaBuilder criteriaBuilder) {
     super(hibernateHqlQuery);
-    hibernateTemplate = template;
+    this.hibernateTemplate = template;
+    this.entity = entity;
     this.criteriaQuery = criteriaQuery;
     this.queryRoot = queryRoot;
     this.criteriaBuilder = criteriaBuilder;
+    this.countHql = null;
+  }
+
+  /** HQL constructor — count via scalar HQL. */
+  public PagedResultList(
+      GrailsHibernateTemplate template,
+      PersistentEntity entity,
+      HibernateHqlQuery hibernateHqlQuery) {
+    super(hibernateHqlQuery);
+    this.hibernateTemplate = template;
     this.entity = entity;
+    this.countHql = HibernateHqlQuery.buildCountHql(entity);
+    this.criteriaQuery = null;
+    this.queryRoot = null;
+    this.criteriaBuilder = null;
   }
 
   @Override
@@ -62,24 +83,36 @@ public class PagedResultList extends grails.gorm.PagedResultList {
   public int getTotalCount() {
     if (totalCount == Integer.MIN_VALUE) {
       totalCount =
-          hibernateTemplate.execute(
-              new GrailsHibernateTemplate.HibernateCallback<Integer>() {
-                public Integer doInHibernate(Session session)
-                    throws HibernateException, SQLException {
-                  final CriteriaQuery finalQuery =
-                      criteriaQuery
-                          .select(criteriaBuilder.count(queryRoot))
-                          .distinct(true)
-                          .orderBy();
-                  final Query query = session.createQuery(finalQuery);
-                  hibernateTemplate.applySettings(query);
-                  return ((Number) query.uniqueResult()).intValue();
-                }
-              });
+          countHql != null ? countViaHql() : countViaCriteria();
     }
     return totalCount;
   }
 
+  private int countViaHql() {
+    return hibernateTemplate.execute(session -> {
+      Query<?> q = session.createQuery(countHql);
+      hibernateTemplate.applySettings(q);
+      return ((Number) q.uniqueResult()).intValue();
+    });
+  }
+
+  private int countViaCriteria() {
+    return hibernateTemplate.execute(
+        new GrailsHibernateTemplate.HibernateCallback<Integer>() {
+          public Integer doInHibernate(Session session)
+              throws HibernateException, SQLException {
+            final CriteriaQuery finalQuery =
+                criteriaQuery
+                    .select(criteriaBuilder.count(queryRoot))
+                    .distinct(true)
+                    .orderBy();
+            final Query query = session.createQuery(finalQuery);
+            hibernateTemplate.applySettings(query);
+            return ((Number) query.uniqueResult()).intValue();
+          }
+        });
+  }
+
   public void setTotalCount(int totalCount) {
     this.totalCount = totalCount;
   }
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/SelectQueryDelegate.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/SelectQueryDelegate.java
index 8b9f9518c8..6f31f7dbaa 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/SelectQueryDelegate.java
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/SelectQueryDelegate.java
@@ -20,6 +20,7 @@ package org.grails.orm.hibernate.query;
 
 import java.util.Collection;
 import java.util.List;
+import jakarta.persistence.LockModeType;
 import org.hibernate.query.QueryFlushMode;
 
 /** {@link HqlQueryDelegate} for HQL SELECT queries backed by {@link org.hibernate.query.Query}. */
@@ -86,6 +87,11 @@ final class SelectQueryDelegate implements HqlQueryDelegate {
     query.setReadOnly(b);
   }
 
+  @Override
+  public void setLockMode(LockModeType lockModeType) {
+    query.setLockMode(lockModeType);
+  }
+
   @Override
   public void setParameterList(String name, Collection<?> values) {
     query.setParameterList(name, values);
diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/query/GrailsHibernateQueryUtilsSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/query/GrailsHibernateQueryUtilsSpec.groovy
index dc9284a771..2227581dd1 100644
--- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/query/GrailsHibernateQueryUtilsSpec.groovy
+++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/query/GrailsHibernateQueryUtilsSpec.groovy
@@ -18,22 +18,16 @@
  */
 package org.grails.orm.hibernate.query
 
-import org.grails.datastore.mapping.model.PersistentEntity
-import org.hibernate.FetchMode
-import org.hibernate.query.Query
 import org.hibernate.query.QueryFlushMode
-import org.springframework.core.convert.ConversionService
 import spock.lang.Specification
 import spock.lang.Unroll
 
 class GrailsHibernateQueryUtilsSpec extends Specification {
 
-    GrailsHibernateQueryUtils queryUtils = new GrailsHibernateQueryUtils()
-
     @Unroll
     def "test convertQueryFlushMode for #input"() {
         expect:
-        queryUtils.convertQueryFlushMode(input) == expected
+        HibernateHqlQuery.convertQueryFlushMode(input) == expected
 
         where:
         input               | expected
@@ -44,76 +38,4 @@ class GrailsHibernateQueryUtilsSpec extends Specification {
         null                | QueryFlushMode.DEFAULT
         "INVALID"           | QueryFlushMode.NO_FLUSH // defaults to COMMIT which is NO_FLUSH
     }
-
-    @Unroll
-    def "test getFetchMode for #input"() {
-        expect:
-        queryUtils.getFetchMode(input) == expected
-
-        where:
-        input               | expected
-        "JOIN"              | FetchMode.JOIN
-        "eager"             | FetchMode.JOIN
-        "SELECT"            | FetchMode.SELECT
-        "lazy"              | FetchMode.SELECT
-        "default"           | FetchMode.DEFAULT
-        null                | FetchMode.DEFAULT
-    }
-
-    def "test populateArgumentsForCriteria for Query"() {
-        given:
-        PersistentEntity entity = Mock(PersistentEntity)
-        Query query = Mock(Query)
-        ConversionService conversionService = Mock(ConversionService)
-        
-        Map argMap = [
-            max: 10,
-            offset: 20,
-            fetchSize: 50,
-            timeout: 30,
-            readOnly: true,
-            cache: true
-        ]
-
-        entity.getJavaClass() >> Object.class
-        conversionService.convert(10, Integer.class) >> 10
-        conversionService.convert(20, Integer.class) >> 20
-        conversionService.convert(50, Integer.class) >> 50
-        conversionService.convert(30, Integer.class) >> 30
-
-        when:
-        queryUtils.populateArgumentsForCriteria(entity, query, argMap, conversionService)
-
-        then:
-        1 * query.setMaxResults(10)
-        1 * query.setFirstResult(20)
-        1 * query.setFetchSize(50)
-        1 * query.setTimeout(30)
-        1 * query.setReadOnly(true)
-        1 * query.setCacheable(true)
-    }
-
-    def "test populateArgumentsForCriteria for Query with null conversion results"() {
-        given:
-        PersistentEntity entity = Mock(PersistentEntity)
-        Query query = Mock(Query)
-        ConversionService conversionService = Mock(ConversionService)
-        
-        Map argMap = [
-            fetchSize: 50,
-            timeout: 30
-        ]
-
-        entity.getJavaClass() >> Object.class
-        // Simulate conversion returning null
-        conversionService.convert(50, Integer.class) >> null
-        conversionService.convert(30, Integer.class) >> null
-
-        when:
-        queryUtils.populateArgumentsForCriteria(entity, query, argMap, conversionService)
-
-        then:
-        0 * query.setFetchSize(_)
-        0 * query.setTimeout(_)
-    }
 }


(grails-core) 27/34: hibernate7: more CodeNarc

Posted by bo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

borinquenkid pushed a commit to branch 8.0.x-hibernate7-dev
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit d2f1d4273878116a90da2549b0e1ea5a837e8e8e
Author: Walter Duque de Estrada <wb...@mac.com>
AuthorDate: Sat Mar 7 18:58:21 2026 -0600

    hibernate7: more CodeNarc
---
 .../grails/orm/hibernate/cfg/CacheConfig.groovy    |  7 ++--
 .../grails/orm/hibernate/cfg/ColumnConfig.groovy   |  1 +
 .../orm/hibernate/cfg/CompositeIdentity.groovy     |  1 +
 .../hibernate/support/DataSourceFactoryBean.groovy | 42 ----------------------
 4 files changed, 6 insertions(+), 45 deletions(-)

diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/CacheConfig.groovy b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/CacheConfig.groovy
index 5d6f30fda2..f7da3718ef 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/CacheConfig.groovy
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/CacheConfig.groovy
@@ -32,13 +32,14 @@ import org.springframework.validation.DataBinder
 @CompileStatic
 @Builder(builderStrategy = SimpleStrategy, prefix = '')
 class CacheConfig implements Cloneable {
-    static final List USAGE_OPTIONS = ['read-only', 'read-write','nonstrict-read-write','transactional']
+
+    static final List USAGE_OPTIONS = ['read-only', 'read-write', 'nonstrict-read-write', 'transactional']
     static final List INCLUDE_OPTIONS = ['all', 'non-lazy']
 
     /**
      * The cache usage
      */
-    String usage = "read-write"
+    String usage = 'read-write'
     /**
      * Whether caching is enabled
      */
@@ -46,7 +47,7 @@ class CacheConfig implements Cloneable {
     /**
      * What to include in caching
      */
-    String include = "all"
+    String include = 'all'
 
     /**
      * Configures a new CacheConfig instance
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/ColumnConfig.groovy b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/ColumnConfig.groovy
index c7a63d1856..8f2b92c3f0 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/ColumnConfig.groovy
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/ColumnConfig.groovy
@@ -32,6 +32,7 @@ import org.springframework.validation.DataBinder
 @CompileStatic
 @Builder(builderStrategy = SimpleStrategy, prefix = '')
 class ColumnConfig {
+
     /**
      * The column name
      */
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/CompositeIdentity.groovy b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/CompositeIdentity.groovy
index c9613af565..6dc34ca7ac 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/CompositeIdentity.groovy
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/CompositeIdentity.groovy
@@ -35,6 +35,7 @@ import org.hibernate.MappingException
 @Builder(builderStrategy = SimpleStrategy, prefix = '')
 @CompileStatic
 class CompositeIdentity extends Property implements HibernateIdentity {
+
     /**
      * The property names that make up the custom identity
      */
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/support/DataSourceFactoryBean.groovy b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/support/DataSourceFactoryBean.groovy
deleted file mode 100644
index f47bf74f54..0000000000
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/support/DataSourceFactoryBean.groovy
+++ /dev/null
@@ -1,42 +0,0 @@
-package org.grails.orm.hibernate.support
-
-import groovy.transform.CompileStatic
-import org.grails.orm.hibernate.HibernateDatastore
-import org.grails.orm.hibernate.connections.HibernateConnectionSource
-import org.springframework.beans.factory.FactoryBean
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.beans.factory.annotation.Qualifier
-
-import javax.sql.DataSource
-
-/**
- * A factory class to retrieve a {@link javax.sql.DataSource} from the Hibernate datastore
- *
- * @author James Kleeh
- */
-@CompileStatic
-class DataSourceFactoryBean implements FactoryBean<DataSource> {
-
-    HibernateDatastore datastore
-    String connectionName
-
-    DataSourceFactoryBean(HibernateDatastore datastore, String connectionName) {
-        this.datastore = datastore
-        this.connectionName = connectionName
-    }
-
-    @Override
-    DataSource getObject() throws Exception {
-        ((HibernateConnectionSource)datastore.connectionSources.getConnectionSource(connectionName)).dataSource
-    }
-
-    @Override
-    Class<?> getObjectType() {
-        DataSource
-    }
-
-    @Override
-    boolean isSingleton() {
-        true
-    }
-}


(grails-core) 32/34: hibernate7: raw fixes

Posted by bo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

borinquenkid pushed a commit to branch 8.0.x-hibernate7-dev
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit 3b830d07d02876b924b593064754af3892ccb915
Author: Walter Duque de Estrada <wb...@mac.com>
AuthorDate: Sun Mar 8 09:56:44 2026 -0500

    hibernate7:
    raw fixes
---
 .../grails/orm/HibernateCriteriaBuilder.java       | 30 +++++++++++-----------
 .../mapping/query/api/BuildableCriteria.java       | 10 ++++----
 .../datastore/mapping/query/api/Criteria.java      | 24 ++++++++---------
 3 files changed, 32 insertions(+), 32 deletions(-)

diff --git a/grails-data-hibernate7/core/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java b/grails-data-hibernate7/core/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java
index 1464f753e5..99eba287aa 100644
--- a/grails-data-hibernate7/core/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java
+++ b/grails-data-hibernate7/core/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java
@@ -104,6 +104,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
   private Class<?> targetClass;
   private CriteriaQuery<?> criteriaQuery;
   private boolean uniqueResult = false;
+  //TODO Transactional behaviour is currently not supported, but we need to track whether the criteria should participate in a transaction or not
   private boolean participate;
 
   @SuppressWarnings("PMD.AvoidFieldNameMatchingMethodName")
@@ -598,14 +599,13 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
    * @return A Criterion instance
    */
   @Override
-  public Criteria gtAll(
-      String propertyName, @SuppressWarnings("rawtypes") QueryableCriteria propertyValue) {
+  public Criteria gtAll(String propertyName, QueryableCriteria<?> propertyValue) {
     hibernateQuery.gtAll(propertyName, propertyValue);
     return this;
   }
 
   @Override
-  public Criteria gtSome(String propertyName, QueryableCriteria propertyValue) {
+  public Criteria gtSome(String propertyName, QueryableCriteria<?> propertyValue) {
     return this;
   }
 
@@ -615,7 +615,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
   }
 
   @Override
-  public Criteria geSome(String propertyName, QueryableCriteria propertyValue) {
+  public Criteria geSome(String propertyName, QueryableCriteria<?> propertyValue) {
     hibernateQuery.geSome(propertyName, propertyValue);
     return this;
   }
@@ -626,7 +626,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
   }
 
   @Override
-  public Criteria ltSome(String propertyName, QueryableCriteria propertyValue) {
+  public Criteria ltSome(String propertyName, QueryableCriteria<?> propertyValue) {
     hibernateQuery.ltSome(propertyName, propertyValue);
     return this;
   }
@@ -637,7 +637,7 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
   }
 
   @Override
-  public Criteria leSome(String propertyName, QueryableCriteria propertyValue) {
+  public Criteria leSome(String propertyName, QueryableCriteria<?> propertyValue) {
     hibernateQuery.leSome(propertyName, propertyValue);
     return this;
   }
@@ -823,19 +823,19 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
   }
 
   @Override
-  public Criteria and(Closure callable) {
+  public Criteria and(Closure<?> callable) {
     hibernateQuery.and(callable);
     return this;
   }
 
   @Override
-  public Criteria or(Closure callable) {
+  public Criteria or(Closure<?> callable) {
     hibernateQuery.or(callable);
     return this;
   }
 
   @Override
-  public Criteria not(Closure callable) {
+  public Criteria not(Closure<?> callable) {
     hibernateQuery.not(callable);
     return this;
   }
@@ -1120,12 +1120,12 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
   }
 
   @Override
-  public Object list(@DelegatesTo(Criteria.class) Closure c) {
+  public Object list(@DelegatesTo(Criteria.class) Closure<?> c) {
     hibernateQuery.setDetachedCriteria(new DetachedCriteria<>(targetClass));
     return invokeMethod(CriteriaMethods.LIST_CALL.getName(), new Object[] {c});
   }
 
-  public List list() {
+  public List<?> list() {
     return hibernateQuery.list();
   }
 
@@ -1134,23 +1134,23 @@ public class HibernateCriteriaBuilder extends GroovyObjectSupport implements Bui
   }
 
   @Override
-  public Object list(Map params, @DelegatesTo(Criteria.class) Closure c) {
+  public Object list(Map<String,?> params, @DelegatesTo(Criteria.class) Closure<?> c) {
     hibernateQuery.setDetachedCriteria(new DetachedCriteria<>(targetClass));
     return invokeMethod(CriteriaMethods.LIST_CALL.getName(), new Object[] {params, c});
   }
 
   @Override
-  public Object listDistinct(@DelegatesTo(Criteria.class) Closure c) {
+  public Object listDistinct(@DelegatesTo(Criteria.class) Closure<?> c) {
     return invokeMethod(CriteriaMethods.LIST_DISTINCT_CALL.getName(), new Object[] {c});
   }
 
   @Override
-  public Object get(@DelegatesTo(Criteria.class) Closure c) {
+  public Object get(@DelegatesTo(Criteria.class) Closure<?> c) {
     return invokeMethod(CriteriaMethods.GET_CALL.getName(), new Object[] {c});
   }
 
   @Override
-  public Object scroll(@DelegatesTo(Criteria.class) Closure c) {
+  public Object scroll(@DelegatesTo(Criteria.class) Closure<?> c) {
     return invokeMethod(CriteriaMethods.SCROLL_CALL.getName(), new Object[] {c});
   }
 
diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/api/BuildableCriteria.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/api/BuildableCriteria.java
index b279ebb76d..4e97503529 100644
--- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/api/BuildableCriteria.java
+++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/api/BuildableCriteria.java
@@ -85,7 +85,7 @@ public interface BuildableCriteria extends Criteria {
      *
      * @return The result
      */
-    Object list(@DelegatesTo(Criteria.class) Closure closure);
+    Object list(@DelegatesTo(Criteria.class) Closure<?> closure);
 
     /**
      * Defines and executes a list query in a single call. Example: Foo.createCriteria().list { }
@@ -95,7 +95,7 @@ public interface BuildableCriteria extends Criteria {
      *
      * @return The result
      */
-    Object list(Map params, @DelegatesTo(Criteria.class) Closure closure);
+    Object list(Map<String,?> params, @DelegatesTo(Criteria.class) Closure<?> closure);
 
     /**
      * Defines and executes a list distinct query in a single call. Example: Foo.createCriteria().listDistinct { }
@@ -103,7 +103,7 @@ public interface BuildableCriteria extends Criteria {
      *
      * @return The result
      */
-    Object listDistinct(@DelegatesTo(Criteria.class) Closure closure);
+    Object listDistinct(@DelegatesTo(Criteria.class) Closure<?> closure);
 
     /**
      * Defines and executes a scroll query in a single call. Example: Foo.createCriteria().scroll { }
@@ -112,7 +112,7 @@ public interface BuildableCriteria extends Criteria {
      *
      * @return A scrollable result set
      */
-    Object scroll(@DelegatesTo(Criteria.class) Closure closure);
+    Object scroll(@DelegatesTo(Criteria.class) Closure<?> closure);
 
     /**
      * Defines and executes a get query ( a single result) in a single call. Example: Foo.createCriteria().get { }
@@ -121,5 +121,5 @@ public interface BuildableCriteria extends Criteria {
      *
      * @return A single result
      */
-    Object get(@DelegatesTo(Criteria.class) Closure closure);
+    Object get(@DelegatesTo(Criteria.class) Closure<?> closure);
 }
diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/api/Criteria.java b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/api/Criteria.java
index 14df94f6b0..51483e7ae8 100644
--- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/api/Criteria.java
+++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/api/Criteria.java
@@ -214,21 +214,21 @@ public interface Criteria {
      *
      * @return This criteria
      */
-    Criteria and(@DelegatesTo(Criteria.class) Closure callable);
+    Criteria and(@DelegatesTo(Criteria.class) Closure<?> callable);
 
     /**
      * Creates a logical disjunction
      * @param callable The closure
      * @return This criteria
      */
-    Criteria or(@DelegatesTo(Criteria.class) Closure callable);
+    Criteria or(@DelegatesTo(Criteria.class) Closure<?> callable);
 
     /**
      * Creates a logical negation
      * @param callable The closure
      * @return This criteria
      */
-    Criteria not(@DelegatesTo(Criteria.class) Closure callable);
+    Criteria not(@DelegatesTo(Criteria.class) Closure<?> callable);
 
     /**
      * Creates an "in" Criterion based on the specified property name and list of values
@@ -536,7 +536,7 @@ public interface Criteria {
      *
      * @return This Criteria instance
      */
-    Criteria eqAll(String propertyName, QueryableCriteria propertyValue);
+    Criteria eqAll(String propertyName, QueryableCriteria<?> propertyValue);
 
     /**
      * Creates a subquery criterion that ensures the given property is greater than all the given returned values
@@ -546,7 +546,7 @@ public interface Criteria {
      *
      * @return This Criteria instance
      */
-    Criteria gtAll(String propertyName, QueryableCriteria propertyValue);
+    Criteria gtAll(String propertyName, QueryableCriteria<?> propertyValue);
 
     /**
      * Creates a subquery criterion that ensures the given property is less than all the given returned values
@@ -556,7 +556,7 @@ public interface Criteria {
      *
      * @return This Criteria instance
      */
-    Criteria ltAll(String propertyName, QueryableCriteria propertyValue);
+    Criteria ltAll(String propertyName, QueryableCriteria<?> propertyValue);
 
     /**
      * Creates a subquery criterion that ensures the given property is greater than all the given returned values
@@ -566,7 +566,7 @@ public interface Criteria {
      *
      * @return This Criteria instance
      */
-    Criteria geAll(String propertyName, QueryableCriteria propertyValue);
+    Criteria geAll(String propertyName, QueryableCriteria<?> propertyValue);
 
     /**
      * Creates a subquery criterion that ensures the given property is less than all the given returned values
@@ -576,7 +576,7 @@ public interface Criteria {
      *
      * @return This Criteria instance
      */
-    Criteria leAll(String propertyName, QueryableCriteria propertyValue);
+    Criteria leAll(String propertyName, QueryableCriteria<?> propertyValue);
 
     /**
      * Creates a subquery criterion that ensures the given property is greater than some of the given values
@@ -586,7 +586,7 @@ public interface Criteria {
      *
      * @return This Criteria instance
      */
-    Criteria gtSome(String propertyName, QueryableCriteria propertyValue);
+    Criteria gtSome(String propertyName, QueryableCriteria<?> propertyValue);
 
     /**
      * Creates a subquery criterion that ensures the given property is greater than some of the given values
@@ -606,7 +606,7 @@ public interface Criteria {
      *
      * @return This Criteria instance
      */
-    Criteria geSome(String propertyName, QueryableCriteria propertyValue);
+    Criteria geSome(String propertyName, QueryableCriteria<?> propertyValue);
 
     /**
      * Creates a subquery criterion that ensures the given property is greater than or equal to some of the given values
@@ -626,7 +626,7 @@ public interface Criteria {
      *
      * @return This Criteria instance
      */
-    Criteria ltSome(String propertyName, QueryableCriteria propertyValue);
+    Criteria ltSome(String propertyName, QueryableCriteria<?> propertyValue);
 
     /**
      * Creates a subquery criterion that ensures the given property is less than some of the given values
@@ -646,7 +646,7 @@ public interface Criteria {
      *
      * @return This Criteria instance
      */
-    Criteria leSome(String propertyName, QueryableCriteria propertyValue);
+    Criteria leSome(String propertyName, QueryableCriteria<?> propertyValue);
 
     /**
      * Creates a subquery criterion that ensures the given property is less than or equal to some of the given values


(grails-core) 25/34: hibernate7: more CodeNarc

Posted by bo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

borinquenkid pushed a commit to branch 8.0.x-hibernate7-dev
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit 2334ce725b41e6c9a07bec0060ee8fdab3e94cbc
Author: Walter Duque de Estrada <wb...@mac.com>
AuthorDate: Sat Mar 7 17:47:51 2026 -0600

    hibernate7: more CodeNarc
---
 .../{orm => gorm}/hibernate/HibernateEntity.groovy | 20 ++++----
 .../HibernateConnectionSourceSettings.groovy       | 56 +++++++---------------
 ...HibernateConnectionSourceSettingsBuilder.groovy | 17 +++----
 ...rnateDatastoreConnectionSourcesRegistrar.groovy |  9 ++--
 4 files changed, 41 insertions(+), 61 deletions(-)

diff --git a/grails-data-hibernate7/core/src/main/groovy/grails/orm/hibernate/HibernateEntity.groovy b/grails-data-hibernate7/core/src/main/groovy/grails/gorm/hibernate/HibernateEntity.groovy
similarity index 80%
rename from grails-data-hibernate7/core/src/main/groovy/grails/orm/hibernate/HibernateEntity.groovy
rename to grails-data-hibernate7/core/src/main/groovy/grails/gorm/hibernate/HibernateEntity.groovy
index 8519635f20..76dc35c1ed 100644
--- a/grails-data-hibernate7/core/src/main/groovy/grails/orm/hibernate/HibernateEntity.groovy
+++ b/grails-data-hibernate7/core/src/main/groovy/grails/gorm/hibernate/HibernateEntity.groovy
@@ -24,7 +24,7 @@ trait HibernateEntity<D> extends GormEntity<D> {
      */
     @Generated
     static List<D> findAllWithNativeSql(CharSequence sql) {
-        currentHibernateStaticApi().findAllWithNativeSql sql, Collections.emptyMap()
+        HibernateEntity.currentHibernateStaticApi().findAllWithNativeSql sql, Collections.emptyMap()
     }
 
     /**
@@ -36,7 +36,7 @@ trait HibernateEntity<D> extends GormEntity<D> {
      */
     @Generated
     static D findWithNativeSql(CharSequence sql) {
-        currentHibernateStaticApi().findWithNativeSql(sql, Collections.emptyMap())
+        HibernateEntity.currentHibernateStaticApi().findWithNativeSql(sql, Collections.emptyMap())
     }
 
     /**
@@ -49,7 +49,7 @@ trait HibernateEntity<D> extends GormEntity<D> {
      */
     @Generated
     static List<D> findAllWithNativeSql(CharSequence sql, Map args) {
-        currentHibernateStaticApi().findAllWithNativeSql sql, args
+        HibernateEntity.currentHibernateStaticApi().findAllWithNativeSql sql, args
     }
 
     /**
@@ -62,7 +62,7 @@ trait HibernateEntity<D> extends GormEntity<D> {
      */
     @Generated
     static D findWithNativeSql(CharSequence sql, Map args) {
-        currentHibernateStaticApi().findWithNativeSql(sql, args)
+        HibernateEntity.currentHibernateStaticApi().findWithNativeSql(sql, args)
     }
 
     /**
@@ -71,7 +71,7 @@ trait HibernateEntity<D> extends GormEntity<D> {
     @Deprecated
     @Generated
     static List<D> findAllWithSql(CharSequence sql) {
-        currentHibernateStaticApi().findAllWithNativeSql sql, Collections.emptyMap()
+        HibernateEntity.currentHibernateStaticApi().findAllWithNativeSql sql, Collections.emptyMap()
     }
 
     /**
@@ -80,7 +80,7 @@ trait HibernateEntity<D> extends GormEntity<D> {
     @Deprecated
     @Generated
     static D findWithSql(CharSequence sql) {
-        currentHibernateStaticApi().findWithNativeSql(sql, Collections.emptyMap())
+        HibernateEntity.currentHibernateStaticApi().findWithNativeSql(sql, Collections.emptyMap())
     }
 
     /**
@@ -89,7 +89,7 @@ trait HibernateEntity<D> extends GormEntity<D> {
     @Deprecated
     @Generated
     static List<D> findAllWithSql(CharSequence sql, Map args) {
-        currentHibernateStaticApi().findAllWithNativeSql sql, args
+        HibernateEntity.currentHibernateStaticApi().findAllWithNativeSql sql, args
     }
 
     /**
@@ -98,11 +98,11 @@ trait HibernateEntity<D> extends GormEntity<D> {
     @Deprecated
     @Generated
     static D findWithSql(CharSequence sql, Map args) {
-        currentHibernateStaticApi().findWithNativeSql(sql, args)
+        HibernateEntity.currentHibernateStaticApi().findWithNativeSql(sql, args)
     }
 
     @Generated
     private static HibernateGormStaticApi currentHibernateStaticApi() {
-        (HibernateGormStaticApi)GormEnhancer.findStaticApi(this)
+        (HibernateGormStaticApi) GormEnhancer.findStaticApi(this)
     }
-}
\ No newline at end of file
+}
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceSettings.groovy b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceSettings.groovy
index f3a18c27aa..bd8a55da4d 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceSettings.groovy
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceSettings.groovy
@@ -10,9 +10,8 @@ import org.grails.datastore.gorm.jdbc.connections.DataSourceSettings
 import org.grails.orm.hibernate.dirty.GrailsEntityDirtinessStrategy
 import org.grails.orm.hibernate.support.ClosureEventTriggeringInterceptor
 import org.hibernate.CustomEntityDirtinessStrategy
-import org.hibernate.boot.model.naming.CamelCaseToUnderscoresNamingStrategy
+import org.hibernate.boot.model.naming.PhysicalNamingStrategySnakeCaseImpl
 import org.hibernate.boot.model.naming.PhysicalNamingStrategy
-import org.hibernate.cfg.AvailableSettings
 import org.hibernate.cfg.Configuration
 import org.springframework.core.io.Resource
 
@@ -47,12 +46,11 @@ class HibernateConnectionSourceSettings extends ConnectionSourceSettings {
      */
     Properties toProperties() {
         Properties properties = new Properties()
-        properties.putAll( dataSource.toHibernateProperties() )
-        properties.putAll( hibernate.toProperties() )
+        properties.putAll(dataSource.toHibernateProperties())
+        properties.putAll(hibernate.toProperties())
         return properties
     }
 
-
     @Builder(builderStrategy = SimpleStrategy, prefix = '')
     @AutoClone
     static class HibernateSettings extends LinkedHashMap<String, String> {
@@ -80,7 +78,6 @@ class HibernateConnectionSourceSettings extends ConnectionSourceSettings {
          */
         FlushSettings flush = new FlushSettings()
 
-
         /**
          * The configuration class
          */
@@ -89,7 +86,7 @@ class HibernateConnectionSourceSettings extends ConnectionSourceSettings {
         /**
          * The naming strategy
          */
-        Class<? extends PhysicalNamingStrategy> naming_strategy = CamelCaseToUnderscoresNamingStrategy
+        Class<? extends PhysicalNamingStrategy> naming_strategy = PhysicalNamingStrategySnakeCaseImpl
 
         /**
          *
@@ -191,8 +188,8 @@ class HibernateConnectionSourceSettings extends ConnectionSourceSettings {
         Properties additionalProperties = new Properties()
 
         @CompileStatic
-        Map<String, Object> toHibernateEventListeners(ClosureEventTriggeringInterceptor eventTriggeringInterceptor) {
-            if(eventTriggeringInterceptor != null) {
+        static Map<String, Object> toHibernateEventListeners(ClosureEventTriggeringInterceptor eventTriggeringInterceptor) {
+            if (eventTriggeringInterceptor != null) {
                 return [
 //                    'save': eventTriggeringInterceptor,
 //                    'save-update': eventTriggeringInterceptor,
@@ -206,7 +203,7 @@ class HibernateConnectionSourceSettings extends ConnectionSourceSettings {
                     'post-update': eventTriggeringInterceptor,
                     'pre-delete': eventTriggeringInterceptor,
                     'post-delete': eventTriggeringInterceptor
-                ] as Map<String,Object>
+                ] as Map<String, Object>
             }
             return Collections.emptyMap()
         }
@@ -219,11 +216,11 @@ class HibernateConnectionSourceSettings extends ConnectionSourceSettings {
         @CompileStatic
         Properties toProperties() {
             Properties props = new Properties()
-            if(naming_strategy != null) {
-                props.put("hibernate.naming_strategy".toString(), naming_strategy.name)
+            if (naming_strategy != null) {
+                props.put('hibernate.naming_strategy'.toString(), naming_strategy.name)
             }
-            if(configClass != null) {
-                props.put("hibernate.config_class".toString(), configClass.name)
+            if (configClass != null) {
+                props.put('hibernate.config_class'.toString(), configClass.name)
             }
             props.put('hibernate.use_query_cache', String.valueOf(cache.queries))
             props.put('hibernate.jpa.compliance.cascade', String.valueOf(jpa.compliance.cascade))
@@ -232,26 +229,11 @@ class HibernateConnectionSourceSettings extends ConnectionSourceSettings {
                 props.put('hibernate.entity_dirtiness_strategy', entity_dirtiness_strategy.name)
             }
 
-            // Hibernate 5.1/5.2: manually enforce connection release mode ON_CLOSE (the former default)
-            try {
-                // Try Hibernate 5.2
-                AvailableSettings.class.getField("CONNECTION_HANDLING")
-                props.put("hibernate.connection.handling_mode", "DELAYED_ACQUISITION_AND_HOLD")
-            }
-            catch (NoSuchFieldException ex) {
-                // Try Hibernate 5.1
-                try {
-                    AvailableSettings.class.getField("ACQUIRE_CONNECTIONS")
-                    props.put("hibernate.connection.release_mode", "ON_CLOSE")
-                }
-                catch (NoSuchFieldException ex2) {
-                    // on Hibernate 5.0.x or lower - no need to change the default there
-                }
-            }
+            props.put('hibernate.connection.handling_mode', 'DELAYED_ACQUISITION_AND_HOLD')
 
-            String prefix = "hibernate"
-            props.putAll( additionalProperties )
-            populateProperties(props, this,prefix)
+            String prefix = 'hibernate'
+            props.putAll(additionalProperties)
+            populateProperties(props, this, prefix)
             return props
         }
 
@@ -259,8 +241,8 @@ class HibernateConnectionSourceSettings extends ConnectionSourceSettings {
         protected void populateProperties(Properties props, Map current, String prefix) {
             for (key in current.keySet()) {
                 def value = current.get(key)
-                if(value instanceof Map) {
-                    populateProperties(props, (Map)value, "${prefix}.$key")
+                if (value instanceof Map) {
+                    populateProperties(props, (Map) value, "${prefix}.$key")
                 }
                 else {
                     props.put("$prefix.$key".toString(), value)
@@ -328,14 +310,12 @@ class HibernateConnectionSourceSettings extends ConnectionSourceSettings {
         @Builder(builderStrategy = SimpleStrategy, prefix = '')
         @AutoClone
         static class JpaSettings {
-            JpaComplianceSettings compliance = new JpaComplianceSettings();
+            JpaComplianceSettings compliance = new JpaComplianceSettings()
         }
 
         @Builder(builderStrategy = SimpleStrategy, prefix = '')
         static class JpaComplianceSettings {
             boolean cascade = true
         }
-
-
     }
 }
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceSettingsBuilder.groovy b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceSettingsBuilder.groovy
index 8f832be811..4afd817657 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceSettingsBuilder.groovy
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceSettingsBuilder.groovy
@@ -13,31 +13,32 @@ import org.springframework.core.env.PropertyResolver
  */
 @CompileStatic
 class HibernateConnectionSourceSettingsBuilder extends ConfigurationBuilder<HibernateConnectionSourceSettings, HibernateConnectionSourceSettings> {
+
     HibernateConnectionSourceSettings fallBackHibernateSettings
 
-    HibernateConnectionSourceSettingsBuilder(PropertyResolver propertyResolver, String configurationPrefix = "", ConnectionSourceSettings fallBackConfiguration = null) {
+    HibernateConnectionSourceSettingsBuilder(PropertyResolver propertyResolver, String configurationPrefix = '', ConnectionSourceSettings fallBackConfiguration = null) {
         super(propertyResolver, configurationPrefix, fallBackConfiguration)
 
-        if(fallBackConfiguration instanceof HibernateConnectionSourceSettings) {
-            fallBackHibernateSettings = (HibernateConnectionSourceSettings)fallBackConfiguration
+        if (fallBackConfiguration instanceof HibernateConnectionSourceSettings) {
+            fallBackHibernateSettings = (HibernateConnectionSourceSettings) fallBackConfiguration
         }
     }
 
     @Override
     protected HibernateConnectionSourceSettings createBuilder() {
         def settings = new HibernateConnectionSourceSettings()
-        if(fallBackHibernateSettings != null) {
-            settings.getHibernate().putAll( fallBackHibernateSettings.getHibernate() )
+        if (fallBackHibernateSettings != null) {
+            settings.getHibernate().putAll(fallBackHibernateSettings.getHibernate())
         }
         return settings
     }
 
     @Override
     HibernateConnectionSourceSettings build() {
-        HibernateConnectionSourceSettings finalSettings = (HibernateConnectionSourceSettings)super.build()
-        Map orgHibernateProperties = propertyResolver.getProperty("org.hibernate", Map.class, Collections.emptyMap())
+        HibernateConnectionSourceSettings finalSettings = (HibernateConnectionSourceSettings) super.build()
+        Map orgHibernateProperties = propertyResolver.getProperty('org.hibernate', Map, Collections.emptyMap())
         Properties additionalProperties = finalSettings.getHibernate().getAdditionalProperties()
-        for(key in orgHibernateProperties.keySet()) {
+        for (key in orgHibernateProperties.keySet()) {
             additionalProperties.put("org.hibernate.$key".toString(), orgHibernateProperties.get(key))
         }
         return finalSettings
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/support/HibernateDatastoreConnectionSourcesRegistrar.groovy b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/support/HibernateDatastoreConnectionSourcesRegistrar.groovy
index 167c741c3a..bd0e26db3a 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/support/HibernateDatastoreConnectionSourcesRegistrar.groovy
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/support/HibernateDatastoreConnectionSourcesRegistrar.groovy
@@ -17,7 +17,6 @@ import org.springframework.transaction.PlatformTransactionManager
 
 import javax.sql.DataSource
 
-
 /**
  * A factory bean that looks up a datastore by connection name
  *
@@ -35,12 +34,12 @@ class HibernateDatastoreConnectionSourcesRegistrar implements BeanDefinitionRegi
 
     @Override
     void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
-        for(String dataSourceName in dataSourceNames) {
+        for (String dataSourceName in dataSourceNames) {
             boolean isDefault = dataSourceName == ConnectionSource.DEFAULT || dataSourceName == Settings.SETTING_DATASOURCE
-            boolean shouldConfigureDataSourceBean = GrailsVersion.isAtLeastMajorMinor(3,3)
+            boolean shouldConfigureDataSourceBean = GrailsVersion.isAtLeastMajorMinor(3, 3)
             String dataSourceBeanName = isDefault ? Settings.SETTING_DATASOURCE : "${Settings.SETTING_DATASOURCE}_$dataSourceName"
 
-            if(!registry.containsBeanDefinition(dataSourceBeanName) && shouldConfigureDataSourceBean) {
+            if (!registry.containsBeanDefinition(dataSourceBeanName) && shouldConfigureDataSourceBean) {
                 def dataSourceBean = new RootBeanDefinition()
                 dataSourceBean.setTargetType(DataSource)
                 dataSourceBean.setBeanClass(InstanceFactoryBean)
@@ -53,7 +52,7 @@ class HibernateDatastoreConnectionSourcesRegistrar implements BeanDefinitionRegi
                 registry.registerBeanDefinition(dataSourceBeanName, dataSourceBean)
             }
 
-            if(!isDefault) {
+            if (!isDefault) {
                 String suffix = '_' + dataSourceName
                 String sessionFactoryName = "sessionFactory$suffix"
                 String transactionManagerBeanName = "transactionManager$suffix"


(grails-core) 19/34: hibernate7: more Codenarc

Posted by bo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

borinquenkid pushed a commit to branch 8.0.x-hibernate7-dev
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit ada4f05255c135416ec4ec3aa7f360a24f17af40
Author: Walter Duque de Estrada <wb...@mac.com>
AuthorDate: Sat Mar 7 12:43:43 2026 -0600

    hibernate7: more Codenarc
---
 .../org/grails/orm/hibernate/cfg/Identity.groovy   |  1 +
 .../grails/orm/hibernate/cfg/InstanceProxy.groovy  |  5 +--
 .../hibernate/HibernateMappingBuilder.groovy       | 31 ++++++++--------
 .../hibernate/support/HibernateRuntimeUtils.groovy | 41 +++++++++++++---------
 .../mapping/HibernateMappingBuilderTests.groovy    | 11 ++++++
 5 files changed, 55 insertions(+), 34 deletions(-)

diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/Identity.groovy b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/Identity.groovy
index 45039669ce..c4607aef98 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/Identity.groovy
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/Identity.groovy
@@ -35,6 +35,7 @@ import org.grails.orm.hibernate.cfg.domainbinding.generator.GrailsSequenceGenera
 @CompileStatic
 @Builder(builderStrategy = SimpleStrategy, prefix = '')
 class Identity extends Property implements HibernateIdentity {
+
     /**
      * The generator to use
      */
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/InstanceProxy.groovy b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/InstanceProxy.groovy
index 5a544c0795..b7c9d0ec10 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/InstanceProxy.groovy
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/InstanceProxy.groovy
@@ -22,6 +22,7 @@ import org.grails.orm.hibernate.HibernateGormValidationApi
 
 @CompileStatic
 class InstanceProxy {
+
     protected instance
     protected HibernateGormValidationApi validateApi
     protected HibernateGormInstanceApi instanceApi
@@ -43,10 +44,10 @@ class InstanceProxy {
 
     def invokeMethod(String name, args) {
         if (validateMethods.contains(name)) {
-            validateApi.invokeMethod(name, prependToArray(instance, (Object[])args))
+            validateApi.invokeMethod(name, prependToArray(instance, (Object[]) args))
         }
         else {
-            instanceApi.invokeMethod(name, prependToArray(instance, (Object[])args))
+            instanceApi.invokeMethod(name, prependToArray(instance, (Object[]) args))
         }
     }
 
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateMappingBuilder.groovy b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateMappingBuilder.groovy
index f97273b707..1ecfed48dd 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateMappingBuilder.groovy
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/HibernateMappingBuilder.groovy
@@ -161,7 +161,7 @@ class HibernateMappingBuilder implements MappingConfigurationBuilder<Mapping, Pr
     }
 
     void order(String direction) {
-        if ("desc".equalsIgnoreCase(direction) || "asc".equalsIgnoreCase(direction)) {
+        if ('desc'.equalsIgnoreCase(direction) || 'asc'.equalsIgnoreCase(direction)) {
             SortConfig sc = (SortConfig) mapping.getSort()
             sc.direction = direction
         }
@@ -269,7 +269,7 @@ class HibernateMappingBuilder implements MappingConfigurationBuilder<Mapping, Pr
             }
         }
         if (!args.composite && args) {
-            handlePropertyInternal("id", args, null)
+            handlePropertyInternal('id', args, null)
         }
     }
 
@@ -322,6 +322,7 @@ class HibernateMappingBuilder implements MappingConfigurationBuilder<Mapping, Pr
         Object orderVal = namedArgs.order
         if (orderVal != null) property.order = orderVal.toString()
         if (namedArgs.batchSize instanceof Integer) property.batchSize = (Integer) namedArgs.batchSize
+        if (namedArgs.batchSize instanceof Integer) property.batchSize = (Integer) namedArgs.batchSize
         if (namedArgs.ignoreNotFound instanceof Boolean) property.ignoreNotFound = (Boolean) namedArgs.ignoreNotFound
         if (namedArgs.params instanceof Map) {
             Properties typeProps = new Properties()
@@ -345,8 +346,8 @@ class HibernateMappingBuilder implements MappingConfigurationBuilder<Mapping, Pr
 
         if (namedArgs.fetch) {
             String fetchStr = namedArgs.fetch.toString()
-            if (fetchStr.equalsIgnoreCase("join")) property.fetch = FetchMode.JOIN
-            else if (fetchStr.equalsIgnoreCase("select")) property.fetch = FetchMode.SELECT
+            if (fetchStr.equalsIgnoreCase('join')) property.fetch = FetchMode.JOIN
+            else if (fetchStr.equalsIgnoreCase('select')) property.fetch = FetchMode.SELECT
             else property.fetch = FetchMode.DEFAULT
         }
 
@@ -358,27 +359,27 @@ class HibernateMappingBuilder implements MappingConfigurationBuilder<Mapping, Pr
             ColumnConfig cc = property.columns ? property.columns[0] : new ColumnConfig()
             if (!property.columns) property.columns << cc
 
-            Object colVal = namedArgs["column"]
+            Object colVal = namedArgs['column']
             if (colVal) cc.name = colVal.toString()
-            Object sqlTypeVal = namedArgs["sqlType"]
+            Object sqlTypeVal = namedArgs['sqlType']
             if (sqlTypeVal) cc.sqlType = sqlTypeVal.toString()
-            Object enumTypeVal = namedArgs["enumType"]
+            Object enumTypeVal = namedArgs['enumType']
             if (enumTypeVal) cc.enumType = enumTypeVal.toString()
-            Object indexVal = namedArgs["index"]
+            Object indexVal = namedArgs['index']
             if (indexVal) cc.index = indexVal.toString()
-            Object ccUniqueVal = namedArgs["unique"]
+            Object ccUniqueVal = namedArgs['unique']
             if (ccUniqueVal) cc.unique = ccUniqueVal instanceof Boolean ? (Boolean) ccUniqueVal : ccUniqueVal
-            Object readVal = namedArgs["read"]
+            Object readVal = namedArgs['read']
             if (readVal) cc.read = readVal.toString()
-            Object writeVal = namedArgs["write"]
+            Object writeVal = namedArgs['write']
             if (writeVal) cc.write = writeVal.toString()
             Object defaultVal = namedArgs.defaultValue
             if (defaultVal) cc.defaultValue = defaultVal.toString()
             Object commentVal = namedArgs.comment
             if (commentVal) cc.comment = commentVal.toString()
-            if (namedArgs["length"] instanceof Integer) cc.length = (int) (Integer) namedArgs["length"]
-            if (namedArgs["precision"] instanceof Integer) cc.precision = (int) (Integer) namedArgs["precision"]
-            if (namedArgs["scale"] instanceof Integer) cc.scale = (int) (Integer) namedArgs["scale"]
+            if (namedArgs['length'] instanceof Integer) cc.length = (int) (Integer) namedArgs['length']
+            if (namedArgs['precision'] instanceof Integer) cc.precision = (int) (Integer) namedArgs['precision']
+            if (namedArgs['scale'] instanceof Integer) cc.scale = (int) (Integer) namedArgs['scale']
 
             Object joinTableVal = namedArgs.joinTable
             if (joinTableVal instanceof String) {
@@ -493,4 +494,4 @@ class HibernateMappingBuilder implements MappingConfigurationBuilder<Mapping, Pr
             handlePropertyInternal(name, namedArgs, sub)
         }
     }
-}
\ No newline at end of file
+}
diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/support/HibernateRuntimeUtils.groovy b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/support/HibernateRuntimeUtils.groovy
index 7c6b39223a..89ae922716 100644
--- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/support/HibernateRuntimeUtils.groovy
+++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/support/HibernateRuntimeUtils.groovy
@@ -17,6 +17,7 @@ import org.grails.datastore.mapping.model.config.GormProperties
 import org.grails.datastore.mapping.model.types.Association
 import org.grails.datastore.mapping.model.types.OneToOne
 import org.grails.datastore.mapping.validation.ValidationErrors
+
 /**
  * Utility methods used at runtime by the GORM for Hibernate implementation
  *
@@ -26,14 +27,15 @@ import org.grails.datastore.mapping.validation.ValidationErrors
 @CompileStatic
 class HibernateRuntimeUtils {
 
-    private static final String DYNAMIC_FILTER_ENABLER = "dynamicFilterEnabler"
+    private static final String DYNAMIC_FILTER_ENABLER = 'dynamicFilterEnabler'
 
-    @SuppressWarnings("rawtypes")
+    @SuppressWarnings('rawtypes')
     static void enableDynamicFilterEnablerIfPresent(SessionFactory sessionFactory, Session session) {
         if (sessionFactory != null && session != null) {
             final Set definedFilterNames = sessionFactory.getDefinedFilterNames()
-            if (definedFilterNames != null && definedFilterNames.contains(DYNAMIC_FILTER_ENABLER))
+            if (definedFilterNames != null && definedFilterNames.contains(DYNAMIC_FILTER_ENABLER)) {
                 session.enableFilter(DYNAMIC_FILTER_ENABLER) // work around for HHH-2624
+            }
         }
     }
 
@@ -52,11 +54,11 @@ class HibernateRuntimeUtils {
 
         def errors = new ValidationErrors(target)
 
-        Errors originalErrors = isGormValidateable ? ((GormValidateable)target).getErrors() : (Errors) metaClass.getProperty(target, GormProperties.ERRORS)
+        Errors originalErrors = isGormValidateable ? ((GormValidateable) target).getErrors() : (Errors) metaClass.getProperty(target, GormProperties.ERRORS)
         // Copy binding failures and any existing object-level errors
         for (Object o in originalErrors.allErrors) {
             if (o instanceof FieldError) {
-                FieldError fe = (FieldError)o
+                FieldError fe = (FieldError) o
                 if (fe.isBindingFailure()) {
                     errors.addError(new FieldError(fe.getObjectName(),
                             fe.field,
@@ -66,13 +68,14 @@ class HibernateRuntimeUtils {
                             fe.arguments,
                             fe.defaultMessage))
                 }
-            } else {
+            }
+            else {
                 errors.addError((ObjectError) o)
             }
         }
 
-        if(isGormValidateable) {
-            ((GormValidateable)target).setErrors(errors)
+        if (isGormValidateable) {
+            ((GormValidateable) target).setErrors(errors)
         }
         else {
             metaClass.setProperty(target, GormProperties.ERRORS, errors)
@@ -82,21 +85,19 @@ class HibernateRuntimeUtils {
 
     static void autoAssociateBidirectionalOneToOnes(PersistentEntity entity, Object target) {
         def mappingContext = entity.mappingContext
-        for (Association association :  entity.associations) {
+        for (Association association : entity.associations) {
             if (!(association instanceof OneToOne) || !association.bidirectional || !association.owningSide) {
                 continue
             }
 
             def propertyName = association.name
 
-
             def otherSide = association.inverseSide
 
             if (otherSide == null) {
                 continue
             }
 
-
             def entityReflector = mappingContext.getEntityReflector(entity)
             Object inverseObject = entityReflector.getProperty(target, propertyName)
             if (inverseObject == null) {
@@ -125,22 +126,28 @@ class HibernateRuntimeUtils {
                 if (value instanceof Number && (targetType == Long || targetType == Integer)) {
                     if (targetType == Long) {
                         value = ((Number) value).toLong()
-                    } else {
+                    }
+                    else {
                         value = ((Number) value).toInteger()
                     }
-                } else if (value instanceof String && Number.isAssignableFrom(targetType)) {
+                }
+                else if (value instanceof String && Number.isAssignableFrom(targetType)) {
                     String strValue = value.trim()
                     if (targetType == Long) {
                         value = Long.parseLong(strValue)
-                    } else if (targetType == Integer) {
+                    }
+                    else if (targetType == Integer) {
                         value = Integer.parseInt(strValue)
-                    } else {
+                    }
+                    else {
                         value = StringGroovyMethods.asType(strValue, targetType as Class<Object>)
                     }
-                } else {
+                }
+                else {
                     value = conversionService.convert(value, targetType)
                 }
-            } catch (ignored) {
+            }
+            catch (ignored) {
                 // ignore
             }
         }
diff --git a/grails-data-hibernate7/core/src/test/groovy/grails/gorm/hibernate/mapping/HibernateMappingBuilderTests.groovy b/grails-data-hibernate7/core/src/test/groovy/grails/gorm/hibernate/mapping/HibernateMappingBuilderTests.groovy
index 3e6b9129d9..2e34e104fa 100644
--- a/grails-data-hibernate7/core/src/test/groovy/grails/gorm/hibernate/mapping/HibernateMappingBuilderTests.groovy
+++ b/grails-data-hibernate7/core/src/test/groovy/grails/gorm/hibernate/mapping/HibernateMappingBuilderTests.groovy
@@ -430,6 +430,17 @@ class HibernateMappingBuilderTests {
         assertFalse mapping.tablePerHierarchy
     }
 
+    @Test
+    void testTablePerConcreteClass() {
+        def builder = new HibernateMappingBuilder("Foo")
+        def mapping = builder.evaluate {
+            tablePerConcreteClass true
+        }
+
+        assertTrue mapping.tablePerConcreteClass
+        assertFalse mapping.tablePerHierarchy
+    }
+
     @Test
     void testAutoTimeStamp() {
         def builder = new HibernateMappingBuilder("Foo")