diff --git a/src/main/java/org/springframework/data/jpa/repository/query/StringQuery.java b/src/main/java/org/springframework/data/jpa/repository/query/StringQuery.java index 285d41439..bd9bd5af2 100644 --- a/src/main/java/org/springframework/data/jpa/repository/query/StringQuery.java +++ b/src/main/java/org/springframework/data/jpa/repository/query/StringQuery.java @@ -38,6 +38,7 @@ import org.springframework.util.StringUtils; * @author Thomas Darimont * @author Oliver Wehrens * @author Mark Paluch + * @author Jens Schauder */ class StringQuery { @@ -287,7 +288,7 @@ class StringQuery { } if (replacement != null) { - result = StringUtils.replace(result, matcher.group(2), replacement); + result = replaceFirst(result, matcher.group(2), replacement); } } @@ -295,6 +296,16 @@ class StringQuery { return result; } + private static String replaceFirst(String text, String substring, String replacement) { + + int index = text.indexOf(substring); + if (index < 0) { + return text; + } + + return text.substring(0, index) + replacement + text.substring(index + substring.length()); + } + private int tryFindGreatestParameterIndexIn(String query) { Matcher parameterIndexMatcher = PARAMETER_BINDING_BY_INDEX.matcher(query); diff --git a/src/test/java/org/springframework/data/jpa/repository/UserRepositoryTests.java b/src/test/java/org/springframework/data/jpa/repository/UserRepositoryTests.java index f252358dc..6685b8054 100644 --- a/src/test/java/org/springframework/data/jpa/repository/UserRepositoryTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/UserRepositoryTests.java @@ -2145,6 +2145,16 @@ public class UserRepositoryTests { assertThat(query.getParameters(),hasSize(2)); } + @Test // DATAJPA-1179 + public void duplicateSpelsWorkAsIntended() { + + flushTestUsers(); + + List users = repository.findUsersByDuplicateSpel("Oliver"); + + assertThat(users, hasSize(1)); + } + private Page executeSpecWithSort(Sort sort) { flushTestUsers(); diff --git a/src/test/java/org/springframework/data/jpa/repository/query/StringQueryUnitTests.java b/src/test/java/org/springframework/data/jpa/repository/query/StringQueryUnitTests.java index 67bea150f..8eb251bee 100644 --- a/src/test/java/org/springframework/data/jpa/repository/query/StringQueryUnitTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/query/StringQueryUnitTests.java @@ -34,6 +34,7 @@ import org.springframework.data.repository.query.parser.Part.Type; * * @author Oliver Gierke * @author Thomas Darimont + * @author Jens Schauder */ public class StringQueryUnitTests { @@ -302,6 +303,20 @@ public class StringQueryUnitTests { assertThat(new StringQuery("select new Dto from A a").hasConstructorExpression(), is(false)); } + @Test // DATAJPA-1179 + public void bindingsMatchQueryForIdenticalSpelExpressions() { + + StringQuery query = new StringQuery("select a from A a where a.first = :#{#exp} or a.second = :#{#exp}"); + + List bindings = query.getParameterBindings(); + assertThat(bindings, not(empty())); + + for (ParameterBinding binding : bindings) { + assertThat(binding.getName(), notNullValue()); + assertThat(query.getQueryString(), containsString(binding.getName())); + } + } + private void assertPositionalBinding(Class bindingType, Integer position, ParameterBinding expectedBinding) { diff --git a/src/test/java/org/springframework/data/jpa/repository/sample/UserRepository.java b/src/test/java/org/springframework/data/jpa/repository/sample/UserRepository.java index c05497221..f55fe04c2 100644 --- a/src/test/java/org/springframework/data/jpa/repository/sample/UserRepository.java +++ b/src/test/java/org/springframework/data/jpa/repository/sample/UserRepository.java @@ -466,6 +466,10 @@ public interface UserRepository // DATAJPA-858 List findByRolesNameContaining(String name); + // DATAJPA-1179 + @Query("select u from User u where u.firstname = :#{#firstname} and u.firstname = :#{#firstname}") + List findUsersByDuplicateSpel(@Param("firstname") String firstname); + List findRolesAndFirstnameBy(); static interface RolesAndFirstname {