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 <[email protected]>
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(_)
-    }
 }

Reply via email to