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