Merge pull request #17 from olivergierke/SGF-113

SGF-113 - Added support to return single entities from query methods.
This commit is contained in:
David Turanski
2012-08-06 06:46:33 -07:00
4 changed files with 67 additions and 7 deletions

View File

@@ -19,6 +19,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import org.springframework.dao.IncorrectResultSizeDataAccessException;
import org.springframework.data.gemfire.GemfireTemplate;
import org.springframework.data.repository.query.ParametersParameterAccessor;
import org.springframework.util.Assert;
@@ -34,6 +35,8 @@ import com.gemstone.gemfire.cache.query.internal.ResultsBag;
*/
public class StringBasedGemfireRepositoryQuery extends GemfireRepositoryQuery {
private static final String INVALID_EXECUTION = "Paging and modifying queries are not supported!";
private final QueryString query;
private final GemfireQueryMethod method;
private final GemfireTemplate template;
@@ -67,6 +70,10 @@ public class StringBasedGemfireRepositoryQuery extends GemfireRepositoryQuery {
this.query = new QueryString(StringUtils.hasText(query) ? query : method.getAnnotatedQuery());
this.method = method;
this.template = template;
if (method.isPageQuery() || method.isModifyingQuery()) {
throw new IllegalStateException(INVALID_EXECUTION);
}
}
/*
@@ -83,7 +90,24 @@ public class StringBasedGemfireRepositoryQuery extends GemfireRepositoryQuery {
while (indexes.hasNext()) {
query = query.bindIn(toCollection(accessor.getBindableValue(indexes.next() - 1)));
}
return toCollection(template.find(query.toString(), parameters));
Collection<?> result = toCollection(template.find(query.toString(), parameters));
if (method.isCollectionQuery()) {
return result;
} else if (method.isQueryForEntity()) {
if (result.isEmpty()) {
return null;
} else if (result.size() == 1) {
return result.iterator().next();
} else {
throw new IncorrectResultSizeDataAccessException(1, result.size());
}
} else {
throw new IllegalStateException(INVALID_EXECUTION);
}
}
/**
@@ -94,15 +118,15 @@ public class StringBasedGemfireRepositoryQuery extends GemfireRepositoryQuery {
* @return
*/
private Collection<?> toCollection(Object source) {
if (source instanceof ResultsBag) {
ResultsBag bag = (ResultsBag)source;
ResultsBag bag = (ResultsBag) source;
return bag.asList();
}
if (source instanceof Collection) {
return (Collection<?>) source;
}
return source.getClass().isArray() ? CollectionUtils.arrayToList(source) : Collections.singleton(source);
}

View File

@@ -42,4 +42,6 @@ public interface PersonRepository extends CrudRepository<Person, Long> {
Collection<Person> findByFirstnameAndLastname(String firstname, String lastname);
Collection<Person> findByFirstnameOrLastname(String firstname, String lastname);
Person findByLastname(String lastname);
}

View File

@@ -26,6 +26,7 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.IncorrectResultSizeDataAccessException;
import org.springframework.data.gemfire.GemfireTemplate;
import org.springframework.data.gemfire.mapping.GemfireMappingContext;
import org.springframework.data.gemfire.mapping.Regions;
@@ -46,7 +47,7 @@ public abstract class AbstractGemfireRepositoryFactoryIntegrationTests {
@Autowired
List<Region<?, ?>> regions;
Person dave, carter, boyd, stefan, leroi, jeff;
Person dave, carter, boyd, stefan, leroi, jeff, oliverAugust;
PersonRepository repository;
@Before
@@ -58,6 +59,7 @@ public abstract class AbstractGemfireRepositoryFactoryIntegrationTests {
stefan = new Person(4L, "Stefan", "Lessard");
leroi = new Person(5L, "Leroi", "Moore");
jeff = new Person(6L, "Jeff", "Coffin");
oliverAugust = new Person(7L, "Oliver August", "Matthews");
GemfireMappingContext context = new GemfireMappingContext();
@@ -70,6 +72,7 @@ public abstract class AbstractGemfireRepositoryFactoryIntegrationTests {
template.put(stefan.id, stefan);
template.put(leroi.id, leroi);
template.put(jeff.id, jeff);
template.put(oliverAugust.id, oliverAugust);
repository = getRepository(regions);
}
@@ -105,7 +108,7 @@ public abstract class AbstractGemfireRepositoryFactoryIntegrationTests {
@Test
public void executesDerivedQueryWithOrCorrectly() {
assertResultsFound(repository.findByFirstnameOrLastname("Carter", "Matthews"), carter, dave);
assertResultsFound(repository.findByFirstnameOrLastname("Carter", "Matthews"), carter, dave, oliverAugust);
}
/**
@@ -119,6 +122,37 @@ public abstract class AbstractGemfireRepositoryFactoryIntegrationTests {
assertResultsFound(repository.findAll());
}
/**
* @see SGF-113
*/
@Test
public void findsPersonByLastname() {
assertThat(repository.findByLastname("Beauford"), is(carter));
}
/**
* @see SGF-113
*/
@Test
public void returnsNullForEmptyResultForSingleEntityQuery() {
assertThat(repository.findByLastname("Foo"), is(nullValue()));
}
/**
* @see SGF-113
*/
@Test
public void throwsExceptionForMoreThanOneResultForSingleEntityQuery() {
try {
repository.findByLastname("Matthews");
fail("Exception expected!");
} catch (IncorrectResultSizeDataAccessException e) {
assertThat(e.getExpectedSize(), is(1));
assertThat(e.getActualSize(), is(2));
}
}
private <T> void assertResultsFound(Iterable<T> result, T... expected) {
assertThat(result, is(notNullValue()));

View File

@@ -38,7 +38,7 @@ public class GemfireRepositoryFactoryIntegrationTests extends AbstractGemfireRep
}
@Test(expected = IllegalStateException.class)
@SuppressWarnings("unchecked")
@SuppressWarnings({ "unchecked", "rawtypes" })
public void throwsExceptionIfReferencedRegionIsNotConfigured() {
GemfireRepositoryFactory factory = new GemfireRepositoryFactory((Iterable) Collections.emptySet(), null);