You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by st...@apache.org on 2019/02/14 14:09:48 UTC

[openjpa] branch master updated (b714dba -> 0e4ec5b)

This is an automated email from the ASF dual-hosted git repository.

struberg pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/openjpa.git.


    from b714dba  use correct name for the db
     new b484ee1  add missing delegate method for Java8 support
     new 0d96457  add -ea to have all debug options uniform
     new 80736f6  OPENJPA-2733 subquery parameters are incorrectly assigned
     new 0e4ec5b  OPENJPA-2733 fix param index.

The 4 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../java/org/apache/openjpa/kernel/QueryImpl.java  |   4 +-
 .../lib/jdbc/DelegatingPreparedStatement.java      |   6 +-
 .../org/apache/openjpa/lib/util/OrderedMap.java    |   1 +
 .../apache/openjpa/persistence/criteria/Order.java |  18 +--
 .../persistence/criteria/TestSubqueries.java       | 121 +++++++++++++++++++--
 .../persistence/criteria/CriteriaBuilderImpl.java  |   2 +-
 .../persistence/criteria/CriteriaQueryImpl.java    |  33 +++---
 .../criteria/ParameterExpressionImpl.java          |  41 ++++++-
 .../openjpa/persistence/criteria/SubqueryImpl.java |   8 +-
 openjpa-project/BUILDING.txt                       |   2 +-
 10 files changed, 194 insertions(+), 42 deletions(-)


[openjpa] 02/04: add -ea to have all debug options uniform

Posted by st...@apache.org.
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 0d9645781e243609c59196270d0325f6d75062a8
Author: Mark Struberg <st...@apache.org>
AuthorDate: Thu Feb 14 10:03:35 2019 +0100

    add -ea to have all debug options uniform
---
 openjpa-project/BUILDING.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/openjpa-project/BUILDING.txt b/openjpa-project/BUILDING.txt
index d59310b..9e8bc15 100644
--- a/openjpa-project/BUILDING.txt
+++ b/openjpa-project/BUILDING.txt
@@ -195,7 +195,7 @@ Running unit tests in the Debugger
 By default all tests run against a derby database.
 To run the tests in the debugger simply add the following JVM properties
 
- -Dopenjpa.ConnectionURL=jdbc:derby:target/database/openjpa-derby-database;create=true -Dopenjpa.ConnectionDriverName=org.apache.derby.jdbc.EmbeddedDriver
+ -ea -Dopenjpa.ConnectionURL=jdbc:derby:target/database/openjpa-derby-database;create=true -Dopenjpa.ConnectionDriverName=org.apache.derby.jdbc.EmbeddedDriver
 
 For running against a MySQL Docker installation:
  -ea -Dopenjpa.ConnectionDriverName=com.mysql.jdbc.Driver -Dopenjpa.ConnectionURL=jdbc:mysql://localhost:3306/openjpatst -Dopenjpa.ConnectionUserName=openjpatst -Dopenjpa.ConnectionPassword=openjpatst


[openjpa] 04/04: OPENJPA-2733 fix param index.

Posted by st...@apache.org.
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 0e4ec5b392b978c4515b26c60e485f2b610de94f
Author: Mark Struberg <st...@apache.org>
AuthorDate: Thu Feb 14 15:06:50 2019 +0100

    OPENJPA-2733 fix param index.
    
    Also handle the case if the same Param gets registered multiple times.
    This eg happens in case of a Criteria Subquery having the same parameter name.
---
 .../java/org/apache/openjpa/kernel/QueryImpl.java  |  4 +-
 .../apache/openjpa/persistence/criteria/Order.java | 18 +++--
 .../persistence/criteria/TestSubqueries.java       | 92 ++++++++++++++++------
 .../persistence/criteria/CriteriaBuilderImpl.java  |  2 +-
 .../persistence/criteria/CriteriaQueryImpl.java    | 30 ++++---
 .../criteria/ParameterExpressionImpl.java          | 41 +++++++++-
 .../openjpa/persistence/criteria/SubqueryImpl.java |  3 +-
 7 files changed, 139 insertions(+), 51 deletions(-)

diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryImpl.java b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryImpl.java
index 0521a1a..cb50be1 100644
--- a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryImpl.java
+++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryImpl.java
@@ -919,7 +919,7 @@ public class QueryImpl implements Query {
                 throw ke;
             } catch (Exception e) {
                 throw new UserException(_loc.get("query-execution-error",
-                		_query), e);
+                        _query), e);
             } finally {
                 _broker.endOperation();
             }
