borinquenkid commented on code in PR #15568:
URL: https://github.com/apache/grails-core/pull/15568#discussion_r3470039697


##########
grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/RootBinder.java:
##########
@@ -0,0 +1,105 @@
+/*
+ *  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.cfg.domainbinding.binder;
+
+import java.util.stream.Stream;
+
+import jakarta.annotation.Nonnull;
+
+import org.hibernate.boot.spi.InFlightMetadataCollector;
+import org.hibernate.mapping.RootClass;
+import org.hibernate.mapping.Subclass;
+import org.jspecify.annotations.NonNull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.grails.orm.hibernate.cfg.MappingCacheHolder;
+import 
org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernatePersistentEntity;
+import org.grails.orm.hibernate.cfg.domainbinding.util.MultiTenantFilterBinder;
+
+/** Binder for root classes. */
+@SuppressWarnings("PMD.DataflowAnomalyAnalysis")
+public class RootBinder {
+
+    private static final Logger LOG = 
LoggerFactory.getLogger(RootBinder.class);
+
+    private final String dataSourceName;
+    private final MultiTenantFilterBinder multiTenantFilterBinder;
+    private final SubClassBinder subClassBinder;
+    private final RootPersistentClassCommonValuesBinder 
rootPersistentClassCommonValuesBinder;
+    private final DiscriminatorPropertyBinder discriminatorPropertyBinder;
+    private final InFlightMetadataCollector mappings;
+    private final MappingCacheHolder mappingCacheHolder;
+
+    public RootBinder(
+            String dataSourceName,
+            MultiTenantFilterBinder multiTenantFilterBinder,
+            SubClassBinder subClassBinder,
+            RootPersistentClassCommonValuesBinder 
rootPersistentClassCommonValuesBinder,
+            DiscriminatorPropertyBinder discriminatorPropertyBinder,
+            InFlightMetadataCollector mappings,
+            MappingCacheHolder mappingCacheHolder) {
+        this.dataSourceName = dataSourceName;
+        this.multiTenantFilterBinder = multiTenantFilterBinder;
+        this.subClassBinder = subClassBinder;
+        this.rootPersistentClassCommonValuesBinder = 
rootPersistentClassCommonValuesBinder;
+        this.discriminatorPropertyBinder = discriminatorPropertyBinder;
+        this.mappings = mappings;
+        this.mappingCacheHolder = mappingCacheHolder;
+    }
+
+    /**
+     * Binds a root class (one with no super classes) to the runtime meta 
model based on the supplied
+     * Grails domain class
+     *
+     * @param entity The Grails domain class
+     */
+    public void bindRoot(@Nonnull HibernatePersistentEntity entity) {

Review Comment:
   Done in `ad5114dfab` — switched to `org.jspecify.annotations.NonNull`.



##########
grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/proxy/GrailsBytecodeProvider.java:
##########
@@ -0,0 +1,75 @@
+/*
+ *  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.proxy;
+
+import java.util.Map;
+
+import org.hibernate.bytecode.enhance.spi.EnhancementContext;
+import org.hibernate.bytecode.enhance.spi.Enhancer;
+import org.hibernate.bytecode.spi.BytecodeProvider;
+import org.hibernate.bytecode.spi.ProxyFactoryFactory;
+import org.hibernate.bytecode.spi.ReflectionOptimizer;
+import org.hibernate.property.access.spi.PropertyAccess;
+import org.hibernate.proxy.pojo.bytebuddy.ByteBuddyProxyHelper;
+
+/**
+ * A {@link BytecodeProvider} implementation for Hibernate 7 that provides 
Groovy-aware proxies.
+ *
+ * @author Walter Duque de Estrada

Review Comment:
   Done in `ad5114dfab` — removed.



##########
grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/ClassBinder.java:
##########
@@ -0,0 +1,79 @@
+/*
+ *  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.cfg.domainbinding.binder;
+
+import jakarta.annotation.Nonnull;

Review Comment:
   Done in `ad5114dfab` — switched to `org.jspecify.annotations.NonNull`.



##########
grails-data-hibernate7/core/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java:
##########
@@ -68,226 +75,1274 @@
  *             }
  *             maxResults(10)
  *             order("holderLastName", "desc")
+ *             cache(true)
+ *             readOnly(true)
  *         }
  * </pre>
- * <p>The builder can also be instantiated standalone with a SessionFactory 
and persistent Class instance:
+ *
+ * <h2>Advanced Features</h2>
+ *
+ * <p>The builder supports several advanced Hibernate features:
+ *
+ * <ul>
+ *   <li><b>Pessimistic Locking:</b> Use {@code lock(true)} to obtain a 
pessimistic write lock.
+ *   <li><b>Query Caching:</b> Use {@code cache(true)} to enable query caching 
for the results.
+ *   <li><b>Read-Only Mode:</b> Use {@code readOnly(true)} to disable dirty 
checking for loaded
+ *       entities.
+ *   <li><b>Fetch Mode:</b> Use {@code fetchMode("association", 
FetchMode.JOIN)} to specify Eager/Lazy
+ *       fetching strategies.
+ * </ul>
+ *
+ * <h2>Programmatic instantiation</h2>
+ *
+ * <p>The builder requires a {@link SessionFactory}, the target persistent 
class, and the {@link
+ * org.grails.orm.hibernate.HibernateDatastore} that owns the session:
+ *
  * <pre>
- *      new HibernateCriteriaBuilder(clazz, sessionFactory).list {
+ *      new HibernateCriteriaBuilder(Account, sessionFactory, datastore).list {
  *         eq("firstName", "Fred")
  *      }
  * </pre>
  *
+ * <h2>Architecture</h2>
+ *
+ * <p>Closure method calls in the DSL are dispatched through {@code 
invokeMethod} → {@code
+ * CriteriaMethodInvoker} → {@link HibernateQuery}, which translates each GORM 
constraint into the
+ * equivalent JPA Criteria predicate. {@link grails.gorm.DetachedCriteria} can 
also be passed in
+ * place of a closure to support multi-tenant and reusable query fragments.
+ *
+ * To adjust the methods to be handled you have to extend this class, extend 
CriteriaMethodInvoker
+ *
  * @author Graeme Rocher
+ * @author walterduquedeestrada
+ * @see HibernateQuery
+ * @see grails.gorm.DetachedCriteria
  */
-public class HibernateCriteriaBuilder extends AbstractHibernateCriteriaBuilder 
{
-    /*
-     * Define constants which may be used inside of criteria queries
-     * to refer to standard Hibernate Type instances.
-     */
-    public static final Type BOOLEAN = StandardBasicTypes.BOOLEAN;
-    public static final Type YES_NO = StandardBasicTypes.YES_NO;
-    public static final Type BYTE = StandardBasicTypes.BYTE;
-    public static final Type CHARACTER = StandardBasicTypes.CHARACTER;
-    public static final Type SHORT = StandardBasicTypes.SHORT;
-    public static final Type INTEGER = StandardBasicTypes.INTEGER;
-    public static final Type LONG = StandardBasicTypes.LONG;
-    public static final Type FLOAT = StandardBasicTypes.FLOAT;
-    public static final Type DOUBLE = StandardBasicTypes.DOUBLE;
-    public static final Type BIG_DECIMAL = StandardBasicTypes.BIG_DECIMAL;
-    public static final Type BIG_INTEGER = StandardBasicTypes.BIG_INTEGER;
-    public static final Type STRING = StandardBasicTypes.STRING;
-    public static final Type NUMERIC_BOOLEAN = 
StandardBasicTypes.NUMERIC_BOOLEAN;
-    public static final Type TRUE_FALSE = StandardBasicTypes.TRUE_FALSE;
-    public static final Type URL = StandardBasicTypes.URL;
-    public static final Type TIME = StandardBasicTypes.TIME;
-    public static final Type DATE = StandardBasicTypes.DATE;
-    public static final Type TIMESTAMP = StandardBasicTypes.TIMESTAMP;
-    public static final Type CALENDAR = StandardBasicTypes.CALENDAR;
-    public static final Type CALENDAR_DATE = StandardBasicTypes.CALENDAR_DATE;
-    public static final Type CLASS = StandardBasicTypes.CLASS;
-    public static final Type LOCALE = StandardBasicTypes.LOCALE;
-    public static final Type CURRENCY = StandardBasicTypes.CURRENCY;
-    public static final Type TIMEZONE = StandardBasicTypes.TIMEZONE;
-    public static final Type UUID_BINARY = StandardBasicTypes.UUID_BINARY;
-    public static final Type UUID_CHAR = StandardBasicTypes.UUID_CHAR;
-    public static final Type BINARY = StandardBasicTypes.BINARY;
-    public static final Type WRAPPER_BINARY = 
StandardBasicTypes.WRAPPER_BINARY;
-    public static final Type IMAGE = StandardBasicTypes.IMAGE;
-    public static final Type BLOB = StandardBasicTypes.BLOB;
-    public static final Type MATERIALIZED_BLOB = 
StandardBasicTypes.MATERIALIZED_BLOB;
-    public static final Type CHAR_ARRAY = StandardBasicTypes.CHAR_ARRAY;
-    public static final Type CHARACTER_ARRAY = 
StandardBasicTypes.CHARACTER_ARRAY;
-    public static final Type TEXT = StandardBasicTypes.TEXT;
-    public static final Type CLOB = StandardBasicTypes.CLOB;
-    public static final Type MATERIALIZED_CLOB = 
StandardBasicTypes.MATERIALIZED_CLOB;
-    public static final Type SERIALIZABLE = StandardBasicTypes.SERIALIZABLE;
+@Slf4j
+@SuppressWarnings("PMD.AvoidDuplicateLiterals")
+public class HibernateCriteriaBuilder extends GroovyObjectSupport implements 
BuildableCriteria, ProjectionList {
+    private final SessionFactory sessionFactory;
+    private final boolean participate;
+    private final org.hibernate.query.criteria.HibernateCriteriaBuilder cb;
+    private final HibernateQuery hibernateQuery;
+    private Class<?> targetClass;
+    private CriteriaQuery<?> criteriaQuery;
+    private boolean uniqueResult = false;
 
-    @SuppressWarnings("rawtypes")
-    public HibernateCriteriaBuilder(Class targetClass, SessionFactory 
sessionFactory) {
-        super(targetClass, sessionFactory);
+    @SuppressWarnings("PMD.AvoidFieldNameMatchingMethodName")
+    private boolean scroll;
+
+    @SuppressWarnings("PMD.AvoidFieldNameMatchingMethodName")
+    private boolean count;
+
+    private boolean paginationEnabledList = false;
+    private int defaultFlushMode;
+
+    @SuppressWarnings("PMD.AvoidFieldNameMatchingMethodName")
+    private boolean distinct = false;
+    private CriteriaMethodInvoker criteriaMethodInvoker;
+
+    @SuppressWarnings({"rawtypes", "PMD.CloseResource"})
+    public HibernateCriteriaBuilder(Class targetClass, SessionFactory 
sessionFactory, HibernateDatastore datastore) {
+        this.targetClass = targetClass;
+        setDatastore(datastore);
+        this.sessionFactory = sessionFactory;
+        this.cb = sessionFactory.getCriteriaBuilder();
+        if (TransactionSynchronizationManager.hasResource(sessionFactory)) {
+            this.participate = true;
+        } else {
+            this.participate = false;
+            org.hibernate.Session session = sessionFactory.openSession();
+            TransactionSynchronizationManager.bindResource(sessionFactory, new 
SessionHolder(session));
+        }
+        HibernateSession session = (HibernateSession) datastore.connect();
+        hibernateQuery = new HibernateQuery(
+                session, (GrailsHibernatePersistentEntity) 
datastore.getMappingContext().getPersistentEntity(targetClass.getName()));
         setDefaultFlushMode(GrailsHibernateTemplate.FLUSH_AUTO);
+        criteriaMethodInvoker = new CriteriaMethodInvoker(this);
     }
 
-    @SuppressWarnings("rawtypes")
-    public HibernateCriteriaBuilder(Class targetClass, SessionFactory 
sessionFactory, boolean uniqueResult) {
-        super(targetClass, sessionFactory, uniqueResult);
-        setDefaultFlushMode(GrailsHibernateTemplate.FLUSH_AUTO);
+    public static final String ALIAS_SEPARATOR = ":";
+
+    private static String getFullyQualifiedColumn(String propertyName, String 
alias) {
+        return (Objects.nonNull(alias) ? alias + ALIAS_SEPARATOR : "") + 
propertyName;
+    }
+
+    public org.grails.datastore.mapping.query.api.Criteria exists(Closure 
subquery) {
+        return exists(new 
grails.gorm.DetachedCriteria(targetClass).build(subquery));

Review Comment:
   Agreed — same as above, this is a port of existing code. Will clean up FQCNs 
in a dedicated follow-up PR.



##########
grails-data-hibernate7/core/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java:
##########
@@ -68,226 +75,1274 @@
  *             }
  *             maxResults(10)
  *             order("holderLastName", "desc")
+ *             cache(true)
+ *             readOnly(true)
  *         }
  * </pre>
- * <p>The builder can also be instantiated standalone with a SessionFactory 
and persistent Class instance:
+ *
+ * <h2>Advanced Features</h2>
+ *
+ * <p>The builder supports several advanced Hibernate features:
+ *
+ * <ul>
+ *   <li><b>Pessimistic Locking:</b> Use {@code lock(true)} to obtain a 
pessimistic write lock.
+ *   <li><b>Query Caching:</b> Use {@code cache(true)} to enable query caching 
for the results.
+ *   <li><b>Read-Only Mode:</b> Use {@code readOnly(true)} to disable dirty 
checking for loaded
+ *       entities.
+ *   <li><b>Fetch Mode:</b> Use {@code fetchMode("association", 
FetchMode.JOIN)} to specify Eager/Lazy
+ *       fetching strategies.
+ * </ul>
+ *
+ * <h2>Programmatic instantiation</h2>
+ *
+ * <p>The builder requires a {@link SessionFactory}, the target persistent 
class, and the {@link
+ * org.grails.orm.hibernate.HibernateDatastore} that owns the session:
+ *
  * <pre>
- *      new HibernateCriteriaBuilder(clazz, sessionFactory).list {
+ *      new HibernateCriteriaBuilder(Account, sessionFactory, datastore).list {
  *         eq("firstName", "Fred")
  *      }
  * </pre>
  *
+ * <h2>Architecture</h2>
+ *
+ * <p>Closure method calls in the DSL are dispatched through {@code 
invokeMethod} → {@code
+ * CriteriaMethodInvoker} → {@link HibernateQuery}, which translates each GORM 
constraint into the
+ * equivalent JPA Criteria predicate. {@link grails.gorm.DetachedCriteria} can 
also be passed in
+ * place of a closure to support multi-tenant and reusable query fragments.
+ *
+ * To adjust the methods to be handled you have to extend this class, extend 
CriteriaMethodInvoker
+ *
  * @author Graeme Rocher
+ * @author walterduquedeestrada
+ * @see HibernateQuery
+ * @see grails.gorm.DetachedCriteria
  */
-public class HibernateCriteriaBuilder extends AbstractHibernateCriteriaBuilder 
{
-    /*
-     * Define constants which may be used inside of criteria queries
-     * to refer to standard Hibernate Type instances.
-     */
-    public static final Type BOOLEAN = StandardBasicTypes.BOOLEAN;
-    public static final Type YES_NO = StandardBasicTypes.YES_NO;
-    public static final Type BYTE = StandardBasicTypes.BYTE;
-    public static final Type CHARACTER = StandardBasicTypes.CHARACTER;
-    public static final Type SHORT = StandardBasicTypes.SHORT;
-    public static final Type INTEGER = StandardBasicTypes.INTEGER;
-    public static final Type LONG = StandardBasicTypes.LONG;
-    public static final Type FLOAT = StandardBasicTypes.FLOAT;
-    public static final Type DOUBLE = StandardBasicTypes.DOUBLE;
-    public static final Type BIG_DECIMAL = StandardBasicTypes.BIG_DECIMAL;
-    public static final Type BIG_INTEGER = StandardBasicTypes.BIG_INTEGER;
-    public static final Type STRING = StandardBasicTypes.STRING;
-    public static final Type NUMERIC_BOOLEAN = 
StandardBasicTypes.NUMERIC_BOOLEAN;
-    public static final Type TRUE_FALSE = StandardBasicTypes.TRUE_FALSE;
-    public static final Type URL = StandardBasicTypes.URL;
-    public static final Type TIME = StandardBasicTypes.TIME;
-    public static final Type DATE = StandardBasicTypes.DATE;
-    public static final Type TIMESTAMP = StandardBasicTypes.TIMESTAMP;
-    public static final Type CALENDAR = StandardBasicTypes.CALENDAR;
-    public static final Type CALENDAR_DATE = StandardBasicTypes.CALENDAR_DATE;
-    public static final Type CLASS = StandardBasicTypes.CLASS;
-    public static final Type LOCALE = StandardBasicTypes.LOCALE;
-    public static final Type CURRENCY = StandardBasicTypes.CURRENCY;
-    public static final Type TIMEZONE = StandardBasicTypes.TIMEZONE;
-    public static final Type UUID_BINARY = StandardBasicTypes.UUID_BINARY;
-    public static final Type UUID_CHAR = StandardBasicTypes.UUID_CHAR;
-    public static final Type BINARY = StandardBasicTypes.BINARY;
-    public static final Type WRAPPER_BINARY = 
StandardBasicTypes.WRAPPER_BINARY;
-    public static final Type IMAGE = StandardBasicTypes.IMAGE;
-    public static final Type BLOB = StandardBasicTypes.BLOB;
-    public static final Type MATERIALIZED_BLOB = 
StandardBasicTypes.MATERIALIZED_BLOB;
-    public static final Type CHAR_ARRAY = StandardBasicTypes.CHAR_ARRAY;
-    public static final Type CHARACTER_ARRAY = 
StandardBasicTypes.CHARACTER_ARRAY;
-    public static final Type TEXT = StandardBasicTypes.TEXT;
-    public static final Type CLOB = StandardBasicTypes.CLOB;
-    public static final Type MATERIALIZED_CLOB = 
StandardBasicTypes.MATERIALIZED_CLOB;
-    public static final Type SERIALIZABLE = StandardBasicTypes.SERIALIZABLE;
+@Slf4j
+@SuppressWarnings("PMD.AvoidDuplicateLiterals")
+public class HibernateCriteriaBuilder extends GroovyObjectSupport implements 
BuildableCriteria, ProjectionList {
+    private final SessionFactory sessionFactory;
+    private final boolean participate;
+    private final org.hibernate.query.criteria.HibernateCriteriaBuilder cb;
+    private final HibernateQuery hibernateQuery;
+    private Class<?> targetClass;
+    private CriteriaQuery<?> criteriaQuery;
+    private boolean uniqueResult = false;
 
-    @SuppressWarnings("rawtypes")
-    public HibernateCriteriaBuilder(Class targetClass, SessionFactory 
sessionFactory) {
-        super(targetClass, sessionFactory);
+    @SuppressWarnings("PMD.AvoidFieldNameMatchingMethodName")
+    private boolean scroll;
+
+    @SuppressWarnings("PMD.AvoidFieldNameMatchingMethodName")
+    private boolean count;
+
+    private boolean paginationEnabledList = false;
+    private int defaultFlushMode;
+
+    @SuppressWarnings("PMD.AvoidFieldNameMatchingMethodName")
+    private boolean distinct = false;
+    private CriteriaMethodInvoker criteriaMethodInvoker;
+
+    @SuppressWarnings({"rawtypes", "PMD.CloseResource"})
+    public HibernateCriteriaBuilder(Class targetClass, SessionFactory 
sessionFactory, HibernateDatastore datastore) {
+        this.targetClass = targetClass;
+        setDatastore(datastore);
+        this.sessionFactory = sessionFactory;
+        this.cb = sessionFactory.getCriteriaBuilder();
+        if (TransactionSynchronizationManager.hasResource(sessionFactory)) {
+            this.participate = true;
+        } else {
+            this.participate = false;
+            org.hibernate.Session session = sessionFactory.openSession();

Review Comment:
   Agreed — this file is a port of existing code and this style cleanup was not 
part of the PR scope. Will address in a follow-up PR.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to