This is an automated email from the ASF dual-hosted git repository. struberg pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/openjpa.git
commit 80736f6e9d38dfb180c89cec6cb2916341165a5c Author: Mark Struberg <[email protected]> AuthorDate: Thu Feb 14 14:29:11 2019 +0100 OPENJPA-2733 subquery parameters are incorrectly assigned patch submitted by Pawel Veselov - thanks! --- .../org/apache/openjpa/lib/util/OrderedMap.java | 1 + .../persistence/criteria/TestSubqueries.java | 73 +++++++++++++++++++--- .../persistence/criteria/CriteriaQueryImpl.java | 11 ++-- .../openjpa/persistence/criteria/SubqueryImpl.java | 7 ++- 4 files changed, 78 insertions(+), 14 deletions(-) diff --git a/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/OrderedMap.java b/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/OrderedMap.java index 0953dd3..79148f9 100644 --- a/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/OrderedMap.java +++ b/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/OrderedMap.java @@ -61,6 +61,7 @@ public class OrderedMap<K, V> implements Map<K, V>, Serializable { @Override public void clear() { + _del.clear(); } diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/TestSubqueries.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/TestSubqueries.java index d353d9a..f4e8adb 100644 --- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/TestSubqueries.java +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/TestSubqueries.java @@ -20,15 +20,10 @@ package org.apache.openjpa.persistence.criteria; import java.sql.Timestamp; +import javax.persistence.Parameter; import javax.persistence.Tuple; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Expression; -import javax.persistence.criteria.Join; -import javax.persistence.criteria.JoinType; -import javax.persistence.criteria.ListJoin; -import javax.persistence.criteria.Root; -import javax.persistence.criteria.SetJoin; -import javax.persistence.criteria.Subquery; +import javax.persistence.TypedQuery; +import javax.persistence.criteria.*; public class TestSubqueries extends CriteriaTest { @@ -585,4 +580,66 @@ public class TestSubqueries extends CriteriaTest { Customer.CreditRating.POOR)))); assertEquivalence(q, query); } + + public void testSubquery24() { + + em.getTransaction().begin(); + + em.createQuery("delete from Order o where o.customer.name = 'Capricorn'").executeUpdate(); + em.createQuery("delete from Order o").executeUpdate(); + em.createQuery("delete from Customer c where c.name = 'Capricorn'").executeUpdate(); + + em.flush(); + + Customer c1 = new Customer(); + c1.setAccountNum(156); + c1.setFirstName("John"); + c1.setLastName("Doe"); + c1.setName("Capricorn"); + em.persist(c1); + + Order o1 = new Order(); + o1.setCustomer(c1); + em.persist(o1); + o1 = new Order(); + o1.setCustomer(c1); + em.persist(o1); + + em.flush(); + + // em.getTransaction().commit(); + + // System.out.println("CUSTOMERS: "+em.createQuery("select count(c) from Customer c").getFirstResult()); + // System.out.println("ORDERS: "+em.createQuery("select count(c) from Order c").getFirstResult()); + + CriteriaQuery<Long> q = cb.createQuery(Long.class); + Root<Customer> root = q.from(Customer.class); + q.select(root.get(Customer_.accountNum)); + + ParameterExpression<String> testParam = cb.parameter(String.class, "param1"); + + Subquery<Customer> sq = q.subquery(Customer.class); + Root<Order> sqRoot = sq.from(Order.class); + sq.where(cb.and( + cb.equal(cb.parameter(String.class, "param2"), sqRoot.get(Order_.customer).get(Customer_.lastName)), + cb.equal(testParam, sqRoot.get(Order_.customer).get(Customer_.name)) + )); + sq.select(sqRoot.get(Order_.customer)); + + q.where(cb.and( + cb.equal(testParam, root.get(Customer_.name)), + cb.in(root).value(sq) + )); + + // em.createQuery(q).getResultList(); + TypedQuery<Long> tq = em.createQuery(q); + tq.setParameter("param1", "Capricorn"); + tq.setParameter("param2", "Doe"); + + assertEquals(1, tq.getResultList().size()); + + em.getTransaction().rollback(); + + } + } diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaQueryImpl.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaQueryImpl.java index 034c784..7ea8a3f 100644 --- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaQueryImpl.java +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaQueryImpl.java @@ -115,11 +115,14 @@ class CriteriaQueryImpl<T> implements OpenJPACriteriaQuery<T>, AliasContext { * @param model the metamodel defines the scope of all persistent entity references. * @param delegator the subquery which will delegate to this receiver. */ - CriteriaQueryImpl(MetamodelImpl model, SubqueryImpl<T> delegator) { + CriteriaQueryImpl(MetamodelImpl model, SubqueryImpl<T> delegator, OrderedMap params) { this._model = model; this._resultClass = delegator.getJavaType(); _delegator = delegator; _aliases = getAliases(); + if (params != null) { + this._params = params; + } } /** @@ -225,8 +228,6 @@ class CriteriaQueryImpl<T> implements OpenJPACriteriaQuery<T>, AliasContext { * Registers the given parameter. */ void registerParameter(ParameterExpressionImpl<?> p) { - if (_params == null) - _params = new OrderedMap/*<ParameterExpression<?>, Class<?>*/(); if (!_params.containsKey(p)) { p.setIndex(_params.size()); _params.put(p, p.getJavaType()); @@ -431,7 +432,7 @@ class CriteriaQueryImpl<T> implements OpenJPACriteriaQuery<T>, AliasContext { */ public OrderedMap<Object, Class<?>> getParameterTypes() { collectParameters(new CriteriaExpressionVisitor.ParameterVisitor(this)); - return _params == null ? StoreQuery.EMPTY_ORDERED_PARAMS : _params; + return _params; } /** @@ -654,7 +655,7 @@ class CriteriaQueryImpl<T> implements OpenJPACriteriaQuery<T>, AliasContext { void invalidateCompilation() { _compiled = false; - _params = null; + _params.clear(); } /** diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/SubqueryImpl.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/SubqueryImpl.java index 58a5671..e8abe19 100644 --- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/SubqueryImpl.java +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/SubqueryImpl.java @@ -43,6 +43,7 @@ import org.apache.openjpa.kernel.exps.ExpressionFactory; import org.apache.openjpa.kernel.exps.QueryExpressions; import org.apache.openjpa.kernel.exps.Value; import org.apache.openjpa.kernel.jpql.JPQLExpressionBuilder; +import org.apache.openjpa.lib.util.OrderedMap; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.FieldMetaData; import org.apache.openjpa.meta.ValueMetaData; @@ -78,14 +79,18 @@ class SubqueryImpl<T> extends ExpressionImpl<T> implements Subquery<T> { SubqueryImpl(Class<T> cls, AbstractQuery<?> parent) { super(cls); _parent = parent; + OrderedMap params; if (parent instanceof CriteriaQueryImpl) { _model = ((CriteriaQueryImpl<?>)parent).getMetamodel(); + params = ((CriteriaQueryImpl<?>)parent).getParameterTypes(); } else if (parent instanceof SubqueryImpl) { _model = ((SubqueryImpl<?>)parent).getMetamodel(); + params = ((SubqueryImpl<?>)parent).getInnermostParent().getParameterTypes(); } else { _model = null; + params = null; } - _delegate = new CriteriaQueryImpl<>(_model, this); + _delegate = new CriteriaQueryImpl<>(_model, this, params); } /**