@@ -1306,7 +1306,7 @@ public class QueryImpl implements Query {
         boolean detach = (_broker.getAutoDetach() &
             AutoDetach.DETACH_NONTXREAD) > 0 && !_broker.isActive();
         boolean lrs = range.lrs && !ex.isAggregate(q) && !ex.hasGrouping(q);
-        ResultList<?> res = new ListResultList(Collections.emptyList());
+        ResultList<?> res;
         try {
             res = (!detach && lrs) ? _fc.newResultList(rop) : new EagerResultList(rop);
             res.setUserObject(new Object[]{rop,ex});
diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Order.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Order.java
index 18758ae..ef1b72f 100644
--- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Order.java
+++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Order.java
@@ -37,16 +37,18 @@ public class Order {
     private int id;
 
     private int quantity;
-	private double totalCost;
-	@Column(name="CNT")
-	private int count;
-	private String name;
+    private double totalCost;
 
-	@ManyToOne
-	private Customer customer;
+    @Column(name="CNT")
+    private int count;
 
-	@OneToMany(mappedBy="order")
-	private List<LineItem> lineItems;
+    private String name;
+
+    @ManyToOne
+    private Customer customer;
+
+    @OneToMany(mappedBy="order")
+    private List<LineItem> lineItems;
 
     private boolean delivered;
 
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 f4e8adb..b2547a8 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
@@ -19,6 +19,7 @@
 package org.apache.openjpa.persistence.criteria;
 
 import java.sql.Timestamp;
+import java.util.List;
 
 import javax.persistence.Parameter;
 import javax.persistence.Tuple;
@@ -582,41 +583,52 @@ public class TestSubqueries extends CriteriaTest {
     }
 
     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();
+        freshCustomerAndOrder();
 
-        em.flush();
+        CriteriaQuery<Long> q = cb.createQuery(Long.class);
+        Root<Customer> root = q.from(Customer.class);
+        q.select(root.get(Customer_.accountNum));
 
-        Customer c1 = new Customer();
-        c1.setAccountNum(156);
-        c1.setFirstName("John");
-        c1.setLastName("Doe");
-        c1.setName("Capricorn");
-        em.persist(c1);
+        ParameterExpression<String> testParam = cb.parameter(String.class, "param1");
 
-        Order o1 = new Order();
-        o1.setCustomer(c1);
-        em.persist(o1);
-        o1 = new Order();
-        o1.setCustomer(c1);
-        em.persist(o1);
+        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));
 
-        em.flush();
+        q.where(cb.and(
+                cb.equal(testParam, root.get(Customer_.name)),
+                cb.in(root).value(sq)
+        ));
 
-        // em.getTransaction().commit();
+        // 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();
+
+        cleanCustomerAndOrder();
+    }
+
+    public void testSubquery25() {
+        em.getTransaction().begin();
 
-        // 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());
+        freshCustomerAndOrder();
 
         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");
+        ParameterExpression<String> testParam2 = cb.parameter(String.class, "param1");
 
         Subquery<Customer> sq = q.subquery(Customer.class);
         Root<Order> sqRoot = sq.from(Order.class);
@@ -627,7 +639,7 @@ public class TestSubqueries extends CriteriaTest {
         sq.select(sqRoot.get(Order_.customer));
 
         q.where(cb.and(
-                cb.equal(testParam, root.get(Customer_.name)),
+                cb.equal(testParam2, root.get(Customer_.name)),
                 cb.in(root).value(sq)
         ));
 
@@ -640,6 +652,42 @@ public class TestSubqueries extends CriteriaTest {
 
         em.getTransaction().rollback();
 
+        cleanCustomerAndOrder();
+    }
+
+    private void freshCustomerAndOrder() {
+        cleanCustomerAndOrder();
+
+        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();
+    }
+
+    private void cleanCustomerAndOrder() {
+        boolean txActive = em.getTransaction().isActive();
+        if (!txActive) {
+            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();
+        if (!txActive) {
+            em.getTransaction().commit();
+        }
     }
 
 }
diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaBuilderImpl.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaBuilderImpl.java
index a3e54ed..968b78d 100644
--- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaBuilderImpl.java
+++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaBuilderImpl.java
@@ -674,7 +674,7 @@ public class CriteriaBuilderImpl implements OpenJPACriteriaBuilder, ExpressionPa
 
     @Override
     public Predicate or(Expression<Boolean> x, Expression<Boolean> y) {
-    	return new PredicateImpl.Or(x,y);
+        return new PredicateImpl.Or(x,y);
     }
 
     /**
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 7ea8a3f..778ca72 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
@@ -21,7 +21,6 @@ package org.apache.openjpa.persistence.criteria;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.LinkedHashSet;
@@ -44,7 +43,6 @@ import javax.persistence.criteria.Selection;
 import javax.persistence.criteria.Subquery;
 import javax.persistence.metamodel.EntityType;
 
-import org.apache.openjpa.kernel.StoreQuery;
 import org.apache.openjpa.kernel.exps.Context;
 import org.apache.openjpa.kernel.exps.ExpressionFactory;
 import org.apache.openjpa.kernel.exps.QueryExpressions;
@@ -74,7 +72,7 @@ class CriteriaQueryImpl<T> implements OpenJPACriteriaQuery<T>, AliasContext {
     private Set<Root<?>>        _roots;
     private PredicateImpl       _where;
     private List<Order>         _orders;
-    private OrderedMap<Object, Class<?>> _params; /*<ParameterExpression<?>, Class<?>>*/
+    private OrderedMap<Object, Class<?>> _params = new OrderedMap<>();
     private Selection<? extends T> _selection;
     private List<Selection<?>>  _selections;
     private List<Expression<?>> _groups;
@@ -115,14 +113,12 @@ 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, OrderedMap params) {
+    CriteriaQueryImpl(MetamodelImpl model, SubqueryImpl<T> delegator, OrderedMap<Object, Class<?>> params) {
         this._model = model;
         this._resultClass = delegator.getJavaType();
         _delegator = delegator;
         _aliases = getAliases();
-        if (params != null) {
-            this._params = params;
-        }
+        _params = params;
     }
 
     /**
@@ -237,7 +233,7 @@ class CriteriaQueryImpl<T> implements OpenJPACriteriaQuery<T>, AliasContext {
     @Override
     public Set<ParameterExpression<?>> getParameters() {
         collectParameters(new CriteriaExpressionVisitor.ParameterVisitor(this));
-        return _params == null ? Collections.EMPTY_SET : (Set) _params.keySet();
+        return (Set) _params.keySet();
     }
 
     /**
@@ -266,9 +262,11 @@ class CriteriaQueryImpl<T> implements OpenJPACriteriaQuery<T>, AliasContext {
             _groups = null;
             return this;
         }
+
         _groups = new ArrayList<>();
-        for (Expression<?> e : grouping)
+        for (Expression<?> e : grouping) {
             _groups.add(e);
+        }
         return this;
     }
 
@@ -720,14 +718,14 @@ class CriteriaQueryImpl<T> implements OpenJPACriteriaQuery<T>, AliasContext {
     }
 
     private void renderList(StringBuilder buffer, String clause, Collection<?> coll) {
-    	if (coll == null || coll.isEmpty())
-    		return;
+        if (coll == null || coll.isEmpty())
+            return;
 
-    	buffer.append(clause);
-    	for (Iterator<?> i = coll.iterator(); i.hasNext(); ) {
-    		buffer.append(((CriteriaExpression)i.next()).asValue(this));
-    		if (i.hasNext()) buffer.append(", ");
-    	}
+        buffer.append(clause);
+        for (Iterator<?> i = coll.iterator(); i.hasNext(); ) {
+            buffer.append(((CriteriaExpression)i.next()).asValue(this));
+            if (i.hasNext()) buffer.append(", ");
+        }
     }
 
     private void renderJoins(StringBuilder buffer, Collection<Join<?,?>> joins) {
diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/ParameterExpressionImpl.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/ParameterExpressionImpl.java
index 064cfd5..89dda1e 100644
--- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/ParameterExpressionImpl.java
+++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/ParameterExpressionImpl.java
@@ -107,7 +107,11 @@ class ParameterExpressionImpl<T> extends ExpressionImpl<T>
         org.apache.openjpa.kernel.exps.Parameter param = isCollectionValued
             ? factory.newCollectionValuedParameter(paramKey, clzz)
             : factory.newParameter(paramKey, clzz);
-        param.setIndex(_index);
+
+        int index = _name != null
+            ? q.getParameterTypes().indexOf(this)
+            : _index;
+        param.setIndex(index);
 
         return param;
     }
@@ -121,4 +125,39 @@ class ParameterExpressionImpl<T> extends ExpressionImpl<T>
     public Class<T> getParameterType() {
         return getJavaType();
     }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o)
+            return true;
+
+        if (o == null || getClass() != o.getClass())
+            return false;
+
+        ParameterExpressionImpl<?> that = (ParameterExpressionImpl<?>) o;
+
+        if (_name != null ? !_name.equals(that._name) : that._name != null)
+            return false;
+
+        // if name is given, then we ignore the index
+        if (_name == null && _index != that._index)
+            return false;
+
+        if (getParameterType() != ((ParameterExpressionImpl<?>) o).getParameterType() )
+            return false;
+
+        return value != null ? value.equals(that.value) : that.value == null;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = _name != null ? _name.hashCode() : 0;
+        if (_name == null) {
+            // if name is given, then we ignore the index
+            result = 31 * result + _index;
+        }
+        result = 31 * result + (getParameterType() != null ? getParameterType().hashCode() : 0);
+        result = 31 * result + (value != null ? value.hashCode() : 0);
+        return result;
+    }
 }
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 e8abe19..9e9fb5b 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
@@ -32,6 +32,7 @@ import javax.persistence.criteria.Expression;
 import javax.persistence.criteria.Join;
 import javax.persistence.criteria.ListJoin;
 import javax.persistence.criteria.MapJoin;
+import javax.persistence.criteria.ParameterExpression;
 import javax.persistence.criteria.Predicate;
 import javax.persistence.criteria.Root;
 import javax.persistence.criteria.SetJoin;
@@ -79,7 +80,7 @@ class SubqueryImpl<T> extends ExpressionImpl<T> implements Subquery<T> {
     SubqueryImpl(Class<T> cls, AbstractQuery<?> parent) {
         super(cls);
         _parent = parent;
-        OrderedMap params;
+        OrderedMap<Object, Class<?>> params;
         if (parent instanceof CriteriaQueryImpl) {
             _model = ((CriteriaQueryImpl<?>)parent).getMetamodel();
             params = ((CriteriaQueryImpl<?>)parent).getParameterTypes();


[openjpa] 01/04: add missing delegate method for Java8 support

Posted by st...@apache.org.
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 b484ee1f229fa2732251a1e0682000becaefcca6
Author: Mark Struberg <st...@apache.org>
AuthorDate: Thu Feb 14 10:03:04 2019 +0100

    add missing delegate method for Java8 support
---
 .../org/apache/openjpa/lib/jdbc/DelegatingPreparedStatement.java    | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/openjpa-lib/src/main/java/org/apache/openjpa/lib/jdbc/DelegatingPreparedStatement.java b/openjpa-lib/src/main/java/org/apache/openjpa/lib/jdbc/DelegatingPreparedStatement.java
index 968dc94..728197d 100644
--- a/openjpa-lib/src/main/java/org/apache/openjpa/lib/jdbc/DelegatingPreparedStatement.java
+++ b/openjpa-lib/src/main/java/org/apache/openjpa/lib/jdbc/DelegatingPreparedStatement.java
@@ -59,7 +59,7 @@ public class DelegatingPreparedStatement
     private /*final*/ Connection _conn;
 
     public DelegatingPreparedStatement(PreparedStatement stmnt, Connection conn) {
-    	initialize(stmnt, conn);
+        initialize(stmnt, conn);
     }
 
     public void initialize(PreparedStatement stmnt, Connection conn) {
@@ -664,11 +664,11 @@ public class DelegatingPreparedStatement
 
     @Override
     public boolean isCloseOnCompletion() throws SQLException{
-    	throw new UnsupportedOperationException();
+        return _stmnt.isCloseOnCompletion();
     }
 
     @Override
     public void closeOnCompletion() throws SQLException{
-    	throw new UnsupportedOperationException();
+        _stmnt.closeOnCompletion();
     }
 }


[openjpa] 03/04: OPENJPA-2733 subquery parameters are incorrectly assigned

Posted by st...@apache.org.
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 <st...@apache.org>
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);
     }
 
     /**