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 <[email protected]> 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);
