Permalink
Browse files

DATACMNS-157 - Query method lookup now only returns most specific met…

…hod for overridden methods.

Supposed you have a base repository interface declaring a method:

interface BaseRepository<T, ID extends Serializable> extends Repository<T, ID> {

  T myGenericMethod();
}

as well as a concrete repository redeclaring this method to annotate a query on it:

interface ConcreteRepository extends BaseRepository<User, Long> {

  @Query("…")
  User myGenericMethod()
}

Until now we both returned the intermediate method as well as the concrete one which might cause failures as in this case a query derivation would be attempted for the intermediate method which will fail for obvious reasons. The fix now starts with looking up the most specific method when iterating over the repository's methods which causes the intermediate method to be skipped in case it was overridden.
  • Loading branch information...
1 parent 06dc1e5 commit ddea8eda8f48a2bbbd33c070fd9c08daa529c693 @olivergierke olivergierke committed Apr 20, 2012
@@ -31,6 +31,7 @@
import org.springframework.data.repository.core.RepositoryInformation;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.util.Assert;
+import org.springframework.util.ClassUtils;
/**
* Default implementation of {@link RepositoryInformation}.
@@ -155,6 +156,7 @@ private boolean isTargetClassMethod(Method method, Class<?> targetType) {
Set<Method> result = new HashSet<Method>();
for (Method method : getRepositoryInterface().getMethods()) {
+ method = ClassUtils.getMostSpecificMethod(method, getRepositoryInterface());
if (!isCustomMethod(method) && !isBaseClassMethod(method)) {
result.add(method);
}
@@ -8,7 +8,6 @@
import java.util.List;
import org.hamcrest.Matcher;
-import org.hamcrest.Matchers;
import org.hamcrest.collection.IsEmptyIterable;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -126,7 +125,21 @@ public void doesNotConsiderRedeclaredSaveMethodAQueryMethod() throws Exception {
assertThat(queryMethods, not(hasItem(saveMethod)));
assertThat(queryMethods, not(hasItem(deleteMethod)));
- assertThat(queryMethods, is(Matchers.<Method> iterableWithSize(2)));
+ }
+
+ @Test
+ public void onlyReturnsMostConcreteQueryMethod() throws Exception {
+
+ RepositoryMetadata metadata = new DefaultRepositoryMetadata(ConcreteRepository.class);
+ RepositoryInformation information = new DefaultRepositoryInformation(metadata, CrudRepository.class, null);
+
+ Method intermediateMethod = BaseRepository.class.getMethod("genericMethodToOverride", String.class);
+ Method concreteMethod = ConcreteRepository.class.getMethod("genericMethodToOverride", String.class);
+
+ Iterable<Method> queryMethods = information.getQueryMethods();
+
+ assertThat(queryMethods, hasItem(concreteMethod));
+ assertThat(queryMethods, not(hasItem(intermediateMethod)));
}
private Method getMethodFrom(Class<?> type, String name) {
@@ -167,6 +180,8 @@ public String getAddress() {
S findBySomething(String something);
+ S genericMethodToOverride(String something);
+
<K extends S> K save(K entity);
void delete(S entity);
@@ -175,6 +190,8 @@ public String getAddress() {
interface ConcreteRepository extends BaseRepository<User, Integer> {
User findBySomethingDifferent(String somethingDifferent);
+
+ User genericMethodToOverride(String something);
}
interface ReadOnlyRepository<T, ID extends Serializable> extends Repository<T, ID> {

0 comments on commit ddea8ed

Please sign in to comment.