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 ecd0263d1bd8624ee20c183d3f59dfa9e6c9aeb9 Author: Walter Duque de Estrada <[email protected]> AuthorDate: Wed Mar 4 12:23:31 2026 -0600 clean up HibernateHqlQuery --- .../hibernate/query/GrailsHibernateQueryUtils.java | 13 ++++- .../orm/hibernate/query/HibernateHqlQuery.java | 66 +++++++++++++++------- .../grails/orm/hibernate/query/HibernateQuery.java | 5 +- .../hibernate/query/HibernateQueryExecutor.java | 8 +-- 4 files changed, 63 insertions(+), 29 deletions(-) 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 d0a342aba4..cc73b32ca9 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 @@ -37,6 +37,7 @@ 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; @@ -150,7 +151,7 @@ public class GrailsHibernateQueryUtils { conversionService.convert(argMap.get(DynamicFinder.ARGUMENT_TIMEOUT), Integer.class)); } if (argMap.containsKey(DynamicFinder.ARGUMENT_FLUSH_MODE)) { - query.setHibernateFlushMode(convertFlushMode(argMap.get(DynamicFinder.ARGUMENT_FLUSH_MODE))); + query.setQueryFlushMode(convertQueryFlushMode(argMap.get(DynamicFinder.ARGUMENT_FLUSH_MODE))); } if (argMap.containsKey(DynamicFinder.ARGUMENT_READ_ONLY)) { query.setReadOnly(ClassUtils.getBooleanFromMap(DynamicFinder.ARGUMENT_READ_ONLY, argMap)); @@ -340,6 +341,16 @@ public class GrailsHibernateQueryUtils { } } + 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. * 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 bdf3321ed7..f896a0adf2 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 @@ -40,6 +40,7 @@ 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.MutationQuery; import org.springframework.context.ApplicationEventPublisher; /** @@ -51,12 +52,21 @@ import org.springframework.context.ApplicationEventPublisher; @SuppressWarnings("PMD.AvoidDuplicateLiterals") public class HibernateHqlQuery extends Query { - private org.hibernate.query.Query<?> query; + private final org.hibernate.query.Query<?> query; + private final org.hibernate.query.MutationQuery mutationQuery; public HibernateHqlQuery( Session session, PersistentEntity entity, org.hibernate.query.Query<?> query) { super(session, entity); this.query = query; + this.mutationQuery = null; + } + + public HibernateHqlQuery( + Session session, PersistentEntity entity, org.hibernate.query.MutationQuery mutationQuery) { + super(session, entity); + this.query = null; + this.mutationQuery = mutationQuery; } @Override @@ -82,8 +92,7 @@ public class HibernateHqlQuery extends Query { * Session-bound step — creates the {@link org.hibernate.query.Query} from an open {@link * org.hibernate.Session} and wraps it in a {@link HibernateHqlQuery}. */ - @SuppressWarnings("unchecked") - public static HibernateHqlQuery buildQuery( + protected static HibernateHqlQuery buildQuery( org.hibernate.Session session, HibernateDatastore dataStore, SessionFactory sessionFactory, @@ -92,8 +101,13 @@ public class HibernateHqlQuery extends Query { org.hibernate.query.Query<?> q; if (StringUtils.isEmpty(ctx.hql())) { q = session.createQuery("from " + ctx.targetClass().getName(), ctx.targetClass()); + return new HibernateHqlQuery(new HibernateSession(dataStore, sessionFactory), entity, q); } else if (ctx.isUpdate()) { - q = session.createQuery(ctx.hql()); + org.hibernate.query.MutationQuery mq = session.createMutationQuery(ctx.hql()); + HibernateHqlQuery result = + new HibernateHqlQuery(new HibernateSession(dataStore, sessionFactory), entity, mq); + result.setFlushMode(session.getHibernateFlushMode()); + return result; } else { q = ctx.isNative() @@ -121,7 +135,9 @@ public class HibernateHqlQuery extends Query { GrailsHibernateTemplate template) { HibernateHqlQuery hqlQuery = template.execute(session -> buildQuery(session, dataStore, sessionFactory, entity, ctx)); - template.applySettings(hqlQuery.getQuery()); + if (hqlQuery.getQuery() != null) { + template.applySettings(hqlQuery.getQuery()); + } hqlQuery.populateQuerySettings( MapUtils.isNotEmpty(args) ? new HashMap<>(args) : Collections.emptyMap()); if (MapUtils.isNotEmpty(ctx.namedParams())) { @@ -141,23 +157,31 @@ public class HibernateHqlQuery extends Query { : FlushModeType.COMMIT); } - @SuppressWarnings({"unchecked", "rawtypes"}) public void populateQuerySettings(Map<?, ?> args) { + if (mutationQuery != null) { + ifPresent(args, DynamicFinder.ARGUMENT_TIMEOUT, v -> mutationQuery.setTimeout(toInt(v))); + ifPresent( + args, + DynamicFinder.ARGUMENT_FLUSH_MODE, + v -> mutationQuery.setQueryFlushMode(GrailsHibernateQueryUtils.convertQueryFlushMode(v))); + return; + } + if (query == null) return; ifPresent(args, DynamicFinder.ARGUMENT_MAX, v -> query.setMaxResults(toInt(v))); ifPresent(args, DynamicFinder.ARGUMENT_OFFSET, v -> query.setFirstResult(toInt(v))); ifPresent(args, DynamicFinder.ARGUMENT_CACHE, v -> query.setCacheable(toBool(v))); ifPresent(args, DynamicFinder.ARGUMENT_FETCH_SIZE, v -> query.setFetchSize(toInt(v))); ifPresent(args, DynamicFinder.ARGUMENT_TIMEOUT, v -> query.setTimeout(toInt(v))); ifPresent(args, DynamicFinder.ARGUMENT_READ_ONLY, v -> query.setReadOnly(toBool(v))); - if (args.containsKey(DynamicFinder.ARGUMENT_FLUSH_MODE)) { - Object v = args.get(DynamicFinder.ARGUMENT_FLUSH_MODE); - if (v instanceof FlushMode fm) query.setHibernateFlushMode(fm); - } + ifPresent( + args, + DynamicFinder.ARGUMENT_FLUSH_MODE, + v -> query.setQueryFlushMode(GrailsHibernateQueryUtils.convertQueryFlushMode(v))); } - @SuppressWarnings({"unchecked", "rawtypes"}) public void populateQueryWithNamedArguments(Map<?, ?> namedArgs) { if (namedArgs == null) return; + org.hibernate.query.CommonQueryContract target = mutationQuery != null ? mutationQuery : query; namedArgs.forEach( (key, value) -> { if (!(key instanceof CharSequence)) { @@ -165,27 +189,27 @@ public class HibernateHqlQuery extends Query { } String name = key.toString(); if (value == null) { - query.setParameter(name, null); - } else if (value instanceof Collection<?> col) { + target.setParameter(name, null); + } else if (mutationQuery == null && value instanceof Collection<?> col) { query.setParameterList(name, col); - } else if (value.getClass().isArray()) { + } else if (mutationQuery == null && value.getClass().isArray()) { query.setParameterList(name, (Object[]) value); } else if (value instanceof CharSequence cs) { - query.setParameter(name, cs.toString(), String.class); + target.setParameter(name, cs.toString(), String.class); } else { - query.setParameter(name, value); + target.setParameter(name, value); } }); } - @SuppressWarnings({"unchecked", "rawtypes"}) public void populateQueryWithIndexedArguments(List<?> params) { if (params == null) return; + org.hibernate.query.CommonQueryContract target = mutationQuery != null ? mutationQuery : query; for (int i = 0; i < params.size(); i++) { Object val = params.get(i); - if (val instanceof CharSequence cs) query.setParameter(i + 1, cs.toString(), String.class); - else if (val != null) query.setParameter(i + 1, val); - else query.setParameter(i + 1, null); + if (val instanceof CharSequence cs) target.setParameter(i + 1, cs.toString(), String.class); + else if (val != null) target.setParameter(i + 1, val); + else target.setParameter(i + 1, null); } } @@ -194,7 +218,7 @@ public class HibernateHqlQuery extends Query { } public int executeUpdate() { - return query.executeUpdate(); + return mutationQuery != null ? mutationQuery.executeUpdate() : query.executeUpdate(); } // ─── Private utilities ──────────────────────────────────────────────────── 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 bef86d7118..b8dd55d7bc 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 @@ -39,6 +39,7 @@ import org.grails.orm.hibernate.GrailsHibernateTemplate; import org.grails.orm.hibernate.IHibernateTemplate; import org.grails.orm.hibernate.proxy.HibernateProxyHandler; import org.hibernate.FlushMode; +import org.hibernate.query.QueryFlushMode; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.query.criteria.HibernateCriteriaBuilder; @@ -69,7 +70,7 @@ public class HibernateQuery extends Query { private Integer fetchSize; private Integer timeout; - private FlushMode flushMode; + private QueryFlushMode flushMode; private Boolean readOnly; public HibernateQuery(HibernateSession session, PersistentEntity entity) { @@ -475,7 +476,7 @@ public class HibernateQuery extends Query { } public void setHibernateFlushMode(FlushMode flushMode) { - this.flushMode = flushMode; + this.flushMode = GrailsHibernateQueryUtils.convertQueryFlushMode(flushMode); } public void setReadOnly(Boolean readOnly) { diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateQueryExecutor.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateQueryExecutor.java index 90bd13ae51..eeff4643f8 100644 --- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateQueryExecutor.java +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateQueryExecutor.java @@ -22,7 +22,7 @@ import jakarta.persistence.LockModeType; import java.util.List; import java.util.Optional; import org.grails.datastore.mapping.proxy.ProxyHandler; -import org.hibernate.FlushMode; +import org.hibernate.query.QueryFlushMode; import org.hibernate.NonUniqueResultException; import org.hibernate.Session; import org.hibernate.query.Query; @@ -35,7 +35,7 @@ public record HibernateQueryExecutor( Boolean queryCache, Integer fetchSize, Integer timeout, - FlushMode flushMode, + QueryFlushMode flushMode, Boolean readOnly, ProxyHandler proxyHandler) { @@ -71,9 +71,7 @@ public record HibernateQueryExecutor( Optional.ofNullable(lockResult).ifPresent(query::setLockMode); Optional.ofNullable(fetchSize).filter(v -> v > 0).ifPresent(query::setFetchSize); Optional.ofNullable(timeout).filter(v -> v > 0).ifPresent(query::setTimeout); - Optional.ofNullable(flushMode) - .map(mode -> mode.toJpaFlushMode()) - .ifPresent(query::setFlushMode); + Optional.ofNullable(flushMode).ifPresent(query::setQueryFlushMode); Optional.ofNullable(readOnly).ifPresent(query::setReadOnly); return query; }
