DATAJPA-185 - Sanity check named parameter names in JpaQueryMethod.

To avoid the query execution to fail due to typos in the named parameter mapping, JpaQueryMethod now checks the named parameters potentially annotated using @Param to be present in the annotated query.
This commit is contained in:
Oliver Gierke
2012-04-11 20:48:34 +02:00
parent c49e17fc0b
commit 26f0eec010
2 changed files with 50 additions and 1 deletions

View File

@@ -31,6 +31,7 @@ import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.jpa.repository.QueryHints;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.query.Parameter;
import org.springframework.data.repository.query.Parameters;
import org.springframework.data.repository.query.QueryMethod;
import org.springframework.util.Assert;
@@ -65,6 +66,29 @@ public class JpaQueryMethod extends QueryMethod {
Assert.isTrue(!(isModifyingQuery() && getParameters().hasSpecialParameter()),
String.format("Modifying method must not contain %s!", Parameters.TYPES));
assertParameterNamesInAnnotatedQuery();
}
private final void assertParameterNamesInAnnotatedQuery() {
String annotatedQuery = getAnnotatedQuery();
if (!StringUtils.hasText(annotatedQuery)) {
return;
}
for (Parameter parameter : getParameters()) {
if (!parameter.isNamedParameter()) {
continue;
}
if (!annotatedQuery.contains(String.format(":%s", parameter.getName()))) {
throw new IllegalStateException(String.format(
"Using named parameters for method %s but parameter '%s' not found in annotated query '%s'!", method,
parameter.getName(), annotatedQuery));
}
}
}
/**

View File

@@ -40,6 +40,7 @@ import org.springframework.data.jpa.repository.Query;
import org.springframework.data.jpa.repository.sample.UserRepository;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.core.support.DefaultRepositoryMetadata;
import org.springframework.data.repository.query.Param;
import org.springframework.data.repository.query.QueryMethod;
/**
@@ -59,7 +60,7 @@ public class JpaQueryMethodUnitTests {
RepositoryMetadata metadata;
Method repositoryMethod, invalidReturnType, pageableAndSort, pageableTwice, sortableTwice, modifyingMethod,
nativeQuery, namedQuery, findWithLockMethod;
nativeQuery, namedQuery, findWithLockMethod, invalidNamedParameter;
/**
* @throws Exception
@@ -80,6 +81,7 @@ public class JpaQueryMethodUnitTests {
namedQuery = ValidRepository.class.getMethod("findByNamedQuery");
findWithLockMethod = ValidRepository.class.getMethod("findOneLocked", Integer.class);
invalidNamedParameter = InvalidRepository.class.getMethod("findByAnnotatedQuery", String.class);
}
@Test
@@ -254,6 +256,25 @@ public class JpaQueryMethodUnitTests {
assertThat(method.getNamedCountQueryName(), is("Foo.bar.count"));
}
/**
* @see DATAJPA-185
*/
@Test
public void rejectsInvalidNamedParameter() {
try {
new JpaQueryMethod(invalidNamedParameter, metadata, extractor);
fail();
} catch (IllegalStateException e) {
// Parameter from query
assertThat(e.getMessage(), containsString("foo"));
// Parameter name from annotation
assertThat(e.getMessage(), containsString("param"));
// Method name
assertThat(e.getMessage(), containsString("findByAnnotatedQuery"));
}
}
/**
* Interface to define invalid repository methods for testing.
*
@@ -284,6 +305,10 @@ public class JpaQueryMethodUnitTests {
// Modifying and Sort is not allowed
@Modifying
void updateMethod(String firstname, Sort sort);
// Typo in named parameter
@Query("select u from User u where u.firstname = :foo")
List<User> findByAnnotatedQuery(@Param("param") String param);
}
static interface ValidRepository {