diff --git a/src/main/java/org/springframework/data/redis/core/RedisKeyValueAdapter.java b/src/main/java/org/springframework/data/redis/core/RedisKeyValueAdapter.java index 4029f8de3..d75c567f0 100644 --- a/src/main/java/org/springframework/data/redis/core/RedisKeyValueAdapter.java +++ b/src/main/java/org/springframework/data/redis/core/RedisKeyValueAdapter.java @@ -60,7 +60,6 @@ import org.springframework.data.redis.listener.RedisMessageListenerContainer; import org.springframework.data.redis.util.ByteUtils; import org.springframework.data.util.CloseableIterator; import org.springframework.util.Assert; -import org.springframework.util.NumberUtils; import org.springframework.util.ObjectUtils; /** @@ -346,6 +345,10 @@ public class RedisKeyValueAdapter extends AbstractKeyValueAdapter * @see org.springframework.data.keyvalue.core.KeyValueAdapter#getAllOf(java.io.Serializable) */ public List getAllOf(final Serializable keyspace) { + return getAllOf(keyspace, -1, -1); + } + + public List getAllOf(final Serializable keyspace, int offset, int rows) { final byte[] binKeyspace = toBytes(keyspace); @@ -358,7 +361,15 @@ public class RedisKeyValueAdapter extends AbstractKeyValueAdapter }); List result = new ArrayList(); - for (byte[] key : ids) { + + List keys = new ArrayList(ids); + + offset = Math.max(0, offset); + if (offset >= 0 && rows > 0) { + keys = keys.subList(offset, Math.min(offset + rows, keys.size())); + } + + for (byte[] key : keys) { result.add(get(key, keyspace)); } return result; diff --git a/src/main/java/org/springframework/data/redis/core/RedisQueryEngine.java b/src/main/java/org/springframework/data/redis/core/RedisQueryEngine.java index 1b322e718..542cf0e96 100644 --- a/src/main/java/org/springframework/data/redis/core/RedisQueryEngine.java +++ b/src/main/java/org/springframework/data/redis/core/RedisQueryEngine.java @@ -34,6 +34,7 @@ import org.springframework.data.redis.core.convert.RedisData; import org.springframework.data.redis.repository.query.RedisOperationChain; import org.springframework.data.redis.repository.query.RedisOperationChain.PathAndValue; import org.springframework.data.redis.util.ByteUtils; +import org.springframework.util.CollectionUtils; /** * Redis specific {@link QueryEngine} implementation. @@ -67,9 +68,15 @@ class RedisQueryEngine extends QueryEngine Collection execute(final RedisOperationChain criteria, final Comparator sort, final int offset, final int rows, final Serializable keyspace, Class type) { + if (criteria == null + || (CollectionUtils.isEmpty(criteria.getOrSismember()) && CollectionUtils.isEmpty(criteria.getSismember()))) { + return (Collection) getAdapter().getAllOf(keyspace, offset, rows); + } + RedisCallback>> callback = new RedisCallback>>() { @Override @@ -99,8 +106,9 @@ class RedisQueryEngine extends QueryEngine= 0 && rows > 0) { - allKeys = allKeys.subList(Math.max(0, offset), Math.min(offset + rows, allKeys.size())); + int offsetToUse = Math.max(0, offset); + if (rows > 0) { + allKeys = allKeys.subList(Math.max(0, offsetToUse), Math.min(offsetToUse + rows, allKeys.size())); } for (byte[] id : allKeys) { @@ -171,8 +179,8 @@ class RedisQueryEngine extends QueryEngine query = new KeyValueQuery(criteria); - if (query.getCritieria().getSismember().size() == 1 && query.getCritieria().getOrSismember().size() == 1) { + if (query.getCritieria() != null && !CollectionUtils.isEmpty(query.getCritieria().getSismember()) + && !CollectionUtils.isEmpty(query.getCritieria().getOrSismember())) + if (query.getCritieria().getSismember().size() == 1 && query.getCritieria().getOrSismember().size() == 1) { - query.getCritieria().getOrSismember().add(query.getCritieria().getSismember().iterator().next()); - query.getCritieria().getSismember().clear(); - } + query.getCritieria().getOrSismember().add(query.getCritieria().getSismember().iterator().next()); + query.getCritieria().getSismember().clear(); + } if (sort != null) { query.setSort(sort); diff --git a/src/test/java/org/springframework/data/redis/repository/RedisRepositoryIntegrationTestBase.java b/src/test/java/org/springframework/data/redis/repository/RedisRepositoryIntegrationTestBase.java index 0af807318..e861318f9 100644 --- a/src/test/java/org/springframework/data/redis/repository/RedisRepositoryIntegrationTestBase.java +++ b/src/test/java/org/springframework/data/redis/repository/RedisRepositoryIntegrationTestBase.java @@ -15,10 +15,9 @@ */ package org.springframework.data.redis.repository; +import static org.hamcrest.CoreMatchers.*; import static org.hamcrest.collection.IsCollectionWithSize.*; import static org.hamcrest.collection.IsIterableContainingInAnyOrder.*; -import static org.hamcrest.core.Is.*; -import static org.hamcrest.core.IsCollectionContaining.*; import static org.junit.Assert.*; import java.io.Serializable; @@ -42,7 +41,7 @@ import org.springframework.data.redis.core.index.IndexConfiguration; import org.springframework.data.redis.core.index.IndexDefinition; import org.springframework.data.redis.core.index.Indexed; import org.springframework.data.redis.core.index.SimpleIndexDefinition; -import org.springframework.data.repository.CrudRepository; +import org.springframework.data.repository.PagingAndSortingRepository; /** * Base for testing Redis repository support in different configurations. @@ -190,7 +189,76 @@ public abstract class RedisRepositoryIntegrationTestBase { assertThat(eddardAndJon, containsInAnyOrder(eddard, jon)); } - public static interface PersonRepository extends CrudRepository { + /** + * @see DATAREDIS-547 + */ + @Test + public void shouldApplyFirstKeywordCorrectly() { + + Person eddard = new Person("eddard", "stark"); + Person robb = new Person("robb", "stark"); + Person jon = new Person("jon", "snow"); + + repo.save(Arrays.asList(eddard, robb, jon)); + + assertThat(repo.findFirstBy(), hasSize(1)); + } + + /** + * @see DATAREDIS-547 + */ + @Test + public void shouldApplyPageableCorrectlyWhenUsingFindAll() { + + Person eddard = new Person("eddard", "stark"); + Person robb = new Person("robb", "stark"); + Person jon = new Person("jon", "snow"); + + repo.save(Arrays.asList(eddard, robb, jon)); + + Page firstPage = repo.findAll(new PageRequest(0, 2)); + assertThat(firstPage.getContent(), hasSize(2)); + assertThat(repo.findAll(firstPage.nextPageable()).getContent(), hasSize(1)); + } + + /** + * @see DATAREDIS-547 + */ + @Test + public void shouldApplyTopKeywordCorrectly() { + + Person eddard = new Person("eddard", "stark"); + Person robb = new Person("robb", "stark"); + Person jon = new Person("jon", "snow"); + + repo.save(Arrays.asList(eddard, robb, jon)); + + assertThat(repo.findTop2By(), hasSize(2)); + } + + /** + * @see DATAREDIS-547 + */ + @Test + public void shouldApplyTopKeywordCorrectlyWhenCriteriaPresent() { + + Person eddard = new Person("eddard", "stark"); + Person tyrion = new Person("tyrion", "lannister"); + Person robb = new Person("robb", "stark"); + Person jon = new Person("jon", "snow"); + Person arya = new Person("arya", "stark"); + + repo.save(Arrays.asList(eddard, tyrion, robb, jon, arya)); + + List result = repo.findTop2ByLastname("stark"); + + assertThat(result, hasSize(2)); + for (Person p : result) { + assertThat(p.getLastname(), is("stark")); + } + } + + public static interface PersonRepository extends PagingAndSortingRepository { List findByFirstname(String firstname); @@ -201,6 +269,12 @@ public abstract class RedisRepositoryIntegrationTestBase { List findByFirstnameAndLastname(String firstname, String lastname); List findByFirstnameOrLastname(String firstname, String lastname); + + List findFirstBy(); + + List findTop2By(); + + List findTop2ByLastname(String lastname); } /**