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

jamesfredley pushed a commit to branch test/h7-functional-coverage
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit 6d0aaa5241b3b771655324baf6f541031baff21e
Author: James Fredley <[email protected]>
AuthorDate: Thu Jun 11 13:59:13 2026 -0400

    Apply Hibernate 7 HQL query settings consistently
    
    Assisted-by: Hephaestus:openai/gpt-5.5
---
 .../orm/hibernate/query/HqlQueryMethods.java       | 37 +++++++++++++++++++---
 .../grails/orm/hibernate/query/SelectHqlQuery.java |  4 +--
 .../orm/hibernate/query/HqlQueryMethodsSpec.groovy | 33 ++++++++++++++++---
 .../orm/hibernate/query/SelectHqlQuerySpec.groovy  | 11 +++++++
 4 files changed, 75 insertions(+), 10 deletions(-)

diff --git 
a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HqlQueryMethods.java
 
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HqlQueryMethods.java
index 3f3559fad2..9d80213d41 100644
--- 
a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HqlQueryMethods.java
+++ 
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HqlQueryMethods.java
@@ -25,6 +25,8 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import jakarta.persistence.LockModeType;
+
 public interface HqlQueryMethods {
 
     Set<String> INTERNAL_SETTINGS = Set.of(
@@ -34,7 +36,8 @@ public interface HqlQueryMethods {
         HibernateQueryArgument.READ_ONLY.value(),
         HibernateQueryArgument.FETCH_SIZE.value(),
         HibernateQueryArgument.MAX.value(),
-        HibernateQueryArgument.OFFSET.value()
+        HibernateQueryArgument.OFFSET.value(),
+        HibernateQueryArgument.LOCK.value()
     );
 
     default void populateQuerySettings(HqlQueryDelegate d, Map<String, Object> 
args) {
@@ -43,14 +46,40 @@ public interface HqlQueryMethods {
             
d.setQueryFlushMode(GrailsQueryFlushMode.mapToHibernateQueryFlushMode(args.get(HibernateQueryArgument.FLUSH_MODE.value())));
         }
         if (args.containsKey(HibernateQueryArgument.MAX.value())) {
-            d.setMaxResults((Integer) 
args.get(HibernateQueryArgument.MAX.value()));
+            
d.setMaxResults(toInteger(args.get(HibernateQueryArgument.MAX.value())));
         }
         if (args.containsKey(HibernateQueryArgument.OFFSET.value())) {
-            d.setFirstResult((Integer) 
args.get(HibernateQueryArgument.OFFSET.value()));
+            
d.setFirstResult(toInteger(args.get(HibernateQueryArgument.OFFSET.value())));
+        }
+        if (args.containsKey(HibernateQueryArgument.FETCH_SIZE.value())) {
+            
d.setFetchSize(toInteger(args.get(HibernateQueryArgument.FETCH_SIZE.value())));
+        }
+        if (args.containsKey(HibernateQueryArgument.TIMEOUT.value())) {
+            
d.setTimeout(toInteger(args.get(HibernateQueryArgument.TIMEOUT.value())));
         }
         if (args.containsKey(HibernateQueryArgument.READ_ONLY.value())) {
-            d.setReadOnly((Boolean) 
args.get(HibernateQueryArgument.READ_ONLY.value()));
+            
d.setReadOnly(toBoolean(args.get(HibernateQueryArgument.READ_ONLY.value())));
+        }
+        if (toBoolean(args.get(HibernateQueryArgument.LOCK.value()))) {
+            d.setLockMode(LockModeType.PESSIMISTIC_WRITE);
+            d.setCacheable(false);
+        } else if (args.containsKey(HibernateQueryArgument.CACHE.value())) {
+            
d.setCacheable(toBoolean(args.get(HibernateQueryArgument.CACHE.value())));
+        }
+    }
+
+    static int toInteger(Object value) {
+        if (value instanceof Number number) {
+            return number.intValue();
+        }
+        return Integer.parseInt(value.toString());
+    }
+
+    static boolean toBoolean(Object value) {
+        if (value instanceof Boolean bool) {
+            return bool;
         }
+        return value != null && Boolean.parseBoolean(value.toString());
     }
 
     default void populateHints(HqlQueryDelegate d, Map<String, Object> hints) {
diff --git 
a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/SelectHqlQuery.java
 
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/SelectHqlQuery.java
index eadc7c8071..76f27fcd65 100644
--- 
a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/SelectHqlQuery.java
+++ 
b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/SelectHqlQuery.java
@@ -96,7 +96,7 @@ public class SelectHqlQuery extends Query implements 
HqlQueryMethods, Serializab
             return max;
         }
         Object m = 
queryContext.querySettings().get(HibernateQueryArgument.MAX.value());
-        return m instanceof Number n ? n.intValue() : -1;
+        return m == null ? -1 : HqlQueryMethods.toInteger(m);
     }
 
     @Override
@@ -105,6 +105,6 @@ public class SelectHqlQuery extends Query implements 
HqlQueryMethods, Serializab
             return offset;
         }
         Object o = 
