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 {