From 7796165e2bbf110fddbed779f543a3cc73ded651 Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Fri, 10 Jul 2015 18:48:30 +0200 Subject: [PATCH] DATAJPA-758 - JpaQueryMethod now only checks parameter names if query uses named parameters. We now only validate parameter names if the declared query actually uses named parameters. This is mainly needed in context of an (accidentally) mixed use of named parameters with indexed placeholders which can occur if compiling with parameters is activated on Java 8 (i.e. using -parameters) but indexed parameters are used in the query definition. --- .../data/jpa/repository/query/JpaQueryMethod.java | 2 +- .../data/jpa/repository/query/QueryUtils.java | 13 +++++++++++++ .../repository/query/JpaQueryMethodUnitTests.java | 13 +++++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryMethod.java b/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryMethod.java index 084c5e30b..1da0897a6 100644 --- a/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryMethod.java +++ b/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryMethod.java @@ -96,7 +96,7 @@ public class JpaQueryMethod extends QueryMethod { String annotatedQuery = getAnnotatedQuery(); - if (!StringUtils.hasText(annotatedQuery)) { + if (!QueryUtils.hasNamedParameter(annotatedQuery)) { return; } diff --git a/src/main/java/org/springframework/data/jpa/repository/query/QueryUtils.java b/src/main/java/org/springframework/data/jpa/repository/query/QueryUtils.java index 50346287b..1d1513729 100644 --- a/src/main/java/org/springframework/data/jpa/repository/query/QueryUtils.java +++ b/src/main/java/org/springframework/data/jpa/repository/query/QueryUtils.java @@ -89,6 +89,9 @@ public abstract class QueryUtils { private static final String EQUALS_CONDITION_STRING = "%s.%s = :%s"; private static final Pattern ORDER_BY = Pattern.compile(".*order\\s+by\\s+.*", CASE_INSENSITIVE); + private static final Pattern NAMED_PARAMETER = Pattern.compile(":" + IDENTIFIER + "|\\#" + IDENTIFIER, + CASE_INSENSITIVE); + private static final Map> ASSOCIATION_TYPES; private static final int QUERY_JOIN_ALIAS_GROUP_INDEX = 2; @@ -390,6 +393,16 @@ public abstract class QueryUtils { return false; } + /** + * Returns whether the given query contains named parameters. + * + * @param query can be {@literal null} or empty. + * @return + */ + public static boolean hasNamedParameter(String query) { + return StringUtils.hasText(query) && NAMED_PARAMETER.matcher(query).find(); + } + /** * Turns the given {@link Sort} into {@link javax.persistence.criteria.Order}s. * diff --git a/src/test/java/org/springframework/data/jpa/repository/query/JpaQueryMethodUnitTests.java b/src/test/java/org/springframework/data/jpa/repository/query/JpaQueryMethodUnitTests.java index 7bd7ebfe3..e198b940b 100644 --- a/src/test/java/org/springframework/data/jpa/repository/query/JpaQueryMethodUnitTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/query/JpaQueryMethodUnitTests.java @@ -358,6 +358,16 @@ public class JpaQueryMethodUnitTests { assertThat(method.getEntityGraph().getType(), is(EntityGraphType.FETCH)); } + /** + * @see DATAJPA-758 + */ + @Test + public void allowsPositionalBindingEvenIfParametersAreNamed() throws Exception { + + new JpaQueryMethod(ValidRepository.class.getMethod("queryWithPositionalBinding", String.class), metadata, + extractor); + } + /** * Interface to define invalid repository methods for testing. * @@ -418,6 +428,9 @@ public class JpaQueryMethodUnitTests { */ @EntityGraph(value = "User.propertyLoadPath", type = EntityGraphType.LOAD) User queryMethodWithCustomEntityFetchGraph(Integer id); + + @Query("select u from User u where u.firstname = ?1") + User queryWithPositionalBinding(@Param("firstname") String firstname); } static interface JpaRepositoryOverride extends JpaRepository {