This is an automated email from the ASF dual-hosted git repository. borinquenkid pushed a commit to branch merge-hibernate6 in repository https://gitbox.apache.org/repos/asf/grails-core.git
commit 21dec6b17bb91760dad5adf74846ed44ab2149f8 Author: Walter Duque de Estrada <[email protected]> AuthorDate: Sat Jun 21 21:54:31 2025 -0500 Standalone JpaFromProvider --- .../hibernate/query/AbstractHibernateQuery.java | 39 +++--- .../orm/hibernate/query/JpaFromProvider.java | 95 +++++++------- .../orm/hibernate/query/PredicateGenerator.java | 139 ++++++++++----------- 3 files changed, 129 insertions(+), 144 deletions(-) diff --git a/grails-data-hibernate6/core/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java b/grails-data-hibernate6/core/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java index 9fedb54bed..f774635904 100644 --- a/grails-data-hibernate6/core/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java +++ b/grails-data-hibernate6/core/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java @@ -21,7 +21,6 @@ import jakarta.persistence.FetchType; import jakarta.persistence.criteria.CriteriaQuery; import jakarta.persistence.criteria.Expression; import jakarta.persistence.criteria.From; -import jakarta.persistence.criteria.Join; import jakarta.persistence.criteria.JoinType; import jakarta.persistence.criteria.Path; import org.grails.datastore.gorm.query.criteria.DetachedAssociationCriteria; @@ -45,7 +44,6 @@ import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.dao.InvalidDataAccessApiUsageException; -import java.util.AbstractMap; import java.util.Arrays; import java.util.HashMap; import java.util.LinkedList; @@ -55,8 +53,6 @@ import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Function; import java.util.function.Predicate; -import java.util.stream.Collectors; -import java.util.stream.Stream; /** * Bridges the Query API with the Hibernate Criteria API @@ -494,8 +490,8 @@ public abstract class AbstractHibernateQuery extends Query { var projectionList = collectProjections(); var cq = createCriteriaQuery(projectionList); From root = cq.from(entity.getJavaClass()); - var jpaFromProvider = new JpaFromProvider(detachedCriteria); - Map<String, From> tablesByName = jpaFromProvider.getFromsByName(cq, root); + var tablesByName = new JpaFromProvider(detachedCriteria,cq,root); + assignProjections(projectionList, cq, tablesByName); @@ -582,7 +578,7 @@ public abstract class AbstractHibernateQuery extends Query { .toList(); } - private void assignCriteria(CriteriaQuery cq, HibernateCriteriaBuilder cb, From root, Map<String, From> tablesByName) { + private void assignCriteria(CriteriaQuery cq, HibernateCriteriaBuilder cb, From root, JpaFromProvider tablesByName) { List<Criterion> criteriaList = getDetachedCriteria(); if (!criteriaList.isEmpty()) { jakarta.persistence.criteria.Predicate[] predicates = PredicateGenerator.getPredicates(cb, cq, root, criteriaList, tablesByName); @@ -590,14 +586,14 @@ public abstract class AbstractHibernateQuery extends Query { } } - private void assignOrderBy(CriteriaQuery cq, Map<String, From> tablesByName) { + private void assignOrderBy(CriteriaQuery cq, JpaFromProvider tablesByName) { var cb = getCriteriaBuilder(); List<Order> orders = detachedCriteria.getOrders(); if (!orders.isEmpty()) { cq.orderBy(orders .stream() .map(order -> { - Path expression = getFullyQualifiedPath(tablesByName, order.getProperty()); + Path expression = tablesByName.getFullyQualifiedPath(order.getProperty()); if (order.isIgnoreCase() && expression.getJavaType().equals(String.class)) { if (order.getDirection().equals(Order.Direction.ASC)) { return cb.asc(cb.lower(expression)); @@ -618,13 +614,13 @@ public abstract class AbstractHibernateQuery extends Query { } } - private void assignGroupBy(List<GroupPropertyProjection> groupProjections, From root, CriteriaQuery cq, Map<String, From> tablesByName) { + private void assignGroupBy(List<GroupPropertyProjection> groupProjections, From root, CriteriaQuery cq, JpaFromProvider tablesByName) { if (!groupProjections.isEmpty()) { List<Expression> groupByPaths = groupProjections .stream() .map(groupPropertyProjection -> { String propertyName = groupPropertyProjection.getPropertyName(); - return getFullyQualifiedPath(tablesByName, propertyName); + return tablesByName.getFullyQualifiedPath(propertyName); }) .map(Expression.class::cast) .toList(); @@ -632,7 +628,7 @@ public abstract class AbstractHibernateQuery extends Query { } } - private void assignProjections(List<Projection> projections, CriteriaQuery cq, Map<String, From> tablesByName) { + private void assignProjections(List<Projection> projections, CriteriaQuery cq, JpaFromProvider tablesByName) { List<Expression> projectionExpressions = projections .stream() .map(projectionToJpaExpression(tablesByName)) @@ -644,26 +640,26 @@ public abstract class AbstractHibernateQuery extends Query { } else if (projectionExpressions.size() > 1){ cq.multiselect(projectionExpressions); } else { - cq.select(tablesByName.get("root")); + cq.select(tablesByName.getFullyQualifiedPath("root")); } } private Function<Projection, JpaExpression> projectionToJpaExpression( - Map<String, From> tablesByName) { + JpaFromProvider tablesByName) { var cb = getCriteriaBuilder(); return projection -> { if (countProjectionPredicate.test(projection)) { - return cb.count(tablesByName.get("root")); + return cb.count(tablesByName.getFullyQualifiedPath("root")); } else if (countDistinctProjection.test(projection)) { String propertyName = ((PropertyProjection) projection).getPropertyName(); - return cb.countDistinct(tablesByName.get("root").get(propertyName)); + return cb.countDistinct(tablesByName.getFullyQualifiedPath("root." + propertyName)); } else if (idProjectionPredicate.test(projection)) { - return (JpaExpression) tablesByName.get("root").get("id"); + return (JpaExpression) tablesByName.getFullyQualifiedPath("root.id"); } else if (distinctProjectionPredicate.test(projection)) { return null; } else { String propertyName = ((PropertyProjection) projection).getPropertyName(); - Path path = getFullyQualifiedPath(tablesByName, propertyName); + Path path = tablesByName.getFullyQualifiedPath(propertyName); if (maxProjectionPredicate.test(projection)) { return cb.max(path); } else if (minProjectionPredicate.test(projection)) { @@ -680,13 +676,6 @@ public abstract class AbstractHibernateQuery extends Query { }; } - public static Path getFullyQualifiedPath(Map<String, From> tablesByName, String propertyName) { - String[] parsed = propertyName.split("\\."); - String tableName = parsed.length > 1 ? parsed[0] : "root"; - String columnName = parsed.length > 1 ? parsed[1] : propertyName; - return tablesByName.get(tableName).get(columnName); - } - private SessionFactory getSessionFactory() { return ((IHibernateTemplate) session.getNativeInterface()).getSessionFactory(); } diff --git a/grails-data-hibernate6/core/src/main/groovy/org/grails/orm/hibernate/query/JpaFromProvider.java b/grails-data-hibernate6/core/src/main/groovy/org/grails/orm/hibernate/query/JpaFromProvider.java index 8038900800..629ad2767e 100644 --- a/grails-data-hibernate6/core/src/main/groovy/org/grails/orm/hibernate/query/JpaFromProvider.java +++ b/grails-data-hibernate6/core/src/main/groovy/org/grails/orm/hibernate/query/JpaFromProvider.java @@ -3,12 +3,15 @@ package org.grails.orm.hibernate.query; import grails.gorm.DetachedCriteria; import jakarta.persistence.FetchType; import jakarta.persistence.criteria.From; +import jakarta.persistence.criteria.Join; import jakarta.persistence.criteria.JoinType; +import jakarta.persistence.criteria.Path; import org.grails.datastore.gorm.query.criteria.DetachedAssociationCriteria; import org.grails.datastore.mapping.query.Query; import org.hibernate.query.criteria.JpaCriteriaQuery; import java.util.AbstractMap; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; @@ -16,24 +19,44 @@ import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.Stream; -public class JpaFromProvider { +public class JpaFromProvider implements Cloneable { - private final DetachedCriteria detachedCriteria; + private Map<String, From> fromMap; - public JpaFromProvider(DetachedCriteria detachedCriteria) { - this.detachedCriteria = detachedCriteria; + private JpaFromProvider(Map<String, From> fromMap) { + this.fromMap = new HashMap<>(fromMap); } - public Map<String, From> getFromsByName(JpaCriteriaQuery<?> cq, From root) { - var detachedAssociationCriteriaList = getDetachedAssociationCriteria(); + + public JpaFromProvider(DetachedCriteria detachedCriteria, JpaCriteriaQuery<?> cq, From root) { + fromMap = getFromsByName(detachedCriteria, cq, root); + } + + private Map<String, From> getFromsByName(DetachedCriteria detachedCriteria, JpaCriteriaQuery<?> cq, From root) { + var detachedAssociationCriteriaList = ((List<Query.Criterion>) detachedCriteria.getCriteria()) + .stream() + .map(new DetachedAssociationFunction()) + .flatMap(List::stream) + .toList(); var aliasMap = createAliasMap(detachedAssociationCriteriaList); //The join column is column for joining from the root entity var detachedFroms = createDetachedFroms(cq, detachedAssociationCriteriaList); - Map<String, From> fromsByName = Stream.concat(aliasMap.keySet().stream(), collectJoinColumns().stream()) + Map<String, From> fromsByName = Stream.concat(aliasMap.keySet().stream(), ((Map<String, FetchType>) detachedCriteria.getFetchStrategies()) + .entrySet() + .stream() + .filter(entry -> entry.getValue().equals(FetchType.EAGER)) + .map(Map.Entry::getKey) + .toList().stream()) .distinct() .map(joinColumn -> { - var table = detachedFroms.computeIfAbsent(joinColumn, s -> root).join(joinColumn, getJoinType(joinColumn)); + var table = detachedFroms.computeIfAbsent(joinColumn, s -> root).join(joinColumn, ((Map<String, JoinType>) detachedCriteria.getJoinTypes()) + .entrySet() + .stream() + .filter(entry -> entry.getKey().equals(joinColumn)) + .map(Map.Entry::getValue) + .findFirst() + .orElse(JoinType.INNER)); // Attempt to find specific criteria configuration for this association path var column = Optional.ofNullable(aliasMap.get(joinColumn)) .map(detachedAssociationCriteria -> Objects.requireNonNullElse(detachedAssociationCriteria.getAlias(), joinColumn)) @@ -45,16 +68,6 @@ public class JpaFromProvider { return fromsByName; } - private JoinType getJoinType(String joinColumn) { - return getDetachedCriteriaJoinTypes() - .entrySet() - .stream() - .filter(entry -> entry.getKey().equals(joinColumn)) - .map(Map.Entry::getValue) - .findFirst() - .orElse(JoinType.INNER); - } - private Map<String, From> createDetachedFroms(JpaCriteriaQuery<?> cq, List<DetachedAssociationCriteria> detachedAssociationCriteriaList) { return detachedAssociationCriteriaList.stream() .collect(Collectors.toMap( @@ -69,37 +82,29 @@ public class JpaFromProvider { .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); } - @SuppressWarnings("unchecked") - private List<Query.Criterion> getDetachedCriteria() { - return detachedCriteria.getCriteria(); - } - - private List<DetachedAssociationCriteria> getDetachedAssociationCriteria() { - return getDetachedCriteria() - .stream() - .map(new DetachedAssociationFunction()) - .flatMap(List::stream) - .toList(); + public Path getFullyQualifiedPath(String propertyName) { + if (Objects.isNull(propertyName) || propertyName.trim().isEmpty()) { + throw new IllegalArgumentException("propertyName cannot be null"); + } + String[] parsed = propertyName.split("\\."); + if (parsed.length == 1) { + if (fromMap.containsKey(propertyName)) { + return fromMap.get(propertyName); + } else { + return fromMap.get("root").get(propertyName); + } + } + String tableName = parsed[0]; + String columnName = parsed[1]; + return fromMap.get(tableName).get(columnName); } - private List<String> collectJoinColumns() { - return getDetachedCriteriaFetchStrategies() - .entrySet() - .stream() - .filter(entry -> entry.getValue().equals(FetchType.EAGER)) - .map(Map.Entry::getKey) - .toList(); + public Object clone() { + return new JpaFromProvider(fromMap); } - @SuppressWarnings("unchecked") - private Map<String, JoinType> getDetachedCriteriaJoinTypes() { - return detachedCriteria.getJoinTypes(); - } - @SuppressWarnings("unchecked") - private Map<String,FetchType> getDetachedCriteriaFetchStrategies() { - return detachedCriteria.getFetchStrategies(); + public void put(String tableName, From child) { + fromMap.put(tableName, child); } - - } diff --git a/grails-data-hibernate6/core/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java b/grails-data-hibernate6/core/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java index e36f390431..e9a4caa540 100644 --- a/grails-data-hibernate6/core/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java +++ b/grails-data-hibernate6/core/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java @@ -5,14 +5,12 @@ import jakarta.persistence.criteria.CriteriaQuery; import jakarta.persistence.criteria.From; import jakarta.persistence.criteria.Join; import jakarta.persistence.criteria.JoinType; -import jakarta.persistence.criteria.Path; import jakarta.persistence.criteria.Predicate; import jakarta.persistence.criteria.Root; import jakarta.persistence.criteria.Subquery; import org.grails.datastore.gorm.query.criteria.DetachedAssociationCriteria; import org.grails.datastore.mapping.query.Query; import org.hibernate.query.criteria.HibernateCriteriaBuilder; -import org.hibernate.query.criteria.JpaExpression; import org.hibernate.query.criteria.JpaInPredicate; import org.hibernate.query.sqm.tree.predicate.SqmInListPredicate; import org.slf4j.Logger; @@ -29,8 +27,6 @@ import java.util.List; import java.util.Map; import java.util.Objects; -import static org.grails.orm.hibernate.query.AbstractHibernateQuery.getFullyQualifiedPath; - @Slf4j public class PredicateGenerator { @@ -39,7 +35,7 @@ public class PredicateGenerator { public static Predicate[] getPredicates(HibernateCriteriaBuilder cb, CriteriaQuery criteriaQuery, From root_, - List<Query.Criterion> criteriaList, Map<String, From> tablesByName) { + List<Query.Criterion> criteriaList, JpaFromProvider tablesByName) { List<Predicate> list = criteriaList.stream(). @@ -56,7 +52,7 @@ public class PredicateGenerator { } else if (criterion instanceof DetachedAssociationCriteria<?> c) { Join child = root_.join(c.getAssociationPath(), JoinType.LEFT); List<Query.Criterion> criterionList = c.getCriteria(); - Map<String, From> childTablesByName = new HashMap<>(tablesByName); + JpaFromProvider childTablesByName = (JpaFromProvider )tablesByName.clone(); childTablesByName.put("root",child); return cb.and(getPredicates(cb, criteriaQuery, child, criterionList, childTablesByName)); } else if (criterion instanceof Query.Negation) { @@ -68,87 +64,87 @@ public class PredicateGenerator { } return cb.not(predicates[0]); } else if (criterion instanceof Query.IsNull c) { - return cb.isNull(getFullyQualifiedPath(tablesByName, c.getProperty())); + return cb.isNull(tablesByName.getFullyQualifiedPath(c.getProperty())); } else if (criterion instanceof Query.IsNotNull c) { - return cb.isNotNull(getFullyQualifiedPath(tablesByName, c.getProperty())); + return cb.isNotNull(tablesByName.getFullyQualifiedPath(c.getProperty())); } else if (criterion instanceof Query.IsEmpty c) { - return cb.isEmpty(getFullyQualifiedPath(tablesByName, c.getProperty())); + return cb.isEmpty(tablesByName.getFullyQualifiedPath(c.getProperty())); } else if (criterion instanceof Query.Equals c) { - return cb.equal(getFullyQualifiedPath(tablesByName, c.getProperty()), c.getValue()); + return cb.equal(tablesByName.getFullyQualifiedPath(c.getProperty()), c.getValue()); } else if (criterion instanceof Query.NotEquals c) { - return cb.notEqual(getFullyQualifiedPath(tablesByName, c.getProperty()), c.getValue()); + return cb.notEqual(tablesByName.getFullyQualifiedPath(c.getProperty()), c.getValue()); } else if (criterion instanceof Query.EqualsProperty c) { - return cb.equal(getFullyQualifiedPath(tablesByName, c.getProperty()), root_.get(c.getOtherProperty())); + return cb.equal(tablesByName.getFullyQualifiedPath(c.getProperty()), root_.get(c.getOtherProperty())); } else if (criterion instanceof Query.NotEqualsProperty c) { - return cb.notEqual(getFullyQualifiedPath(tablesByName, c.getProperty()), root_.get(c.getOtherProperty())); + return cb.notEqual(tablesByName.getFullyQualifiedPath(c.getProperty()), root_.get(c.getOtherProperty())); } else if (criterion instanceof Query.LessThanEqualsProperty c) { - return cb.le(getFullyQualifiedPath(tablesByName, c.getProperty()), root_.get(c.getOtherProperty())); + return cb.le(tablesByName.getFullyQualifiedPath(c.getProperty()), root_.get(c.getOtherProperty())); } else if (criterion instanceof Query.LessThanProperty c) { - return cb.lt(getFullyQualifiedPath(tablesByName, c.getProperty()), root_.get(c.getOtherProperty())); + return cb.lt(tablesByName.getFullyQualifiedPath(c.getProperty()), root_.get(c.getOtherProperty())); } else if (criterion instanceof Query.GreaterThanEqualsProperty c) { - return cb.ge(getFullyQualifiedPath(tablesByName, c.getProperty()), root_.get(c.getOtherProperty())); + return cb.ge(tablesByName.getFullyQualifiedPath(c.getProperty()), root_.get(c.getOtherProperty())); } else if (criterion instanceof Query.GreaterThanProperty c) { - return cb.gt(getFullyQualifiedPath(tablesByName, c.getProperty()), root_.get(c.getOtherProperty())); + return cb.gt(tablesByName.getFullyQualifiedPath(c.getProperty()), root_.get(c.getOtherProperty())); } else if (criterion instanceof Query.IdEquals c) { return cb.equal(root_.get("id"), c.getValue()); } else if (criterion instanceof Query.GreaterThan c) { - return cb.gt(getFullyQualifiedPath(tablesByName, c.getProperty()), (Number) c.getValue()); + return cb.gt(tablesByName.getFullyQualifiedPath(c.getProperty()), (Number) c.getValue()); } else if (criterion instanceof Query.GreaterThanEquals c) { - return cb.ge(getFullyQualifiedPath(tablesByName, c.getProperty()), (Number) c.getValue()); + return cb.ge(tablesByName.getFullyQualifiedPath(c.getProperty()), (Number) c.getValue()); } else if (criterion instanceof Query.LessThan c) { - return cb.lt(getFullyQualifiedPath(tablesByName, c.getProperty()), (Number) c.getValue()); + return cb.lt(tablesByName.getFullyQualifiedPath(c.getProperty()), (Number) c.getValue()); } else if (criterion instanceof Query.LessThanEquals c) { - return cb.le(getFullyQualifiedPath(tablesByName, c.getProperty()), (Number) c.getValue()); + return cb.le(tablesByName.getFullyQualifiedPath(c.getProperty()), (Number) c.getValue()); } else if (criterion instanceof Query.SizeEquals c) { - return cb.equal(cb.size(getFullyQualifiedPath(tablesByName, c.getProperty())), c.getValue()); + return cb.equal(cb.size(tablesByName.getFullyQualifiedPath(c.getProperty())), c.getValue()); } else if (criterion instanceof Query.SizeNotEquals c) { - return cb.notEqual(cb.size(getFullyQualifiedPath(tablesByName, c.getProperty())), c.getValue()); + return cb.notEqual(cb.size(tablesByName.getFullyQualifiedPath(c.getProperty())), c.getValue()); } else if (criterion instanceof Query.SizeGreaterThan c) { - return cb.gt(cb.size(getFullyQualifiedPath(tablesByName, c.getProperty())), (Number) c.getValue()); + return cb.gt(cb.size(tablesByName.getFullyQualifiedPath(c.getProperty())), (Number) c.getValue()); } else if (criterion instanceof Query.SizeGreaterThanEquals c) { - return cb.ge(cb.size(getFullyQualifiedPath(tablesByName, c.getProperty())), (Number) c.getValue()); + return cb.ge(cb.size(tablesByName.getFullyQualifiedPath(c.getProperty())), (Number) c.getValue()); } else if (criterion instanceof Query.SizeLessThan c) { - return cb.lt(cb.size(getFullyQualifiedPath(tablesByName, c.getProperty())), (Number) c.getValue()); + return cb.lt(cb.size(tablesByName.getFullyQualifiedPath(c.getProperty())), (Number) c.getValue()); } else if (criterion instanceof Query.SizeLessThanEquals c) { - return cb.le(cb.size(getFullyQualifiedPath(tablesByName, c.getProperty())), (Number) c.getValue()); + return cb.le(cb.size(tablesByName.getFullyQualifiedPath(c.getProperty())), (Number) c.getValue()); } else if (criterion instanceof Query.Between c) { if (c.getFrom() instanceof String && c.getTo() instanceof String) { - return cb.between(getFullyQualifiedPath(tablesByName, c.getProperty()), (String) c.getFrom(), (String) c.getTo()); + return cb.between(tablesByName.getFullyQualifiedPath(c.getProperty()), (String) c.getFrom(), (String) c.getTo()); } else if (c.getFrom() instanceof Short && c.getTo() instanceof Short) { - return cb.between(getFullyQualifiedPath(tablesByName, c.getProperty()), (Short) c.getFrom(), (Short) c.getTo()); + return cb.between(tablesByName.getFullyQualifiedPath(c.getProperty()), (Short) c.getFrom(), (Short) c.getTo()); } else if (c.getFrom() instanceof Integer && c.getTo() instanceof Integer) { - return cb.between(getFullyQualifiedPath(tablesByName, c.getProperty()), (Integer) c.getFrom(), (Integer) c.getTo()); + return cb.between(tablesByName.getFullyQualifiedPath(c.getProperty()), (Integer) c.getFrom(), (Integer) c.getTo()); } else if (c.getFrom() instanceof Long && c.getTo() instanceof Long) { - return cb.between(getFullyQualifiedPath(tablesByName, c.getProperty()), (Long) c.getFrom(), (Long) c.getTo()); + return cb.between(tablesByName.getFullyQualifiedPath(c.getProperty()), (Long) c.getFrom(), (Long) c.getTo()); } else if (c.getFrom() instanceof Date && c.getTo() instanceof Date) { - return cb.between(getFullyQualifiedPath(tablesByName, c.getProperty()), (Date) c.getFrom(), (Date) c.getTo()); + return cb.between(tablesByName.getFullyQualifiedPath(c.getProperty()), (Date) c.getFrom(), (Date) c.getTo()); } else if (c.getFrom() instanceof Instant && c.getTo() instanceof Instant) { - return cb.between(getFullyQualifiedPath(tablesByName, c.getProperty()), (Instant) c.getFrom(), (Instant) c.getTo()); + return cb.between(tablesByName.getFullyQualifiedPath(c.getProperty()), (Instant) c.getFrom(), (Instant) c.getTo()); } else if (c.getFrom() instanceof LocalDate && c.getTo() instanceof LocalDate) { - return cb.between(getFullyQualifiedPath(tablesByName, c.getProperty()), (LocalDate) c.getFrom(), (LocalDate) c.getTo()); + return cb.between(tablesByName.getFullyQualifiedPath(c.getProperty()), (LocalDate) c.getFrom(), (LocalDate) c.getTo()); } else if (c.getFrom() instanceof LocalDateTime && c.getTo() instanceof LocalDateTime) { - return cb.between(getFullyQualifiedPath(tablesByName, c.getProperty()), (LocalDateTime) c.getFrom(), (LocalDateTime) c.getTo()); + return cb.between(tablesByName.getFullyQualifiedPath(c.getProperty()), (LocalDateTime) c.getFrom(), (LocalDateTime) c.getTo()); } else if (c.getFrom() instanceof OffsetDateTime && c.getTo() instanceof OffsetDateTime) { - return cb.between(getFullyQualifiedPath(tablesByName, c.getProperty()), (OffsetDateTime) c.getFrom(), (OffsetDateTime) c.getTo()); + return cb.between(tablesByName.getFullyQualifiedPath(c.getProperty()), (OffsetDateTime) c.getFrom(), (OffsetDateTime) c.getTo()); } else if (c.getFrom() instanceof ZonedDateTime && c.getTo() instanceof ZonedDateTime) { - return cb.between(getFullyQualifiedPath(tablesByName, c.getProperty()), (ZonedDateTime) c.getFrom(), (ZonedDateTime) c.getTo()); + return cb.between(tablesByName.getFullyQualifiedPath(c.getProperty()), (ZonedDateTime) c.getFrom(), (ZonedDateTime) c.getTo()); } } else if (criterion instanceof Query.ILike c) { - return cb.ilike(getFullyQualifiedPath(tablesByName, c.getProperty()), c.getValue().toString()); + return cb.ilike(tablesByName.getFullyQualifiedPath(c.getProperty()), c.getValue().toString()); } else if (criterion instanceof Query.RLike c) { - return cb.like(getFullyQualifiedPath(tablesByName, c.getProperty()), c.getPattern(), '\\'); + return cb.like(tablesByName.getFullyQualifiedPath(c.getProperty()), c.getPattern(), '\\'); } else if (criterion instanceof Query.Like c) { - return cb.like(getFullyQualifiedPath(tablesByName, c.getProperty()), c.getValue().toString()); + return cb.like(tablesByName.getFullyQualifiedPath(c.getProperty()), c.getValue().toString()); } else if (criterion instanceof Query.SizeEquals c) { - return cb.equal(cb.size(getFullyQualifiedPath(tablesByName, c.getProperty())), c.getValue()); + return cb.equal(cb.size(tablesByName.getFullyQualifiedPath(c.getProperty())), c.getValue()); } else if (criterion instanceof Query.SizeGreaterThan c) { - return cb.gt(cb.size(getFullyQualifiedPath(tablesByName, c.getProperty())), (Number) c.getValue()); + return cb.gt(cb.size(tablesByName.getFullyQualifiedPath(c.getProperty())), (Number) c.getValue()); } else if (criterion instanceof Query.SizeGreaterThanEquals c) { - return cb.ge(cb.size(getFullyQualifiedPath(tablesByName, c.getProperty())), (Number) c.getValue()); + return cb.ge(cb.size(tablesByName.getFullyQualifiedPath(c.getProperty())), (Number) c.getValue()); } else if (criterion instanceof Query.SizeLessThan c) { - return cb.lt(cb.size(getFullyQualifiedPath(tablesByName, c.getProperty())), (Number) c.getValue()); + return cb.lt(cb.size(tablesByName.getFullyQualifiedPath(c.getProperty())), (Number) c.getValue()); } else if (criterion instanceof Query.SizeLessThanEquals c) { - return cb.le(cb.size(getFullyQualifiedPath(tablesByName, c.getProperty())), (Number) c.getValue()); + return cb.le(cb.size(tablesByName.getFullyQualifiedPath(c.getProperty())), (Number) c.getValue()); } else if ( criterion instanceof Query.In c && Objects.nonNull(c.getSubquery()) @@ -161,11 +157,10 @@ public class PredicateGenerator { Subquery subquery = criteriaQuery.subquery(getJavaTypeOfInClause((SqmInListPredicate) in)); Root from = subquery.from(c.getSubquery().getPersistentEntity().getJavaClass()); List subCriteria = c.getSubquery().getCriteria(); - Map<String,From> newMap = new HashMap<>(); - newMap.putAll(tablesByName); + JpaFromProvider newMap = (JpaFromProvider) tablesByName.clone(); newMap.put("root", from); Predicate[] predicates = getPredicates(cb, criteriaQuery, from, subCriteria, newMap); - subquery.select(getFullyQualifiedPath(newMap,projection.getPropertyName())).distinct(distinct).where(cb.and(predicates)); + subquery.select(newMap.getFullyQualifiedPath(projection.getPropertyName())).distinct(distinct).where(cb.and(predicates)); return in.value(subquery); } else if ( criterion instanceof Query.NotIn c @@ -179,11 +174,10 @@ public class PredicateGenerator { Subquery subquery = criteriaQuery.subquery(getJavaTypeOfInClause((SqmInListPredicate) in)); Root from = subquery.from(c.getSubquery().getPersistentEntity().getJavaClass()); List subCriteria = c.getSubquery().getCriteria(); - Map<String,From> newMap = new HashMap<>(); - newMap.putAll(tablesByName); + JpaFromProvider newMap = (JpaFromProvider) tablesByName.clone(); newMap.put("root", from); Predicate[] predicates = getPredicates(cb, criteriaQuery, from, subCriteria, newMap); - subquery.select(getFullyQualifiedPath(newMap,projection.getPropertyName())).distinct(distinct).where(cb.and(predicates)); + subquery.select(newMap.getFullyQualifiedPath(projection.getPropertyName())).distinct(distinct).where(cb.and(predicates)); return cb.not(in.value(subquery)); } else if (criterion instanceof Query.In c && Objects.nonNull(c.getSubquery()) @@ -194,8 +188,7 @@ public class PredicateGenerator { Subquery subquery = criteriaQuery.subquery(getJavaTypeOfInClause((SqmInListPredicate) in)); Root from = subquery.from(c.getSubquery().getPersistentEntity().getJavaClass()); List subCriteria = c.getSubquery().getCriteria(); - Map<String,From> newMap = new HashMap<>(); - newMap.putAll(tablesByName); + JpaFromProvider newMap = (JpaFromProvider) tablesByName.clone(); newMap.put("root", from); Predicate[] predicates = getPredicates(cb, criteriaQuery, from, subCriteria, newMap); subquery.select(from).where(cb.and(predicates)); @@ -209,31 +202,30 @@ public class PredicateGenerator { Subquery subquery = criteriaQuery.subquery(getJavaTypeOfInClause((SqmInListPredicate) in)); Root from = subquery.from(c.getSubquery().getPersistentEntity().getJavaClass()); List subCriteria = c.getSubquery().getCriteria(); - Map<String,From> newMap = new HashMap<>(); - newMap.putAll(tablesByName); + JpaFromProvider newMap = (JpaFromProvider) tablesByName.clone(); newMap.put("root", from); Predicate[] predicates = getPredicates(cb, criteriaQuery, from, subCriteria, newMap); subquery.select(from).where(cb.and(predicates)); return cb.not(in.value(subquery)); } else if (criterion instanceof Query.In c && !c.getValues().isEmpty() ) { - return cb.in(getFullyQualifiedPath(tablesByName, c.getProperty()), c.getValues()); + return cb.in(tablesByName.getFullyQualifiedPath(c.getProperty()), c.getValues()); } else if (criterion instanceof Query.NotIn c ) { - return cb.not(cb.in(getFullyQualifiedPath(tablesByName, c.getProperty()), c.getValue())); + return cb.not(cb.in(tablesByName.getFullyQualifiedPath(c.getProperty()), c.getValue())); } else if (criterion instanceof Query.Exists c) { Subquery subquery = criteriaQuery.subquery(Object.class); Root subRoot = subquery.from(c.getSubquery().getPersistentEntity().getJavaClass()); - HashMap<String, From> subMap = new HashMap<>(tablesByName); - subMap.put("root", subRoot); - Predicate[] predicates = getPredicates(cb, criteriaQuery, subRoot, c.getSubquery().getCriteria(), subMap); + JpaFromProvider newMap = (JpaFromProvider) tablesByName.clone(); + newMap.put("root", subRoot); + Predicate[] predicates = getPredicates(cb, criteriaQuery, subRoot, c.getSubquery().getCriteria(), newMap); subquery.select(cb.literal(1)).where(cb.and(predicates)); return cb.exists(subquery); } else if (criterion instanceof Query.NotExists c) { Subquery subquery = criteriaQuery.subquery(Object.class); Root subRoot = subquery.from(c.getSubquery().getPersistentEntity().getJavaClass()); - HashMap<String, From> subMap = new HashMap<>(tablesByName); - subMap.put("root", subRoot); + JpaFromProvider newMap = (JpaFromProvider) tablesByName.clone(); + newMap.put("root", subRoot); Predicate[] predicates = getPredicates(cb, criteriaQuery, subRoot, c.getSubquery().getCriteria(), tablesByName); subquery.select(cb.literal(1)).where(cb.and(predicates)); return cb.not(cb.exists(subquery)); @@ -241,37 +233,36 @@ public class PredicateGenerator { Subquery subquery = criteriaQuery.subquery(Number.class); Root from = subquery.from(c.getValue().getPersistentEntity().getJavaClass()); List subCriteria = c.getValue().getCriteria(); - Map<String,From> newMap = new HashMap<>(); - newMap.putAll(tablesByName); + JpaFromProvider newMap = (JpaFromProvider) tablesByName.clone(); newMap.put("root", from); Predicate[] predicates = getPredicates(cb, criteriaQuery, from, subCriteria, newMap); if (c instanceof Query.GreaterThanEqualsAll sc) { subquery.select(cb.max(from.get(c.getProperty()))).where(cb.and(predicates)); - return cb.greaterThanOrEqualTo(getFullyQualifiedPath(tablesByName, sc.getProperty()), subquery); + return cb.greaterThanOrEqualTo(tablesByName.getFullyQualifiedPath(sc.getProperty()), subquery); } else if (c instanceof Query.GreaterThanAll sc) { subquery.select(cb.max(from.get(c.getProperty()))).where(cb.and(predicates)); - return cb.greaterThan(getFullyQualifiedPath(tablesByName, sc.getProperty()), subquery); + return cb.greaterThan(tablesByName.getFullyQualifiedPath(sc.getProperty()), subquery); } else if (c instanceof Query.LessThanEqualsAll sc) { subquery.select(cb.min(from.get(c.getProperty()))).where(cb.and(predicates)); - return cb.lessThanOrEqualTo(getFullyQualifiedPath(tablesByName, sc.getProperty()), subquery); + return cb.lessThanOrEqualTo(tablesByName.getFullyQualifiedPath(sc.getProperty()), subquery); } else if (c instanceof Query.LessThanAll sc) { subquery.select(cb.min(from.get(c.getProperty()))).where(cb.and(predicates)); - return cb.lessThan(getFullyQualifiedPath(tablesByName, sc.getProperty()), subquery); + return cb.lessThan(tablesByName.getFullyQualifiedPath(sc.getProperty()), subquery); } else if (c instanceof Query.EqualsAll sc) { subquery.select(from.get(c.getProperty())).where(cb.and(predicates)); - return cb.equal(getFullyQualifiedPath(tablesByName, sc.getProperty()), subquery); + return cb.equal(tablesByName.getFullyQualifiedPath(sc.getProperty()), subquery); } else if (c instanceof Query.GreaterThanEqualsSome sc) { subquery.select(cb.max(from.get(c.getProperty()))).where(cb.or(predicates)); - return cb.greaterThanOrEqualTo(getFullyQualifiedPath(tablesByName, sc.getProperty()), subquery); + return cb.greaterThanOrEqualTo(tablesByName.getFullyQualifiedPath(sc.getProperty()), subquery); } else if (c instanceof Query.GreaterThanSome sc) { subquery.select(cb.max(from.get(c.getProperty()))).where(cb.or(predicates)); - return cb.greaterThan(getFullyQualifiedPath(tablesByName, sc.getProperty()), subquery); + return cb.greaterThan(tablesByName.getFullyQualifiedPath(sc.getProperty()), subquery); } else if (c instanceof Query.LessThanEqualsSome sc) { subquery.select(cb.min(from.get(c.getProperty()))).where(cb.or(predicates)); - return cb.lessThanOrEqualTo(getFullyQualifiedPath(tablesByName, sc.getProperty()), subquery); + return cb.lessThanOrEqualTo(tablesByName.getFullyQualifiedPath(sc.getProperty()), subquery); } else if (c instanceof Query.LessThanSome sc) { subquery.select(cb.min(from.get(c.getProperty()))).where(cb.or(predicates)); - return cb.lessThan(getFullyQualifiedPath(tablesByName, sc.getProperty()), subquery); + return cb.lessThan(tablesByName.getFullyQualifiedPath(sc.getProperty()), subquery); } else if (criterion instanceof Query.NotIn sc && Objects.nonNull(sc.getSubquery()) && !sc.getSubquery().getProjections().isEmpty() @@ -280,7 +271,7 @@ public class PredicateGenerator { Query.PropertyProjection projection = (Query.PropertyProjection) sc.getSubquery().getProjections().get(0); boolean distinct = projection instanceof Query.DistinctPropertyProjection; subquery.select(from.get(projection.getPropertyName())).distinct(distinct).where(cb.and(predicates)); - return cb.in(getFullyQualifiedPath(tablesByName, sc.getProperty())).value(subquery); + return cb.in(tablesByName.getFullyQualifiedPath(sc.getProperty())).value(subquery); } else if (criterion instanceof Query.NotIn sc && Objects.nonNull(sc.getSubquery()) && !sc.getSubquery().getProjections().isEmpty()
