diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ExpressionStoreQuery.java b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ExpressionStoreQuery.java index 1b78ad166..a59d666d6 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ExpressionStoreQuery.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ExpressionStoreQuery.java @@ -405,7 +405,9 @@ public class ExpressionStoreQuery throw new UserException(_loc.get("gap-query-param", new Object[]{q.getContext().getQueryString(), key, userParams.size(), userParams})); - arr[idx] = userParams.get(key); + Object value = userParams.get(key); + validateParameterValue(key, value, (Class)paramTypes.get(key)); + arr[idx] = value; } return arr; } @@ -430,7 +432,25 @@ public class ExpressionStoreQuery } return low; } - + + private static void validateParameterValue(Object key, Object value, + Class expected) { + if (expected == null) + return; + + if (value == null) { + if (expected.isPrimitive()) + throw new UserException(_loc.get("null-primitive-param", + key, expected)); + } else { + Class actual = value.getClass(); + boolean strict = true; + if (!Filters.canConvert(actual, expected, strict)) + throw new UserException(_loc.get("param-value-mismatch", + new Object[]{key, expected, value, actual})); + } + } + public final Map getUpdates(StoreQuery q) { return assertQueryExpression().updates; } diff --git a/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/localizer.properties b/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/localizer.properties index 9a9a76333..f211a408a 100644 --- a/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/localizer.properties +++ b/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/localizer.properties @@ -291,8 +291,10 @@ unbound-params: Cannot execute query; declared parameters "{0}" were not given \ extra-params: More parameters were passed to execute() than were declared: \ {1} parameters were specified for query execution, but only {0} \ parameters were declared in the query. -null-primitive-param: Parameter "{0}" was declared with a primitive type, but \ - has been given a null value. +null-primitive-param: Parameter "{0}" expects a value of primitive "{1}" \ + but was given a null value. +param-value-mismatch: Parameter "{0}" expects a value of "{1}" but was given \ + a value of "{2}" of "{3}". merged-aggregate: This query on candidate type "{0}" with filter "{1}" \ involves combining the results of multiple sub-queries. However, because \ this query is for aggregate data, OpenJPA cannot combine the sub-query \ diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/sqlcache/TestParameterProcessing.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/sqlcache/TestParameterProcessing.java index 2ea187fdd..76aa4781a 100644 --- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/sqlcache/TestParameterProcessing.java +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/sqlcache/TestParameterProcessing.java @@ -94,5 +94,37 @@ public class TestParameterProcessing extends SingleEMFTestCase { assertEquals(1, result2.size()); } + + public void testWrongParameterValueTypeThrowException() { + String jpql = "select p from Person p where p.firstName=:first" + + " and p.age > :age"; + EntityManager em = emf.createEntityManager(); + + OpenJPAQuery q1 = OpenJPAPersistence.cast(em.createQuery(jpql)); + try { + List result1 = q1.setParameter("first", (short)40) + .setParameter("age", "John") + .getResultList(); + fail("Expected to fail with wrong parameter value"); + } catch (IllegalArgumentException e) { + // good + } + } + + public void testNullParameterValueForPrimitiveTypeThrowsException() { + String jpql = "select p from Person p where p.firstName=:first" + + " and p.age > :age"; + EntityManager em = emf.createEntityManager(); + + OpenJPAQuery q1 = OpenJPAPersistence.cast(em.createQuery(jpql)); + try { + List result1 = q1.setParameter("first", "John") + .setParameter("age", null) + .getResultList(); + fail("Expected to fail with null parameter value for primitives"); + } catch (RuntimeException e) { + // good + } + } }