diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/sqlcache/TestExternalizedParameter.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/sqlcache/TestExternalizedParameter.java
index b559a2fa1c..5d4dbe68fc 100644
--- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/sqlcache/TestExternalizedParameter.java
+++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/sqlcache/TestExternalizedParameter.java
@@ -18,7 +18,9 @@
*/
package org.apache.openjpa.persistence.jdbc.sqlcache;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.Properties;
import jakarta.persistence.EntityManager;
@@ -29,11 +31,18 @@
import org.apache.openjpa.lib.rop.ResultList;
import org.apache.openjpa.meta.FieldMetaData;
import org.apache.openjpa.persistence.OpenJPAPersistence;
+import org.apache.openjpa.persistence.QueryImpl;
import junit.framework.TestCase;
/**
* Tests that we can detect if a query is using query parameters for fields whose values are externalized.
+ *
+ * Such queries can not be reparameterized and are therefore excluded from the prepared query cache. The
+ * detection operates on the {@link QueryExpressions} that are attached as a user object to the
+ * {@link ResultList} produced by the kernel query. Since JPA 3.2 the facade
+ * {@link jakarta.persistence.Query#getResultList()} returns a mutable copy of that result rather than the
+ * {@code ResultList} itself, so the tests execute the kernel query directly to get hold of the expressions.
*
* @author Pinaki Poddar
*
@@ -56,44 +65,61 @@ public void setUp() throws Exception {
}
}
- /**
- * Verifies that a query with a non-externalized parameter executes
- * correctly.
- */
public void testNoFalseAlarmOnExternalizedParameterDetection() {
String jpql = "select b from Book b where b.title=:title";
EntityManager em = emf.createEntityManager();
- List> result = em.createQuery(jpql)
- .setParameter("title","XYZ")
- .getResultList();
- assertNotNull(result);
+ Map params = new HashMap<>();
+ params.put("title", "XYZ");
+
+ QueryExpressions[] exps = getExpressions(execute(em, jpql, params));
+ assertNotNull(exps);
+
+ assertFalse(isUsingExternalizedParameter(exps[0]));
}
- /**
- * Verifies that a query with an externalized parameter (token maps
- * to an enum via ExternalValues) executes correctly.
- */
public void testCanDetectExternalizedSingleParameterValue() {
String jpql = "select b from Book b where b.token=:token";
EntityManager em = emf.createEntityManager();
- List> result = em.createQuery(jpql)
- .setParameter("token","MEDIUM")
- .getResultList();
- assertNotNull(result);
+ Map params = new HashMap<>();
+ params.put("token", "MEDIUM");
+
+ QueryExpressions[] exps = getExpressions(execute(em, jpql, params));
+ assertNotNull(exps);
+
+ assertTrue(isUsingExternalizedParameter(exps[0]));
}
- /**
- * Verifies that a query mixing externalized and non-externalized
- * parameters executes correctly.
- */
public void testCanDetectExternalizedMixedParameterValue() {
String jpql = "select b from Book b where b.token=:token and b.title = :title";
EntityManager em = emf.createEntityManager();
- List> result = em.createQuery(jpql)
- .setParameter("token","MEDIUM")
- .setParameter("title", "LARGE")
- .getResultList();
- assertNotNull(result);
+ Map params = new HashMap<>();
+ params.put("token", "MEDIUM");
+ params.put("title", "LARGE");
+
+ QueryExpressions[] exps = getExpressions(execute(em, jpql, params));
+ assertNotNull(exps);
+
+ assertTrue(isUsingExternalizedParameter(exps[0]));
+ }
+
+ /**
+ * Executes the given JPQL on the kernel query to get hold of the raw {@link ResultList}.
+ */
+ Object execute(EntityManager em, String jpql, Map params) {
+ QueryImpl> query = (QueryImpl>) em.createQuery(jpql);
+ return query.getDelegate().execute(params);
+ }
+
+ public QueryExpressions[] getExpressions(Object result) {
+ if (!(result instanceof ResultList))
+ return null;
+ Object userObject = ((ResultList>)result).getUserObject();
+ if (userObject == null || !userObject.getClass().isArray() || ((Object[])userObject).length != 2)
+ return null;
+ Object executor = ((Object[])userObject)[1];
+ if (!(executor instanceof StoreQuery.Executor))
+ return null;
+ return ((StoreQuery.Executor)executor).getQueryExpressions();
}
boolean isUsingExternalizedParameter(QueryExpressions exp) {