queryContext.querySettings().get(HibernateQueryArgument.OFFSET.value());
-        return o instanceof Number n ? n.intValue() : 0;
+        return o == null ? 0 : HqlQueryMethods.toInteger(o);
     }
 }
diff --git 
a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/query/HqlQueryMethodsSpec.groovy
 
b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/query/HqlQueryMethodsSpec.groovy
index a6ad612e1d..4dbd386ea0 100644
--- 
a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/query/HqlQueryMethodsSpec.groovy
+++ 
b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/query/HqlQueryMethodsSpec.groovy
@@ -19,6 +19,7 @@
 package org.grails.orm.hibernate.query
 
 import org.grails.orm.hibernate.query.HibernateQueryArgument
+import jakarta.persistence.LockModeType
 import spock.lang.Specification
 import org.hibernate.query.QueryFlushMode
 
@@ -64,9 +65,12 @@ class HqlQueryMethodsSpec extends Specification {
         def delegate = Mock(HqlQueryDelegate)
         def settings = [
             (HibernateQueryArgument.FLUSH_MODE.value()): "COMMIT",
-            (HibernateQueryArgument.MAX.value()): 10,
-            (HibernateQueryArgument.OFFSET.value()): 5,
-            (HibernateQueryArgument.READ_ONLY.value()): true
+            (HibernateQueryArgument.MAX.value()): '10',
+            (HibernateQueryArgument.OFFSET.value()): '5',
+            (HibernateQueryArgument.FETCH_SIZE.value()): '50',
+            (HibernateQueryArgument.TIMEOUT.value()): '30',
+            (HibernateQueryArgument.READ_ONLY.value()): 'true',
+            (HibernateQueryArgument.CACHE.value()): 'true'
         ]
 
         when:
@@ -76,7 +80,27 @@ class HqlQueryMethodsSpec extends Specification {
         1 * delegate.setQueryFlushMode(QueryFlushMode.NO_FLUSH)
         1 * delegate.setMaxResults(10)
         1 * delegate.setFirstResult(5)
+        1 * delegate.setFetchSize(50)
+        1 * delegate.setTimeout(30)
         1 * delegate.setReadOnly(true)
+        1 * delegate.setCacheable(true)
+    }
+
+    void "test populateQuerySettings applies lock and disables cache"() {
+        given:
+        def delegate = Mock(HqlQueryDelegate)
+        def settings = [
+            (HibernateQueryArgument.LOCK.value()): 'true',
+            (HibernateQueryArgument.CACHE.value()): 'true'
+        ]
+
+        when:
+        queryMethods.populateQuerySettings(delegate, settings)
+
+        then:
+        1 * delegate.setLockMode(LockModeType.PESSIMISTIC_WRITE)
+        1 * delegate.setCacheable(false)
+        0 * delegate.setCacheable(true)
     }
 
     void "test populateParameters with named parameters"() {
@@ -96,13 +120,14 @@ class HqlQueryMethodsSpec extends Specification {
     void "test populateParameters filters internal settings"() {
         given:
         def delegate = Mock(HqlQueryDelegate)
-        def ctx = new HqlQueryContext("hql", Object, 
[(HibernateQueryArgument.MAX.value()): 10, title: "GORM"], [], [:], [:], false, 
false)
+        def ctx = new HqlQueryContext("hql", Object, 
[(HibernateQueryArgument.MAX.value()): 10, 
(HibernateQueryArgument.LOCK.value()): true, title: "GORM"], [], [:], [:], 
false, false)
 
         when:
         HqlQueryMethods.populateParameters(delegate, ctx)
 
         then:
         0 * delegate.setParameter(HibernateQueryArgument.MAX.value(), _)
+        0 * delegate.setParameter(HibernateQueryArgument.LOCK.value(), _)
         1 * delegate.setParameter("title", "GORM")
     }
 
diff --git 
a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/query/SelectHqlQuerySpec.groovy
 
b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/query/SelectHqlQuerySpec.groovy
index 8c947936bf..3642ef198b 100644
--- 
a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/query/SelectHqlQuerySpec.groovy
+++ 
b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/query/SelectHqlQuerySpec.groovy
@@ -141,6 +141,17 @@ class SelectHqlQuerySpec extends 
HibernateGormDatastoreSpec {
         results.size() == 1
     }
 
+    void "createHqlQuery exposes converted max and offset args"() {
+        when:
+        def query = buildHqlQuery("from SelectHqlQuerySpecBook order by 
title", [:], null, [max: '2', offset: '1'])
+        def results = query.list()
+
+        then:
+        query.max == 2
+        query.offset == 1
+        results.size() == 2
+    }
+
     void "createHqlQuery with empty query string defaults to full entity 
query"() {
         when:
         def results = buildHqlQuery("").list()

Reply via email to