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 0953dd3b7..79148f91d 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 implements Map, 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 d353d9a65..f4e8adb6f 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 q = cb.createQuery(Long.class); + Root root = q.from(Customer.class); + q.select(root.get(Customer_.accountNum)); + + ParameterExpression testParam = cb.parameter(String.class, "param1"); + + Subquery sq = q.subquery(Customer.class); + Root 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 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 034c78452..7ea8a3f2a 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 implements OpenJPACriteriaQuery, 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 delegator) { + CriteriaQueryImpl(MetamodelImpl model, SubqueryImpl 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 implements OpenJPACriteriaQuery, AliasContext { * Registers the given parameter. */ void registerParameter(ParameterExpressionImpl p) { - if (_params == null) - _params = new OrderedMap/*, Class*/(); if (!_params.containsKey(p)) { p.setIndex(_params.size()); _params.put(p, p.getJavaType()); @@ -431,7 +432,7 @@ class CriteriaQueryImpl implements OpenJPACriteriaQuery, AliasContext { */ public OrderedMap> getParameterTypes() { collectParameters(new CriteriaExpressionVisitor.ParameterVisitor(this)); - return _params == null ? StoreQuery.EMPTY_ORDERED_PARAMS : _params; + return _params; } /** @@ -654,7 +655,7 @@ class CriteriaQueryImpl implements OpenJPACriteriaQuery, 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 58a56712f..e8abe191c 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 extends ExpressionImpl implements Subquery { SubqueryImpl(Class 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); } /**