DATAJPA-1179 - Create multiple placeholders for identical SpEL expressions.

Before, a duplicate SpEL created one placeholder but multiple bindings resulting in exceptions during parameter binding.

Original pull request: #220.
This commit is contained in:
Jens Schauder
2017-09-18 10:18:43 +02:00
committed by Oliver Gierke
parent cb245b6f8f
commit 4674509d13
4 changed files with 41 additions and 1 deletions

View File

@@ -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);

View File

@@ -2145,6 +2145,16 @@ public class UserRepositoryTests {
assertThat(query.getParameters(),hasSize(2));
}
@Test // DATAJPA-1179
public void duplicateSpelsWorkAsIntended() {
flushTestUsers();
List<User> users = repository.findUsersByDuplicateSpel("Oliver");
assertThat(users, hasSize(1));
}
private Page<User> executeSpecWithSort(Sort sort) {
flushTestUsers();

View File

@@ -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<ParameterBinding> 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<? extends ParameterBinding> bindingType, Integer position,
ParameterBinding expectedBinding) {

View File

@@ -466,6 +466,10 @@ public interface UserRepository
// DATAJPA-858
List<User> findByRolesNameContaining(String name);
// DATAJPA-1179
@Query("select u from User u where u.firstname = :#{#firstname} and u.firstname = :#{#firstname}")
List<User> findUsersByDuplicateSpel(@Param("firstname") String firstname);
List<RolesAndFirstname> findRolesAndFirstnameBy();
static interface RolesAndFirstname {