DATAJPA-629 - Allow SpEL template expressions in combination with parameter expressions in @Query.
Previously SpEL template expressions like #{#entityName} could not be used in conjunction with parameter expressions in @Query because the SpEL template parser tried to evaluate the dynamic parameter expressions as well. We now mask the parameters prior to evaluating the SpEL template expression.
Original pull request: #122.
This commit is contained in:
committed by
Oliver Gierke
parent
fa5a7ace50
commit
36a6f958f2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2013-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package org.springframework.data.jpa.repository.query;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.springframework.data.repository.core.EntityMetadata;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.ParserContext;
|
||||
@@ -35,6 +37,13 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
class ExpressionBasedStringQuery extends StringQuery {
|
||||
|
||||
private static final String EXPRESSION_PARAMETER = "?#{";
|
||||
private static final String QUOTED_EXPRESSION_PARAMETER = "?__HASH__{";
|
||||
|
||||
private static final Pattern EXPRESSION_PARAMETER_QUOTING = Pattern.compile(Pattern.quote(EXPRESSION_PARAMETER));
|
||||
private static final Pattern EXPRESSION_PARAMETER_UNQUOTING = Pattern.compile(Pattern
|
||||
.quote(QUOTED_EXPRESSION_PARAMETER));
|
||||
|
||||
private static final String ENTITY_NAME = "entityName";
|
||||
private static final String ENTITY_NAME_VARIABLE = "#" + ENTITY_NAME;
|
||||
private static final String ENTITY_NAME_VARIABLE_EXPRESSION = "#{" + ENTITY_NAME_VARIABLE + "}";
|
||||
@@ -70,10 +79,25 @@ class ExpressionBasedStringQuery extends StringQuery {
|
||||
StandardEvaluationContext evalContext = new StandardEvaluationContext();
|
||||
evalContext.setVariable(ENTITY_NAME, metadata.getEntityName());
|
||||
|
||||
query = potentiallyQuoteExpressionsParameter(query);
|
||||
|
||||
Expression expr = parser.parseExpression(query, ParserContext.TEMPLATE_EXPRESSION);
|
||||
|
||||
Object result = expr.getValue(evalContext, String.class);
|
||||
return result == null ? query : String.valueOf(result);
|
||||
String result = expr.getValue(evalContext, String.class);
|
||||
|
||||
if (result == null) {
|
||||
return query;
|
||||
}
|
||||
|
||||
return potentiallyUnquoteParameterExpressions(result);
|
||||
}
|
||||
|
||||
private static String potentiallyUnquoteParameterExpressions(String result) {
|
||||
return EXPRESSION_PARAMETER_UNQUOTING.matcher(result).replaceAll(EXPRESSION_PARAMETER);
|
||||
}
|
||||
|
||||
private static String potentiallyQuoteExpressionsParameter(String query) {
|
||||
return EXPRESSION_PARAMETER_QUOTING.matcher(query).replaceAll(QUOTED_EXPRESSION_PARAMETER);
|
||||
}
|
||||
|
||||
private static boolean containsExpression(String query) {
|
||||
|
||||
@@ -1753,6 +1753,20 @@ public class UserRepositoryTests {
|
||||
assertThat(users.getContent().get(1), is(fourthUser));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAJPA-629
|
||||
*/
|
||||
@Test
|
||||
public void shouldfindUsersBySpELExpressionParametersWithSpelTemplateExpression() {
|
||||
|
||||
flushTestUsers();
|
||||
List<User> users = repository.findUsersByFirstnameForSpELExpressionWithParameterIndexOnlyWithEntityExpression(
|
||||
"Joachim", "Arrasz");
|
||||
|
||||
assertThat(users, hasSize(1));
|
||||
assertThat(users.get(0), is(secondUser));
|
||||
}
|
||||
|
||||
private Page<User> executeSpecWithSort(Sort sort) {
|
||||
|
||||
flushTestUsers();
|
||||
|
||||
@@ -459,7 +459,7 @@ public interface UserRepository extends JpaRepository<User, Integer>, JpaSpecifi
|
||||
*/
|
||||
@Query("select u from User u where u.emailAddress = ?1")
|
||||
Optional<User> findOptionalByEmailAddress(String emailAddress);
|
||||
|
||||
|
||||
/**
|
||||
* @see DATAJPA-564
|
||||
*/
|
||||
@@ -527,4 +527,11 @@ public interface UserRepository extends JpaRepository<User, Integer>, JpaSpecifi
|
||||
value = "select * from (select rownum() as RN, u.* from User u) where RN between ?#{ #pageable.offset -1} and ?#{#pageable.offset + #pageable.pageSize}",
|
||||
countQuery = "select count(u.id) from User u", nativeQuery = true)
|
||||
Page<User> findUsersInNativeQueryWithPagination(Pageable pageable);
|
||||
|
||||
/**
|
||||
* @see DATAJPA-629
|
||||
*/
|
||||
@Query("select u from #{#entityName} u where u.firstname = ?#{[0]} and u.lastname = ?#{[1]}")
|
||||
List<User> findUsersByFirstnameForSpELExpressionWithParameterIndexOnlyWithEntityExpression(String firstname,
|
||||
String lastname);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user