You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by ak...@apache.org on 2020/06/05 14:27:14 UTC

[ignite] branch master updated: IGNITE-13104 Fixed incorrect logic in spring-data repositories for findAllById() and deleteAllById() methods. Code cleanup. #7886 - Fixes #7886.

This is an automated email from the ASF dual-hosted git repository.

akuznetsov pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git


The following commit(s) were added to refs/heads/master by this push:
     new e3c09bb  IGNITE-13104 Fixed incorrect logic in spring-data repositories for findAllById() and deleteAllById() methods. Code cleanup. #7886 - Fixes #7886.
e3c09bb is described below

commit e3c09bb36b8193ea0904be6e3b858f1fb0839410
Author: Alexey Kuznetsov <ak...@apache.org>
AuthorDate: Fri Jun 5 21:25:46 2020 +0700

    IGNITE-13104 Fixed incorrect logic in spring-data repositories for findAllById() and deleteAllById() methods. Code cleanup. #7886 - Fixes #7886.
    
    Signed-off-by: Alexey Kuznetsov <ak...@apache.org>
---
 .../repository/support/IgniteRepositoryImpl.java   |  51 +++---
 .../IgniteSpringDataCrudSelfExpressionTest.java    |  33 ++--
 .../springdata/IgniteSpringDataCrudSelfTest.java   | 196 ++++++++++----------
 .../IgniteSpringDataQueriesSelfTest.java           |  32 ++--
 .../springdata/misc/ApplicationConfiguration.java  |  23 +--
 .../ignite/springdata/misc/CacheNamesBean.java     |  11 +-
 .../org/apache/ignite/springdata/misc/Person.java  |  16 +-
 .../apache/ignite/springdata/misc/PersonKey.java}  |  34 +++-
 .../ignite/springdata/misc/PersonRepository.java   |   5 +-
 .../misc/PersonRepositoryWithCompoundKey.java}     |  22 +--
 .../springdata/misc/PersonSecondRepository.java    |   2 +-
 .../repository/support/IgniteRepositoryImpl.java   |  51 +++---
 .../IgniteSpringDataCrudSelfExpressionTest.java    |  33 ++--
 .../springdata/IgniteSpringDataCrudSelfTest.java   | 198 +++++++++++----------
 .../IgniteSpringDataQueriesSelfTest.java           |  18 +-
 .../springdata/misc/ApplicationConfiguration.java  |  23 +--
 .../ignite/springdata/misc/CacheNamesBean.java     |  12 +-
 .../org/apache/ignite/springdata/misc/Person.java  |  16 +-
 .../misc/{CacheNamesBean.java => PersonKey.java}   |  34 +++-
 .../ignite/springdata/misc/PersonRepository.java   |   5 +-
 ...n.java => PersonRepositoryWithCompoundKey.java} |  22 +--
 .../springdata/misc/PersonSecondRepository.java    |   2 +-
 .../repository/support/IgniteRepositoryImpl.java   |  51 +++---
 .../springdata/IgniteSpringDataCrudSelfTest.java   | 136 ++++++++------
 .../springdata/misc/ApplicationConfiguration.java  |  25 ++-
 .../org/apache/ignite/springdata/misc/Person.java  |  19 +-
 .../apache/ignite/springdata/misc/PersonKey.java}  |  34 +++-
 .../ignite/springdata/misc/PersonRepository.java   |   4 +-
 .../misc/PersonRepositoryWithCompoundKey.java}     |  22 +--
 29 files changed, 590 insertions(+), 540 deletions(-)

diff --git a/modules/spring-data-2.0/src/main/java/org/apache/ignite/springdata20/repository/support/IgniteRepositoryImpl.java b/modules/spring-data-2.0/src/main/java/org/apache/ignite/springdata20/repository/support/IgniteRepositoryImpl.java
index e0a932e..c9cfded 100644
--- a/modules/spring-data-2.0/src/main/java/org/apache/ignite/springdata20/repository/support/IgniteRepositoryImpl.java
+++ b/modules/spring-data-2.0/src/main/java/org/apache/ignite/springdata20/repository/support/IgniteRepositoryImpl.java
@@ -17,7 +17,6 @@
 package org.apache.ignite.springdata20.repository.support;
 
 import java.io.Serializable;
-import java.util.Collection;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Map;
@@ -30,6 +29,8 @@ import org.apache.ignite.cache.CachePeekMode;
 import org.apache.ignite.springdata20.repository.IgniteRepository;
 import org.springframework.context.annotation.Conditional;
 
+import static java.util.Collections.emptySet;
+
 /**
  * General Apache Ignite repository implementation.
  * This bean should've never been loaded by context directly, only via {@link IgniteRepositoryFactory}
@@ -105,20 +106,37 @@ public class IgniteRepositoryImpl<T, ID extends Serializable> implements IgniteR
         };
     }
 
-    /** {@inheritDoc} */
-    @Override public Iterable<T> findAllById(Iterable<ID> ids) {
+    /**
+     * @param ids Collection of IDs.
+     * @return Collection transformed to set.
+     */
+    private Set<ID> toSet(Iterable<ID> ids) {
         if (ids instanceof Set)
-            return cache.getAll((Set<ID>)ids).values();
+            return (Set<ID>)ids;
+
+        Iterator<ID> itr = ids.iterator();
+
+        if (!itr.hasNext())
+            return emptySet();
+
+        ID key = itr.next();
+
+        Set<ID> keys = key instanceof Comparable ? new TreeSet<>() : new HashSet<>();
 
-        if (ids instanceof Collection)
-            return cache.getAll(new HashSet<>((Collection<ID>)ids)).values();
+        keys.add(key);
 
-        TreeSet<ID> keys = new TreeSet<>();
+        while (itr.hasNext()) {
+            key = itr.next();
 
-        for (ID id : ids)
-            keys.add(id);
+            keys.add(key);
+        }
 
-        return cache.getAll(keys).values();
+        return keys;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Iterable<T> findAllById(Iterable<ID> ids) {
+        return cache.getAll(toSet(ids)).values();
     }
 
     /** {@inheritDoc} */
@@ -143,18 +161,7 @@ public class IgniteRepositoryImpl<T, ID extends Serializable> implements IgniteR
 
     /** {@inheritDoc} */
     @Override public void deleteAllById(Iterable<ID> ids) {
-        if (ids instanceof Set)
-            cache.removeAll((Set<ID>)ids);
-
-        if (ids instanceof Collection)
-            cache.removeAll(new HashSet<>((Collection<ID>)ids));
-
-        TreeSet<ID> keys = new TreeSet<>();
-
-        for (ID id : ids)
-            keys.add(id);
-
-        cache.removeAll(keys);
+        cache.removeAll(toSet(ids));
     }
 
     /** {@inheritDoc} */
diff --git a/modules/spring-data-2.0/src/test/java/org/apache/ignite/springdata/IgniteSpringDataCrudSelfExpressionTest.java b/modules/spring-data-2.0/src/test/java/org/apache/ignite/springdata/IgniteSpringDataCrudSelfExpressionTest.java
index f6c609f..11144e4 100644
--- a/modules/spring-data-2.0/src/test/java/org/apache/ignite/springdata/IgniteSpringDataCrudSelfExpressionTest.java
+++ b/modules/spring-data-2.0/src/test/java/org/apache/ignite/springdata/IgniteSpringDataCrudSelfExpressionTest.java
@@ -22,30 +22,34 @@ import org.apache.ignite.springdata.misc.ApplicationConfiguration;
 import org.apache.ignite.springdata.misc.Person;
 import org.apache.ignite.springdata.misc.PersonExpressionRepository;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 
 /**
  * Test with using repository which is configured by Spring EL
  */
 public class IgniteSpringDataCrudSelfExpressionTest extends GridCommonAbstractTest {
+    /** Number of entries to store */
+    private static final int CACHE_SIZE = 1000;
+
     /** Repository. */
     private static PersonExpressionRepository repo;
 
     /** Context. */
     private static AnnotationConfigApplicationContext ctx;
 
-    /** Number of entries to store */
-    private static int CACHE_SIZE = 1000;
+    /** */
+    @Rule
+    public final ExpectedException expected = ExpectedException.none();
 
     /** {@inheritDoc} */
     @Override protected void beforeTestsStarted() throws Exception {
         super.beforeTestsStarted();
 
         ctx = new AnnotationConfigApplicationContext();
-
         ctx.register(ApplicationConfiguration.class);
-
         ctx.refresh();
 
         repo = ctx.getBean(PersonExpressionRepository.class);
@@ -69,9 +73,7 @@ public class IgniteSpringDataCrudSelfExpressionTest extends GridCommonAbstractTe
         super.afterTest();
     }
 
-    /**
-     *
-     */
+    /** */
     private void fillInRepository() {
         for (int i = 0; i < CACHE_SIZE - 5; i++) {
             repo.save(i, new Person("person" + Integer.toHexString(i),
@@ -86,8 +88,8 @@ public class IgniteSpringDataCrudSelfExpressionTest extends GridCommonAbstractTe
     }
 
     /** {@inheritDoc} */
-    @Override protected void afterTestsStopped() throws Exception {
-        ctx.destroy();
+    @Override protected void afterTestsStopped() {
+        ctx.close();
     }
 
     /**
@@ -105,18 +107,13 @@ public class IgniteSpringDataCrudSelfExpressionTest extends GridCommonAbstractTe
 
         assertEquals(person, repo.findById(id).get());
 
-        try {
-            repo.save(person);
-
-            fail("Managed to save a Person without ID");
-        }
-        catch (UnsupportedOperationException e) {
-            //excepted
-        }
+        expected.expect(UnsupportedOperationException.class);
+        expected.expectMessage("Use IgniteRepository.save(key,value) method instead.");
+        repo.save(person);
     }
 
     /**
-     * Tests SpEL exphression.
+     * Tests SpEL expression.
      */
     @Test
     public void testCacheCount() {
diff --git a/modules/spring-data-2.0/src/test/java/org/apache/ignite/springdata/IgniteSpringDataCrudSelfTest.java b/modules/spring-data-2.0/src/test/java/org/apache/ignite/springdata/IgniteSpringDataCrudSelfTest.java
index 7210d64..b2dce2f 100644
--- a/modules/spring-data-2.0/src/test/java/org/apache/ignite/springdata/IgniteSpringDataCrudSelfTest.java
+++ b/modules/spring-data-2.0/src/test/java/org/apache/ignite/springdata/IgniteSpringDataCrudSelfTest.java
@@ -23,37 +23,48 @@ import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Optional;
 import java.util.TreeSet;
+import javax.cache.CacheException;
 import org.apache.ignite.springdata.misc.ApplicationConfiguration;
 import org.apache.ignite.springdata.misc.Person;
+import org.apache.ignite.springdata.misc.PersonKey;
 import org.apache.ignite.springdata.misc.PersonRepository;
+import org.apache.ignite.springdata.misc.PersonRepositoryWithCompoundKey;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 
 /**
- *
+ * CRUD tests.
  */
 public class IgniteSpringDataCrudSelfTest extends GridCommonAbstractTest {
+    /** Number of entries to store */
+    private static final int CACHE_SIZE = 1000;
+
     /** Repository. */
     private static PersonRepository repo;
 
+    /** Repository. */
+    private static PersonRepositoryWithCompoundKey repoWithCompoundKey;
+
     /** Context. */
     private static AnnotationConfigApplicationContext ctx;
 
-    /** Number of entries to store */
-    private static int CACHE_SIZE = 1000;
+    /** */
+    @Rule
+    public final ExpectedException expected = ExpectedException.none();
 
     /** {@inheritDoc} */
     @Override protected void beforeTestsStarted() throws Exception {
         super.beforeTestsStarted();
 
         ctx = new AnnotationConfigApplicationContext();
-
         ctx.register(ApplicationConfiguration.class);
-
         ctx.refresh();
 
         repo = ctx.getBean(PersonRepository.class);
+        repoWithCompoundKey = ctx.getBean(PersonRepositoryWithCompoundKey.class);
     }
 
     /** {@inheritDoc} */
@@ -74,9 +85,7 @@ public class IgniteSpringDataCrudSelfTest extends GridCommonAbstractTest {
         super.afterTest();
     }
 
-    /**
-     *
-     */
+    /** */
     private void fillInRepository() {
         for (int i = 0; i < CACHE_SIZE - 5; i++) {
             repo.save(i, new Person("person" + Integer.toHexString(i),
@@ -91,13 +100,11 @@ public class IgniteSpringDataCrudSelfTest extends GridCommonAbstractTest {
     }
 
     /** {@inheritDoc} */
-    @Override protected void afterTestsStopped() throws Exception {
-        ctx.destroy();
+    @Override protected void afterTestsStopped() {
+        ctx.close();
     }
 
-    /**
-     *
-     */
+    /** */
     @Test
     public void testPutGet() {
         Person person = new Person("some_name", "some_surname");
@@ -110,19 +117,12 @@ public class IgniteSpringDataCrudSelfTest extends GridCommonAbstractTest {
 
         assertEquals(person, repo.findById(id).get());
 
-        try {
-            repo.save(person);
-
-            fail("Managed to save a Person without ID");
-        }
-        catch (UnsupportedOperationException e) {
-            //excepted
-        }
+        expected.expect(UnsupportedOperationException.class);
+        expected.expectMessage("Use IgniteRepository.save(key,value) method instead.");
+        repo.save(person);
     }
 
-    /**
-     *
-     */
+    /** */
     @Test
     public void testPutAllGetAll() {
         LinkedHashMap<Integer, Person> map = new LinkedHashMap<>();
@@ -139,14 +139,9 @@ public class IgniteSpringDataCrudSelfTest extends GridCommonAbstractTest {
         while (persons.hasNext())
             assertEquals(origPersons.next(), persons.next());
 
-        try {
-            repo.saveAll(map.values());
-
-            fail("Managed to save a list of Persons with ids");
-        }
-        catch (UnsupportedOperationException e) {
-            //expected
-        }
+        expected.expect(UnsupportedOperationException.class);
+        expected.expectMessage("Use IgniteRepository.save(Map<keys,value>) method instead.");
+        repo.saveAll(map.values());
 
         persons = repo.findAllById(map.keySet()).iterator();
 
@@ -160,9 +155,7 @@ public class IgniteSpringDataCrudSelfTest extends GridCommonAbstractTest {
         assertEquals(map.size(), counter);
     }
 
-    /**
-     *
-     */
+    /** */
     @Test
     public void testGetAll() {
         assertEquals(CACHE_SIZE, repo.count());
@@ -179,9 +172,7 @@ public class IgniteSpringDataCrudSelfTest extends GridCommonAbstractTest {
         assertEquals(repo.count(), counter);
     }
 
-    /**
-     *
-     */
+    /** */
     @Test
     public void testDelete() {
         assertEquals(CACHE_SIZE, repo.count());
@@ -191,19 +182,12 @@ public class IgniteSpringDataCrudSelfTest extends GridCommonAbstractTest {
         assertEquals(CACHE_SIZE - 1, repo.count());
         assertEquals(Optional.empty(),repo.findById(0));
 
-        try {
-            repo.delete(new Person("", ""));
-
-            fail("Managed to delete a Person without id");
-        }
-        catch (UnsupportedOperationException e) {
-            //expected
-        }
+        expected.expect(UnsupportedOperationException.class);
+        expected.expectMessage("Use IgniteRepository.deleteById(key) method instead.");
+        repo.delete(new Person("", ""));
     }
 
-    /**
-     *
-     */
+    /** */
     @Test
     public void testDeleteSet() {
         assertEquals(CACHE_SIZE, repo.count());
@@ -217,24 +201,17 @@ public class IgniteSpringDataCrudSelfTest extends GridCommonAbstractTest {
 
         assertEquals(CACHE_SIZE / 2, repo.count());
 
-        try {
-            ArrayList<Person> persons = new ArrayList<>();
+        ArrayList<Person> persons = new ArrayList<>();
 
-            for (int i = 0; i < 3; i++)
-                persons.add(new Person(String.valueOf(i), String.valueOf(i)));
+        for (int i = 0; i < 3; i++)
+            persons.add(new Person(String.valueOf(i), String.valueOf(i)));
 
-            repo.deleteAll(persons);
-
-            fail("Managed to delete Persons without ids");
-        }
-        catch (UnsupportedOperationException e) {
-            //expected
-        }
+        expected.expect(UnsupportedOperationException.class);
+        expected.expectMessage("Use IgniteRepository.deleteAllById(keys) method instead.");
+        repo.deleteAll(persons);
     }
 
-    /**
-     *
-     */
+    /** */
     @Test
     public void testDeleteAll() {
         assertEquals(CACHE_SIZE, repo.count());
@@ -245,7 +222,7 @@ public class IgniteSpringDataCrudSelfTest extends GridCommonAbstractTest {
     }
 
     /**
-     * Delete existing record
+     * Delete existing record.
      */
     @Test
     public void testDeleteByFirstName() {
@@ -257,7 +234,7 @@ public class IgniteSpringDataCrudSelfTest extends GridCommonAbstractTest {
     }
 
     /**
-     * Delete NON existing record
+     * Delete NON existing record.
      */
     @Test
     public void testDeleteExpression() {
@@ -267,58 +244,54 @@ public class IgniteSpringDataCrudSelfTest extends GridCommonAbstractTest {
     }
 
     /**
-     * Delete Multiple records due to where
+     * Delete Multiple records due to where.
      */
     @Test
     public void testDeleteExpressionMultiple() {
-        long count = repo.countByFirstName("nonUniquePerson");
-        long cnt = repo.deleteByFirstName("nonUniquePerson");
+        long cnt = repo.countByFirstName("nonUniquePerson");
+        long cntDeleted = repo.deleteByFirstName("nonUniquePerson");
 
-        assertEquals(cnt, count);
+        assertEquals(cntDeleted, cnt);
     }
 
     /**
-     * Remove should do the same than Delete
+     * Remove should do the same than Delete.
      */
     @Test
     public void testRemoveExpression() {
         repo.removeByFirstName("person3f");
 
-        long count = repo.count();
-        assertEquals(CACHE_SIZE - 1, count);
+        long cnt = repo.count();
+        assertEquals(CACHE_SIZE - 1, cnt);
     }
 
     /**
-     * Delete unique record using lower case key word
+     * Delete unique record using lower case key word.
      */
     @Test
     public void testDeleteQuery() {
         repo.deleteBySecondNameLowerCase("uniqueLastName");
 
-        long countAfter = repo.count();
-        assertEquals(CACHE_SIZE - 1, countAfter);
+        long cntAfter = repo.count();
+        assertEquals(CACHE_SIZE - 1, cntAfter);
     }
 
     /**
-     * Try to delete with a wrong @Query
+     * Try to delete with a wrong @Query.
      */
     @Test
     public void testWrongDeleteQuery() {
-        long countBefore = repo.countByFirstNameLike("person3f");
+        long cntBefore = repo.countByFirstNameLike("person3f");
 
-        try {
-            repo.deleteWrongByFirstNameQuery("person3f");
-        }
-        catch (Exception e) {
-            //expected
-        }
+        expected.expect(CacheException.class);
+        repo.deleteWrongByFirstNameQuery("person3f");
 
-        long countAfter = repo.countByFirstNameLike("person3f");
-        assertEquals(countBefore, countAfter);
+        long cntAfter = repo.countByFirstNameLike("person3f");
+        assertEquals(cntBefore, cntAfter);
     }
 
     /**
-     * Update with a @Query a record
+     * Update with a @Query a record.
      */
     @Test
     public void testUpdateQueryMixedCase() {
@@ -332,22 +305,55 @@ public class IgniteSpringDataCrudSelfTest extends GridCommonAbstractTest {
     }
 
     /**
-     * Update with a wrong @Query
+     * Update with a wrong @Query.
      */
     @Test
     public void testWrongUpdateQuery() {
-        final String newSecondName = "updatedUniqueSecondName";
-        int rowsUpdated = 0;
-        try {
-            rowsUpdated = repo.setWrongFixedSecondName(newSecondName, "uniquePerson");
-        }
-        catch (Exception e) {
-            //expected
-        }
+        expected.expect(CacheException.class);
+        int rowsUpdated = repo.setWrongFixedSecondName("updatedUniqueSecondName", "uniquePerson");
 
         assertEquals(0, rowsUpdated);
 
         List<Person> person = repo.findByFirstName("uniquePerson");
         assertEquals(person.get(0).getSecondName(), "uniqueLastName");
     }
+
+    /** */
+    @Test
+    public void shouldDeleteAllById() {
+        List<PersonKey> ids = prepareDataWithNonComparableKeys();
+
+        repoWithCompoundKey.deleteAllById(ids);
+
+        assertEquals(0, repoWithCompoundKey.count());
+    }
+
+    /** */
+    @Test
+    public void shouldFindAllById() {
+        List<PersonKey> ids = prepareDataWithNonComparableKeys();
+
+        Iterable<Person> res = repoWithCompoundKey.findAllById(ids);
+
+        assertEquals(2, res.spliterator().estimateSize());
+    }
+
+    /** */
+    private List<PersonKey> prepareDataWithNonComparableKeys() {
+        List<PersonKey> ids = new ArrayList<>();
+
+        PersonKey key = new PersonKey(1, 1);
+        ids.add(key);
+
+        repoWithCompoundKey.save(key, new Person("test1", "test1"));
+
+        key = new PersonKey(2, 2);
+        ids.add(key);
+
+        repoWithCompoundKey.save(key, new Person("test2", "test2"));
+
+        assertEquals(2, repoWithCompoundKey.count());
+
+        return ids;
+    }
 }
diff --git a/modules/spring-data-2.0/src/test/java/org/apache/ignite/springdata/IgniteSpringDataQueriesSelfTest.java b/modules/spring-data-2.0/src/test/java/org/apache/ignite/springdata/IgniteSpringDataQueriesSelfTest.java
index aff8054..e1ed7f8 100644
--- a/modules/spring-data-2.0/src/test/java/org/apache/ignite/springdata/IgniteSpringDataQueriesSelfTest.java
+++ b/modules/spring-data-2.0/src/test/java/org/apache/ignite/springdata/IgniteSpringDataQueriesSelfTest.java
@@ -22,8 +22,8 @@ import java.util.Iterator;
 import java.util.List;
 import javax.cache.Cache;
 import org.apache.ignite.springdata.misc.ApplicationConfiguration;
-import org.apache.ignite.springdata.misc.PersonRepository;
 import org.apache.ignite.springdata.misc.Person;
+import org.apache.ignite.springdata.misc.PersonRepository;
 import org.apache.ignite.springdata.misc.PersonSecondRepository;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
 import org.junit.Test;
@@ -36,6 +36,9 @@ import org.springframework.data.domain.Sort;
  *
  */
 public class IgniteSpringDataQueriesSelfTest extends GridCommonAbstractTest {
+    /** Number of entries to store */
+    private static final int CACHE_SIZE = 1000;
+
     /** Repository. */
     private static PersonRepository repo;
 
@@ -45,9 +48,6 @@ public class IgniteSpringDataQueriesSelfTest extends GridCommonAbstractTest {
     /** Context. */
     private static AnnotationConfigApplicationContext ctx;
 
-    /** Number of entries to store */
-    private static int CACHE_SIZE = 1000;
-
     /**
      * Performs context initialization before tests.
      */
@@ -55,9 +55,7 @@ public class IgniteSpringDataQueriesSelfTest extends GridCommonAbstractTest {
         super.beforeTestsStarted();
 
         ctx = new AnnotationConfigApplicationContext();
-
         ctx.register(ApplicationConfiguration.class);
-
         ctx.refresh();
 
         repo = ctx.getBean(PersonRepository.class);
@@ -72,8 +70,8 @@ public class IgniteSpringDataQueriesSelfTest extends GridCommonAbstractTest {
     /**
      * Performs context destroy after tests.
      */
-    @Override protected void afterTestsStopped() throws Exception {
-        ctx.destroy();
+    @Override protected void afterTestsStopped() {
+        ctx.close();
     }
 
     /** */
@@ -158,14 +156,14 @@ public class IgniteSpringDataQueriesSelfTest extends GridCommonAbstractTest {
     /** */
     @Test
     public void testPageable() {
-        PageRequest pageable = new PageRequest(1, 5, Sort.Direction.DESC, "firstName");
-
-        HashSet<String> firstNames = new HashSet<>();
+        PageRequest pageable = PageRequest.of(1, 5, Sort.Direction.DESC, "firstName");
 
         List<Person> pageable1 = repo.findByFirstNameRegex("^[a-z]+$", pageable);
 
         assertEquals(5, pageable1.size());
 
+        HashSet<String> firstNames = new HashSet<>();
+
         for (Person person : pageable1) {
             firstNames.add(person.getFirstName());
 
@@ -198,7 +196,7 @@ public class IgniteSpringDataQueriesSelfTest extends GridCommonAbstractTest {
     /** */
     @Test
     public void testQueryWithSort() {
-        List<Person> persons = repo.queryWithSort("^[a-z]+$", new Sort(Sort.Direction.DESC, "secondName"));
+        List<Person> persons = repo.queryWithSort("^[a-z]+$", Sort.by(Sort.Direction.DESC, "secondName"));
 
         Person previous = persons.get(0);
 
@@ -214,7 +212,7 @@ public class IgniteSpringDataQueriesSelfTest extends GridCommonAbstractTest {
     /** */
     @Test
     public void testQueryWithPaging() {
-        List<Person> persons = repo.queryWithPageable("^[a-z]+$", new PageRequest(1, 7, Sort.Direction.DESC, "secondName"));
+        List<Person> persons = repo.queryWithPageable("^[a-z]+$", PageRequest.of(1, 7, Sort.Direction.DESC, "secondName"));
 
         assertEquals(7, persons.size());
 
@@ -232,7 +230,7 @@ public class IgniteSpringDataQueriesSelfTest extends GridCommonAbstractTest {
     /** */
     @Test
     public void testQueryFields() {
-        List<String> persons = repo.selectField("^[a-z]+$", new PageRequest(1, 7, Sort.Direction.DESC, "secondName"));
+        List<String> persons = repo.selectField("^[a-z]+$", PageRequest.of(1, 7, Sort.Direction.DESC, "secondName"));
 
         assertEquals(7, persons.size());
     }
@@ -271,7 +269,7 @@ public class IgniteSpringDataQueriesSelfTest extends GridCommonAbstractTest {
     /** */
     @Test
     public void testSelectSeveralFields() {
-        List<List> lists = repo.selectSeveralField("^[a-z]+$", new PageRequest(2, 6));
+        List<List> lists = repo.selectSeveralField("^[a-z]+$", PageRequest.of(2, 6));
 
         assertEquals(6, lists.size());
 
@@ -293,7 +291,7 @@ public class IgniteSpringDataQueriesSelfTest extends GridCommonAbstractTest {
     /** */
     @Test
     public void testSliceOfCacheEntries() {
-        Slice<Cache.Entry<Integer, Person>> slice = repo2.findBySecondNameIsNot("lastName18", new PageRequest(3, 4));
+        Slice<Cache.Entry<Integer, Person>> slice = repo2.findBySecondNameIsNot("lastName18", PageRequest.of(3, 4));
 
         assertEquals(4, slice.getSize());
 
@@ -304,7 +302,7 @@ public class IgniteSpringDataQueriesSelfTest extends GridCommonAbstractTest {
     /** */
     @Test
     public void testSliceOfLists() {
-        Slice<List> lists = repo2.querySliceOfList("^[a-z]+$", new PageRequest(0, 3));
+        Slice<List> lists = repo2.querySliceOfList("^[a-z]+$", PageRequest.of(0, 3));
 
         assertEquals(3, lists.getSize());
 
diff --git a/modules/spring-data-2.0/src/test/java/org/apache/ignite/springdata/misc/ApplicationConfiguration.java b/modules/spring-data-2.0/src/test/java/org/apache/ignite/springdata/misc/ApplicationConfiguration.java
index e700c9d..950bd55 100644
--- a/modules/spring-data-2.0/src/test/java/org/apache/ignite/springdata/misc/ApplicationConfiguration.java
+++ b/modules/spring-data-2.0/src/test/java/org/apache/ignite/springdata/misc/ApplicationConfiguration.java
@@ -23,9 +23,9 @@ import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
 import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
+import org.apache.ignite.springdata20.repository.config.EnableIgniteRepositories;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
-import org.apache.ignite.springdata20.repository.config.EnableIgniteRepositories;
 
 /**
  *
@@ -33,7 +33,6 @@ import org.apache.ignite.springdata20.repository.config.EnableIgniteRepositories
 @Configuration
 @EnableIgniteRepositories
 public class ApplicationConfiguration {
-
     /**
      * The bean with cache names
      */
@@ -51,19 +50,13 @@ public class ApplicationConfiguration {
      */
     @Bean
     public Ignite igniteInstance() {
-        IgniteConfiguration cfg = new IgniteConfiguration();
-
-        CacheConfiguration ccfg = new CacheConfiguration("PersonCache");
-
-        ccfg.setIndexedTypes(Integer.class, Person.class);
-
-        cfg.setCacheConfiguration(ccfg);
-
-        TcpDiscoverySpi spi = new TcpDiscoverySpi();
-
-        spi.setIpFinder(new TcpDiscoveryVmIpFinder(true));
-
-        cfg.setDiscoverySpi(spi);
+        IgniteConfiguration cfg = new IgniteConfiguration()
+            .setCacheConfiguration(
+                new CacheConfiguration<Integer, Person>("PersonCache")
+                    .setIndexedTypes(Integer.class, Person.class),
+                new CacheConfiguration<PersonKey, Person>("PersonWithKeyCache")
+            )
+            .setDiscoverySpi(new TcpDiscoverySpi().setIpFinder(new TcpDiscoveryVmIpFinder(true)));
 
         return Ignition.start(cfg);
     }
diff --git a/modules/spring-data-2.0/src/test/java/org/apache/ignite/springdata/misc/CacheNamesBean.java b/modules/spring-data-2.0/src/test/java/org/apache/ignite/springdata/misc/CacheNamesBean.java
index ae041ff..6185744 100644
--- a/modules/spring-data-2.0/src/test/java/org/apache/ignite/springdata/misc/CacheNamesBean.java
+++ b/modules/spring-data-2.0/src/test/java/org/apache/ignite/springdata/misc/CacheNamesBean.java
@@ -18,21 +18,24 @@
 package org.apache.ignite.springdata.misc;
 
 /**
- * The bean with cache names
+ * The bean with cache names.
  */
 public class CacheNamesBean {
-
+    /** */
     private String personCacheName;
 
     /**
-     * Get name of cache for persons
+     * Get name of cache for persons.
      *
-     * @return name of cache
+     * @return Name of cache.
      */
     public String getPersonCacheName() {
         return personCacheName;
     }
 
+    /**
+     * @param personCacheName Name of cache.
+     */
     public void setPersonCacheName(String personCacheName) {
         this.personCacheName = personCacheName;
     }
diff --git a/modules/spring-data-2.0/src/test/java/org/apache/ignite/springdata/misc/Person.java b/modules/spring-data-2.0/src/test/java/org/apache/ignite/springdata/misc/Person.java
index 38aab10..154937f 100644
--- a/modules/spring-data-2.0/src/test/java/org/apache/ignite/springdata/misc/Person.java
+++ b/modules/spring-data-2.0/src/test/java/org/apache/ignite/springdata/misc/Person.java
@@ -17,8 +17,12 @@
 
 package org.apache.ignite.springdata.misc;
 
+import java.util.Objects;
 import org.apache.ignite.cache.query.annotations.QuerySqlField;
 
+/**
+ * DTO class.
+ */
 public class Person {
     /** First name. */
     @QuerySqlField(index = true)
@@ -77,22 +81,18 @@ public class Person {
     @Override public boolean equals(Object o) {
         if (this == o)
             return true;
+
         if (o == null || getClass() != o.getClass())
             return false;
 
         Person person = (Person)o;
 
-        if (firstName != null ? !firstName.equals(person.firstName) : person.firstName != null)
-            return false;
-
-        return secondName != null ? secondName.equals(person.secondName) : person.secondName == null;
-
+        return Objects.equals(firstName, person.firstName) &&
+            Objects.equals(secondName, person.secondName);
     }
 
     /** {@inheritDoc} */
     @Override public int hashCode() {
-        int result = firstName != null ? firstName.hashCode() : 0;
-        result = 31 * result + (secondName != null ? secondName.hashCode() : 0);
-        return result;
+        return Objects.hash(firstName, secondName);
     }
 }
diff --git a/modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/misc/CacheNamesBean.java b/modules/spring-data-2.0/src/test/java/org/apache/ignite/springdata/misc/PersonKey.java
similarity index 65%
copy from modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/misc/CacheNamesBean.java
copy to modules/spring-data-2.0/src/test/java/org/apache/ignite/springdata/misc/PersonKey.java
index 464a6c1..2537c57 100644
--- a/modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/misc/CacheNamesBean.java
+++ b/modules/spring-data-2.0/src/test/java/org/apache/ignite/springdata/misc/PersonKey.java
@@ -17,22 +17,38 @@
 
 package org.apache.ignite.springdata.misc;
 
+import java.io.Serializable;
+
 /**
- * The bean with cache names
+ * Compound key.
  */
-public class CacheNamesBean {
+public class PersonKey implements Serializable {
+    /** */
+    private int id1;
 
-    private String personCacheName;
+    /** */
+    private int id2;
 
     /**
-     *  Get name of cache for persons
-     * @return name of cache
+     * @param id1 ID1.
+     * @param id2 ID2.
      */
-    public String getPersonCacheName() {
-        return personCacheName;
+    public PersonKey(int id1, int id2) {
+        this.id1 = id1;
+        this.id2 = id2;
     }
 
-    public void setPersonCacheName(String personCacheName) {
-        this.personCacheName = personCacheName;
+    /**
+     * @return ID1
+     */
+    public int getId1() {
+        return id1;
+    }
+
+    /**
+     * @return ID1
+     */
+    public int getId2() {
+        return id1;
     }
 }
diff --git a/modules/spring-data-2.0/src/test/java/org/apache/ignite/springdata/misc/PersonRepository.java b/modules/spring-data-2.0/src/test/java/org/apache/ignite/springdata/misc/PersonRepository.java
index bb2b93f..0b9d4df 100644
--- a/modules/spring-data-2.0/src/test/java/org/apache/ignite/springdata/misc/PersonRepository.java
+++ b/modules/spring-data-2.0/src/test/java/org/apache/ignite/springdata/misc/PersonRepository.java
@@ -1,4 +1,3 @@
-
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -21,14 +20,14 @@ package org.apache.ignite.springdata.misc;
 import java.util.Collection;
 import java.util.List;
 import javax.cache.Cache;
+import org.apache.ignite.springdata20.repository.IgniteRepository;
 import org.apache.ignite.springdata20.repository.config.Query;
 import org.apache.ignite.springdata20.repository.config.RepositoryConfig;
 import org.springframework.data.domain.Pageable;
 import org.springframework.data.domain.Sort;
-import org.apache.ignite.springdata20.repository.IgniteRepository;
 
 /**
- *
+ * Test repository.
  */
 @RepositoryConfig(cacheName = "PersonCache")
 public interface PersonRepository extends IgniteRepository<Person, Integer> {
diff --git a/modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/misc/CacheNamesBean.java b/modules/spring-data-2.0/src/test/java/org/apache/ignite/springdata/misc/PersonRepositoryWithCompoundKey.java
similarity index 69%
copy from modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/misc/CacheNamesBean.java
copy to modules/spring-data-2.0/src/test/java/org/apache/ignite/springdata/misc/PersonRepositoryWithCompoundKey.java
index 464a6c1..156bbb3 100644
--- a/modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/misc/CacheNamesBean.java
+++ b/modules/spring-data-2.0/src/test/java/org/apache/ignite/springdata/misc/PersonRepositoryWithCompoundKey.java
@@ -17,22 +17,12 @@
 
 package org.apache.ignite.springdata.misc;
 
+import org.apache.ignite.springdata20.repository.IgniteRepository;
+import org.apache.ignite.springdata20.repository.config.RepositoryConfig;
+
 /**
- * The bean with cache names
+ * Test repository.
  */
-public class CacheNamesBean {
-
-    private String personCacheName;
-
-    /**
-     *  Get name of cache for persons
-     * @return name of cache
-     */
-    public String getPersonCacheName() {
-        return personCacheName;
-    }
-
-    public void setPersonCacheName(String personCacheName) {
-        this.personCacheName = personCacheName;
-    }
+@RepositoryConfig(cacheName = "PersonWithKeyCache")
+public interface PersonRepositoryWithCompoundKey extends IgniteRepository<Person, PersonKey> {
 }
diff --git a/modules/spring-data-2.0/src/test/java/org/apache/ignite/springdata/misc/PersonSecondRepository.java b/modules/spring-data-2.0/src/test/java/org/apache/ignite/springdata/misc/PersonSecondRepository.java
index bb1df0f..2bc713c 100644
--- a/modules/spring-data-2.0/src/test/java/org/apache/ignite/springdata/misc/PersonSecondRepository.java
+++ b/modules/spring-data-2.0/src/test/java/org/apache/ignite/springdata/misc/PersonSecondRepository.java
@@ -27,7 +27,7 @@ import org.springframework.data.domain.PageRequest;
 import org.springframework.data.domain.Slice;
 
 /**
- *
+ * Test repository.
  */
 @RepositoryConfig(cacheName = "PersonCache")
 public interface PersonSecondRepository extends IgniteRepository<Person, Integer> {
diff --git a/modules/spring-data-2.2/src/main/java/org/apache/ignite/springdata22/repository/support/IgniteRepositoryImpl.java b/modules/spring-data-2.2/src/main/java/org/apache/ignite/springdata22/repository/support/IgniteRepositoryImpl.java
index f6f491a..7db6543 100644
--- a/modules/spring-data-2.2/src/main/java/org/apache/ignite/springdata22/repository/support/IgniteRepositoryImpl.java
+++ b/modules/spring-data-2.2/src/main/java/org/apache/ignite/springdata22/repository/support/IgniteRepositoryImpl.java
@@ -17,7 +17,6 @@
 package org.apache.ignite.springdata22.repository.support;
 
 import java.io.Serializable;
-import java.util.Collection;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Map;
@@ -30,6 +29,8 @@ import org.apache.ignite.cache.CachePeekMode;
 import org.apache.ignite.springdata22.repository.IgniteRepository;
 import org.springframework.context.annotation.Conditional;
 
+import static java.util.Collections.emptySet;
+
 /**
  * General Apache Ignite repository implementation.
  * This bean should've never been loaded by context directly, only via {@link IgniteRepositoryFactory}
@@ -105,20 +106,37 @@ public class IgniteRepositoryImpl<T, ID extends Serializable> implements IgniteR
         };
     }
 
-    /** {@inheritDoc} */
-    @Override public Iterable<T> findAllById(Iterable<ID> ids) {
+    /**
+     * @param ids Collection of IDs.
+     * @return Collection transformed to set.
+     */
+    private Set<ID> toSet(Iterable<ID> ids) {
         if (ids instanceof Set)
-            return cache.getAll((Set<ID>)ids).values();
+            return (Set<ID>)ids;
+
+        Iterator<ID> itr = ids.iterator();
+
+        if (!itr.hasNext())
+            return emptySet();
+
+        ID key = itr.next();
+
+        Set<ID> keys = key instanceof Comparable ? new TreeSet<>() : new HashSet<>();
 
-        if (ids instanceof Collection)
-            return cache.getAll(new HashSet<>((Collection<ID>)ids)).values();
+        keys.add(key);
 
-        TreeSet<ID> keys = new TreeSet<>();
+        while (itr.hasNext()) {
+            key = itr.next();
 
-        for (ID id : ids)
-            keys.add(id);
+            keys.add(key);
+        }
 
-        return cache.getAll(keys).values();
+        return keys;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Iterable<T> findAllById(Iterable<ID> ids) {
+        return cache.getAll(toSet(ids)).values();
     }
 
     /** {@inheritDoc} */
@@ -143,18 +161,7 @@ public class IgniteRepositoryImpl<T, ID extends Serializable> implements IgniteR
 
     /** {@inheritDoc} */
     @Override public void deleteAllById(Iterable<ID> ids) {
-        if (ids instanceof Set)
-            cache.removeAll((Set<ID>)ids);
-
-        if (ids instanceof Collection)
-            cache.removeAll(new HashSet<>((Collection<ID>)ids));
-
-        TreeSet<ID> keys = new TreeSet<>();
-
-        for (ID id : ids)
-            keys.add(id);
-
-        cache.removeAll(keys);
+        cache.removeAll(toSet(ids));
     }
 
     /** {@inheritDoc} */
diff --git a/modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/IgniteSpringDataCrudSelfExpressionTest.java b/modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/IgniteSpringDataCrudSelfExpressionTest.java
index f6c609f..11144e4 100644
--- a/modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/IgniteSpringDataCrudSelfExpressionTest.java
+++ b/modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/IgniteSpringDataCrudSelfExpressionTest.java
@@ -22,30 +22,34 @@ import org.apache.ignite.springdata.misc.ApplicationConfiguration;
 import org.apache.ignite.springdata.misc.Person;
 import org.apache.ignite.springdata.misc.PersonExpressionRepository;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 
 /**
  * Test with using repository which is configured by Spring EL
  */
 public class IgniteSpringDataCrudSelfExpressionTest extends GridCommonAbstractTest {
+    /** Number of entries to store */
+    private static final int CACHE_SIZE = 1000;
+
     /** Repository. */
     private static PersonExpressionRepository repo;
 
     /** Context. */
     private static AnnotationConfigApplicationContext ctx;
 
-    /** Number of entries to store */
-    private static int CACHE_SIZE = 1000;
+    /** */
+    @Rule
+    public final ExpectedException expected = ExpectedException.none();
 
     /** {@inheritDoc} */
     @Override protected void beforeTestsStarted() throws Exception {
         super.beforeTestsStarted();
 
         ctx = new AnnotationConfigApplicationContext();
-
         ctx.register(ApplicationConfiguration.class);
-
         ctx.refresh();
 
         repo = ctx.getBean(PersonExpressionRepository.class);
@@ -69,9 +73,7 @@ public class IgniteSpringDataCrudSelfExpressionTest extends GridCommonAbstractTe
         super.afterTest();
     }
 
-    /**
-     *
-     */
+    /** */
     private void fillInRepository() {
         for (int i = 0; i < CACHE_SIZE - 5; i++) {
             repo.save(i, new Person("person" + Integer.toHexString(i),
@@ -86,8 +88,8 @@ public class IgniteSpringDataCrudSelfExpressionTest extends GridCommonAbstractTe
     }
 
     /** {@inheritDoc} */
-    @Override protected void afterTestsStopped() throws Exception {
-        ctx.destroy();
+    @Override protected void afterTestsStopped() {
+        ctx.close();
     }
 
     /**
@@ -105,18 +107,13 @@ public class IgniteSpringDataCrudSelfExpressionTest extends GridCommonAbstractTe
 
         assertEquals(person, repo.findById(id).get());
 
-        try {
-            repo.save(person);
-
-            fail("Managed to save a Person without ID");
-        }
-        catch (UnsupportedOperationException e) {
-            //excepted
-        }
+        expected.expect(UnsupportedOperationException.class);
+        expected.expectMessage("Use IgniteRepository.save(key,value) method instead.");
+        repo.save(person);
     }
 
     /**
-     * Tests SpEL exphression.
+     * Tests SpEL expression.
      */
     @Test
     public void testCacheCount() {
diff --git a/modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/IgniteSpringDataCrudSelfTest.java b/modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/IgniteSpringDataCrudSelfTest.java
index a4cf8d3..19ee296 100644
--- a/modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/IgniteSpringDataCrudSelfTest.java
+++ b/modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/IgniteSpringDataCrudSelfTest.java
@@ -23,37 +23,48 @@ import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Optional;
 import java.util.TreeSet;
+import javax.cache.CacheException;
 import org.apache.ignite.springdata.misc.ApplicationConfiguration;
 import org.apache.ignite.springdata.misc.Person;
+import org.apache.ignite.springdata.misc.PersonKey;
 import org.apache.ignite.springdata.misc.PersonRepository;
+import org.apache.ignite.springdata.misc.PersonRepositoryWithCompoundKey;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 
 /**
- *
+ * CRUD tests.
  */
 public class IgniteSpringDataCrudSelfTest extends GridCommonAbstractTest {
+    /** Number of entries to store */
+    private static final int CACHE_SIZE = 1000;
+
     /** Repository. */
     private static PersonRepository repo;
 
+    /** Repository. */
+    private static PersonRepositoryWithCompoundKey repoWithCompoundKey;
+
     /** Context. */
     private static AnnotationConfigApplicationContext ctx;
 
-    /** Number of entries to store */
-    private static int CACHE_SIZE = 1000;
+    /** */
+    @Rule
+    public final ExpectedException expected = ExpectedException.none();
 
     /** {@inheritDoc} */
     @Override protected void beforeTestsStarted() throws Exception {
         super.beforeTestsStarted();
 
         ctx = new AnnotationConfigApplicationContext();
-
         ctx.register(ApplicationConfiguration.class);
-
         ctx.refresh();
 
         repo = ctx.getBean(PersonRepository.class);
+        repoWithCompoundKey = ctx.getBean(PersonRepositoryWithCompoundKey.class);
     }
 
     /** {@inheritDoc} */
@@ -74,9 +85,7 @@ public class IgniteSpringDataCrudSelfTest extends GridCommonAbstractTest {
         super.afterTest();
     }
 
-    /**
-     *
-     */
+    /** */
     private void fillInRepository() {
         for (int i = 0; i < CACHE_SIZE - 5; i++) {
             repo.save(i, new Person("person" + Integer.toHexString(i),
@@ -91,13 +100,11 @@ public class IgniteSpringDataCrudSelfTest extends GridCommonAbstractTest {
     }
 
     /** {@inheritDoc} */
-    @Override protected void afterTestsStopped() throws Exception {
-        ctx.destroy();
+    @Override protected void afterTestsStopped() {
+        ctx.close();
     }
 
-    /**
-     *
-     */
+    /** */
     @Test
     public void testPutGet() {
         Person person = new Person("some_name", "some_surname");
@@ -110,19 +117,12 @@ public class IgniteSpringDataCrudSelfTest extends GridCommonAbstractTest {
 
         assertEquals(person, repo.findById(id).get());
 
-        try {
-            repo.save(person);
-
-            fail("Managed to save a Person without ID");
-        }
-        catch (UnsupportedOperationException e) {
-            //excepted
-        }
+        expected.expect(UnsupportedOperationException.class);
+        expected.expectMessage("Use IgniteRepository.save(key,value) method instead.");
+        repo.save(person);
     }
 
-    /**
-     *
-     */
+    /** */
     @Test
     public void testPutAllGetAll() {
         LinkedHashMap<Integer, Person> map = new LinkedHashMap<>();
@@ -139,14 +139,9 @@ public class IgniteSpringDataCrudSelfTest extends GridCommonAbstractTest {
         while (persons.hasNext())
             assertEquals(origPersons.next(), persons.next());
 
-        try {
-            repo.saveAll(map.values());
-
-            fail("Managed to save a list of Persons with ids");
-        }
-        catch (UnsupportedOperationException e) {
-            //expected
-        }
+        expected.expect(UnsupportedOperationException.class);
+        expected.expectMessage("Use IgniteRepository.save(Map<keys,value>) method instead.");
+        repo.saveAll(map.values());
 
         persons = repo.findAllById(map.keySet()).iterator();
 
@@ -160,9 +155,7 @@ public class IgniteSpringDataCrudSelfTest extends GridCommonAbstractTest {
         assertEquals(map.size(), counter);
     }
 
-    /**
-     *
-     */
+    /** */
     @Test
     public void testGetAll() {
         assertEquals(CACHE_SIZE, repo.count());
@@ -179,9 +172,7 @@ public class IgniteSpringDataCrudSelfTest extends GridCommonAbstractTest {
         assertEquals(repo.count(), counter);
     }
 
-    /**
-     *
-     */
+    /** */
     @Test
     public void testDelete() {
         assertEquals(CACHE_SIZE, repo.count());
@@ -191,19 +182,12 @@ public class IgniteSpringDataCrudSelfTest extends GridCommonAbstractTest {
         assertEquals(CACHE_SIZE - 1, repo.count());
         assertEquals(Optional.empty(),repo.findById(0));
 
-        try {
-            repo.delete(new Person("", ""));
-
-            fail("Managed to delete a Person without id");
-        }
-        catch (UnsupportedOperationException e) {
-            //expected
-        }
+        expected.expect(UnsupportedOperationException.class);
+        expected.expectMessage("Use IgniteRepository.deleteById(key) method instead.");
+        repo.delete(new Person("", ""));
     }
 
-    /**
-     *
-     */
+    /** */
     @Test
     public void testDeleteSet() {
         assertEquals(CACHE_SIZE, repo.count());
@@ -217,24 +201,17 @@ public class IgniteSpringDataCrudSelfTest extends GridCommonAbstractTest {
 
         assertEquals(CACHE_SIZE / 2, repo.count());
 
-        try {
-            ArrayList<Person> persons = new ArrayList<>();
+        ArrayList<Person> persons = new ArrayList<>();
 
-            for (int i = 0; i < 3; i++)
-                persons.add(new Person(String.valueOf(i), String.valueOf(i)));
+        for (int i = 0; i < 3; i++)
+            persons.add(new Person(String.valueOf(i), String.valueOf(i)));
 
-            repo.deleteAll(persons);
-
-            fail("Managed to delete Persons without ids");
-        }
-        catch (UnsupportedOperationException e) {
-            //expected
-        }
+        expected.expect(UnsupportedOperationException.class);
+        expected.expectMessage("Use IgniteRepository.deleteAllById(keys) method instead.");
+        repo.deleteAll(persons);
     }
 
-    /**
-     *
-     */
+    /** */
     @Test
     public void testDeleteAll() {
         assertEquals(CACHE_SIZE, repo.count());
@@ -245,7 +222,7 @@ public class IgniteSpringDataCrudSelfTest extends GridCommonAbstractTest {
     }
 
     /**
-     * Delete existing record
+     * Delete existing record.
      */
     @Test
     public void testDeleteByFirstName() {
@@ -257,7 +234,7 @@ public class IgniteSpringDataCrudSelfTest extends GridCommonAbstractTest {
     }
 
     /**
-     * Delete NON existing record
+     * Delete NON existing record.
      */
     @Test
     public void testDeleteExpression() {
@@ -267,58 +244,54 @@ public class IgniteSpringDataCrudSelfTest extends GridCommonAbstractTest {
     }
 
     /**
-     * Delete Multiple records due to where
+     * Delete Multiple records due to where.
      */
     @Test
     public void testDeleteExpressionMultiple() {
-        long count = repo.countByFirstName("nonUniquePerson");
-        long cnt = repo.deleteByFirstName("nonUniquePerson");
+        long cnt = repo.countByFirstName("nonUniquePerson");
+        long cntDeleted = repo.deleteByFirstName("nonUniquePerson");
 
-        assertEquals(cnt, count);
+        assertEquals(cntDeleted, cnt);
     }
 
     /**
-     * Remove should do the same than Delete
+     * Remove should do the same than Delete.
      */
     @Test
     public void testRemoveExpression() {
-        long countRemoved = repo.removeByFirstName("person3f");
+        long cntRemoved = repo.removeByFirstName("person3f");
 
-        long count = repo.count();
-        assertEquals(CACHE_SIZE - countRemoved, count);
+        long cnt = repo.count();
+        assertEquals(CACHE_SIZE - cntRemoved, cnt);
     }
 
     /**
-     * Delete unique record using lower case key word
+     * Delete unique record using lower case key word.
      */
     @Test
     public void testDeleteQuery() {
         repo.deleteBySecondNameLowerCase("uniqueLastName");
 
-        long countAfter = repo.count();
-        assertEquals(CACHE_SIZE - 1, countAfter);
+        long cntAfter = repo.count();
+        assertEquals(CACHE_SIZE - 1, cntAfter);
     }
 
     /**
-     * Try to delete with a wrong @Query
+     * Try to delete with a wrong @Query.
      */
     @Test
     public void testWrongDeleteQuery() {
-        long countBefore = repo.countByFirstNameLike("person3f");
+        long cntBefore = repo.countByFirstNameLike("person3f");
 
-        try {
-            repo.deleteWrongByFirstNameQuery("person3f");
-        }
-        catch (Exception e) {
-            //expected
-        }
+        expected.expect(CacheException.class);
+        repo.deleteWrongByFirstNameQuery("person3f");
 
-        long countAfter = repo.countByFirstNameLike("person3f");
-        assertEquals(countBefore, countAfter);
+        long cntAfter = repo.countByFirstNameLike("person3f");
+        assertEquals(cntBefore, cntAfter);
     }
 
     /**
-     * Update with a @Query a record
+     * Update with a @Query a record.
      */
     @Test
     public void testUpdateQueryMixedCase() {
@@ -332,22 +305,55 @@ public class IgniteSpringDataCrudSelfTest extends GridCommonAbstractTest {
     }
 
     /**
-     * Update with a wrong @Query
+     * Update with a wrong @Query.
      */
     @Test
     public void testWrongUpdateQuery() {
-        final String newSecondName = "updatedUniqueSecondName";
-        int rowsUpdated = 0;
-        try {
-            rowsUpdated = repo.setWrongFixedSecondName(newSecondName, "uniquePerson");
-        }
-        catch (Exception e) {
-            //expected
-        }
+        expected.expect(CacheException.class);
+        int rowsUpdated = repo.setWrongFixedSecondName("updatedUniqueSecondName", "uniquePerson");
 
         assertEquals(0, rowsUpdated);
 
         List<Person> person = repo.findByFirstName("uniquePerson");
         assertEquals(person.get(0).getSecondName(), "uniqueLastName");
     }
+
+    /** */
+    @Test
+    public void shouldDeleteAllById() {
+        List<PersonKey> ids = prepareDataWithNonComparableKeys();
+
+        repoWithCompoundKey.deleteAllById(ids);
+
+        assertEquals(0, repoWithCompoundKey.count());
+    }
+
+    /** */
+    @Test
+    public void shouldFindAllById() {
+        List<PersonKey> ids = prepareDataWithNonComparableKeys();
+
+        Iterable<Person> res = repoWithCompoundKey.findAllById(ids);
+
+        assertEquals(2, res.spliterator().estimateSize());
+    }
+
+    /** */
+    private List<PersonKey> prepareDataWithNonComparableKeys() {
+        List<PersonKey> ids = new ArrayList<>();
+
+        PersonKey key = new PersonKey(1, 1);
+        ids.add(key);
+
+        repoWithCompoundKey.save(key, new Person("test1", "test1"));
+
+        key = new PersonKey(2, 2);
+        ids.add(key);
+
+        repoWithCompoundKey.save(key, new Person("test2", "test2"));
+
+        assertEquals(2, repoWithCompoundKey.count());
+
+        return ids;
+    }
 }
diff --git a/modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/IgniteSpringDataQueriesSelfTest.java b/modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/IgniteSpringDataQueriesSelfTest.java
index 6c9ecc5..e1ed7f8 100644
--- a/modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/IgniteSpringDataQueriesSelfTest.java
+++ b/modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/IgniteSpringDataQueriesSelfTest.java
@@ -22,8 +22,8 @@ import java.util.Iterator;
 import java.util.List;
 import javax.cache.Cache;
 import org.apache.ignite.springdata.misc.ApplicationConfiguration;
-import org.apache.ignite.springdata.misc.PersonRepository;
 import org.apache.ignite.springdata.misc.Person;
+import org.apache.ignite.springdata.misc.PersonRepository;
 import org.apache.ignite.springdata.misc.PersonSecondRepository;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
 import org.junit.Test;
@@ -36,6 +36,9 @@ import org.springframework.data.domain.Sort;
  *
  */
 public class IgniteSpringDataQueriesSelfTest extends GridCommonAbstractTest {
+    /** Number of entries to store */
+    private static final int CACHE_SIZE = 1000;
+
     /** Repository. */
     private static PersonRepository repo;
 
@@ -45,9 +48,6 @@ public class IgniteSpringDataQueriesSelfTest extends GridCommonAbstractTest {
     /** Context. */
     private static AnnotationConfigApplicationContext ctx;
 
-    /** Number of entries to store */
-    private static int CACHE_SIZE = 1000;
-
     /**
      * Performs context initialization before tests.
      */
@@ -55,9 +55,7 @@ public class IgniteSpringDataQueriesSelfTest extends GridCommonAbstractTest {
         super.beforeTestsStarted();
 
         ctx = new AnnotationConfigApplicationContext();
-
         ctx.register(ApplicationConfiguration.class);
-
         ctx.refresh();
 
         repo = ctx.getBean(PersonRepository.class);
@@ -72,8 +70,8 @@ public class IgniteSpringDataQueriesSelfTest extends GridCommonAbstractTest {
     /**
      * Performs context destroy after tests.
      */
-    @Override protected void afterTestsStopped() throws Exception {
-        ctx.destroy();
+    @Override protected void afterTestsStopped() {
+        ctx.close();
     }
 
     /** */
@@ -160,12 +158,12 @@ public class IgniteSpringDataQueriesSelfTest extends GridCommonAbstractTest {
     public void testPageable() {
         PageRequest pageable = PageRequest.of(1, 5, Sort.Direction.DESC, "firstName");
 
-        HashSet<String> firstNames = new HashSet<>();
-
         List<Person> pageable1 = repo.findByFirstNameRegex("^[a-z]+$", pageable);
 
         assertEquals(5, pageable1.size());
 
+        HashSet<String> firstNames = new HashSet<>();
+
         for (Person person : pageable1) {
             firstNames.add(person.getFirstName());
 
diff --git a/modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/misc/ApplicationConfiguration.java b/modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/misc/ApplicationConfiguration.java
index 0088d27..84728a7 100644
--- a/modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/misc/ApplicationConfiguration.java
+++ b/modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/misc/ApplicationConfiguration.java
@@ -23,9 +23,9 @@ import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
 import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
+import org.apache.ignite.springdata22.repository.config.EnableIgniteRepositories;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
-import org.apache.ignite.springdata22.repository.config.EnableIgniteRepositories;
 
 /**
  *
@@ -33,7 +33,6 @@ import org.apache.ignite.springdata22.repository.config.EnableIgniteRepositories
 @Configuration
 @EnableIgniteRepositories
 public class ApplicationConfiguration {
-
     /**
      * The bean with cache names
      */
@@ -51,19 +50,13 @@ public class ApplicationConfiguration {
      */
     @Bean
     public Ignite igniteInstance() {
-        IgniteConfiguration cfg = new IgniteConfiguration();
-
-        CacheConfiguration ccfg = new CacheConfiguration("PersonCache");
-
-        ccfg.setIndexedTypes(Integer.class, Person.class);
-
-        cfg.setCacheConfiguration(ccfg);
-
-        TcpDiscoverySpi spi = new TcpDiscoverySpi();
-
-        spi.setIpFinder(new TcpDiscoveryVmIpFinder(true));
-
-        cfg.setDiscoverySpi(spi);
+        IgniteConfiguration cfg = new IgniteConfiguration()
+            .setCacheConfiguration(
+                new CacheConfiguration<Integer, Person>("PersonCache")
+                    .setIndexedTypes(Integer.class, Person.class),
+                new CacheConfiguration<PersonKey, Person>("PersonWithKeyCache")
+            )
+            .setDiscoverySpi(new TcpDiscoverySpi().setIpFinder(new TcpDiscoveryVmIpFinder(true)));
 
         return Ignition.start(cfg);
     }
diff --git a/modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/misc/CacheNamesBean.java b/modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/misc/CacheNamesBean.java
index 464a6c1..6185744 100644
--- a/modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/misc/CacheNamesBean.java
+++ b/modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/misc/CacheNamesBean.java
@@ -18,20 +18,24 @@
 package org.apache.ignite.springdata.misc;
 
 /**
- * The bean with cache names
+ * The bean with cache names.
  */
 public class CacheNamesBean {
-
+    /** */
     private String personCacheName;
 
     /**
-     *  Get name of cache for persons
-     * @return name of cache
+     * Get name of cache for persons.
+     *
+     * @return Name of cache.
      */
     public String getPersonCacheName() {
         return personCacheName;
     }
 
+    /**
+     * @param personCacheName Name of cache.
+     */
     public void setPersonCacheName(String personCacheName) {
         this.personCacheName = personCacheName;
     }
diff --git a/modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/misc/Person.java b/modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/misc/Person.java
index 38aab10..154937f 100644
--- a/modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/misc/Person.java
+++ b/modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/misc/Person.java
@@ -17,8 +17,12 @@
 
 package org.apache.ignite.springdata.misc;
 
+import java.util.Objects;
 import org.apache.ignite.cache.query.annotations.QuerySqlField;
 
+/**
+ * DTO class.
+ */
 public class Person {
     /** First name. */
     @QuerySqlField(index = true)
@@ -77,22 +81,18 @@ public class Person {
     @Override public boolean equals(Object o) {
         if (this == o)
             return true;
+
         if (o == null || getClass() != o.getClass())
             return false;
 
         Person person = (Person)o;
 
-        if (firstName != null ? !firstName.equals(person.firstName) : person.firstName != null)
-            return false;
-
-        return secondName != null ? secondName.equals(person.secondName) : person.secondName == null;
-
+        return Objects.equals(firstName, person.firstName) &&
+            Objects.equals(secondName, person.secondName);
     }
 
     /** {@inheritDoc} */
     @Override public int hashCode() {
-        int result = firstName != null ? firstName.hashCode() : 0;
-        result = 31 * result + (secondName != null ? secondName.hashCode() : 0);
-        return result;
+        return Objects.hash(firstName, secondName);
     }
 }
diff --git a/modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/misc/CacheNamesBean.java b/modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/misc/PersonKey.java
similarity index 65%
copy from modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/misc/CacheNamesBean.java
copy to modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/misc/PersonKey.java
index 464a6c1..2537c57 100644
--- a/modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/misc/CacheNamesBean.java
+++ b/modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/misc/PersonKey.java
@@ -17,22 +17,38 @@
 
 package org.apache.ignite.springdata.misc;
 
+import java.io.Serializable;
+
 /**
- * The bean with cache names
+ * Compound key.
  */
-public class CacheNamesBean {
+public class PersonKey implements Serializable {
+    /** */
+    private int id1;
 
-    private String personCacheName;
+    /** */
+    private int id2;
 
     /**
-     *  Get name of cache for persons
-     * @return name of cache
+     * @param id1 ID1.
+     * @param id2 ID2.
      */
-    public String getPersonCacheName() {
-        return personCacheName;
+    public PersonKey(int id1, int id2) {
+        this.id1 = id1;
+        this.id2 = id2;
     }
 
-    public void setPersonCacheName(String personCacheName) {
-        this.personCacheName = personCacheName;
+    /**
+     * @return ID1
+     */
+    public int getId1() {
+        return id1;
+    }
+
+    /**
+     * @return ID1
+     */
+    public int getId2() {
+        return id1;
     }
 }
diff --git a/modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/misc/PersonRepository.java b/modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/misc/PersonRepository.java
index 88c3ae7..65f79f7 100644
--- a/modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/misc/PersonRepository.java
+++ b/modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/misc/PersonRepository.java
@@ -1,4 +1,3 @@
-
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -21,14 +20,14 @@ package org.apache.ignite.springdata.misc;
 import java.util.Collection;
 import java.util.List;
 import javax.cache.Cache;
+import org.apache.ignite.springdata22.repository.IgniteRepository;
 import org.apache.ignite.springdata22.repository.config.Query;
 import org.apache.ignite.springdata22.repository.config.RepositoryConfig;
 import org.springframework.data.domain.Pageable;
 import org.springframework.data.domain.Sort;
-import org.apache.ignite.springdata22.repository.IgniteRepository;
 
 /**
- *
+ * Test repository.
  */
 @RepositoryConfig(cacheName = "PersonCache")
 public interface PersonRepository extends IgniteRepository<Person, Integer> {
diff --git a/modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/misc/CacheNamesBean.java b/modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/misc/PersonRepositoryWithCompoundKey.java
similarity index 69%
copy from modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/misc/CacheNamesBean.java
copy to modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/misc/PersonRepositoryWithCompoundKey.java
index 464a6c1..b8949da 100644
--- a/modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/misc/CacheNamesBean.java
+++ b/modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/misc/PersonRepositoryWithCompoundKey.java
@@ -17,22 +17,12 @@
 
 package org.apache.ignite.springdata.misc;
 
+import org.apache.ignite.springdata22.repository.IgniteRepository;
+import org.apache.ignite.springdata22.repository.config.RepositoryConfig;
+
 /**
- * The bean with cache names
+ * Test repository.
  */
-public class CacheNamesBean {
-
-    private String personCacheName;
-
-    /**
-     *  Get name of cache for persons
-     * @return name of cache
-     */
-    public String getPersonCacheName() {
-        return personCacheName;
-    }
-
-    public void setPersonCacheName(String personCacheName) {
-        this.personCacheName = personCacheName;
-    }
+@RepositoryConfig(cacheName = "PersonWithKeyCache")
+public interface PersonRepositoryWithCompoundKey extends IgniteRepository<Person, PersonKey> {
 }
diff --git a/modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/misc/PersonSecondRepository.java b/modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/misc/PersonSecondRepository.java
index 7a83d0c..bb698bd 100644
--- a/modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/misc/PersonSecondRepository.java
+++ b/modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/misc/PersonSecondRepository.java
@@ -27,7 +27,7 @@ import org.springframework.data.domain.PageRequest;
 import org.springframework.data.domain.Slice;
 
 /**
- *
+ * Test repository.
  */
 @RepositoryConfig(cacheName = "PersonCache")
 public interface PersonSecondRepository extends IgniteRepository<Person, Integer> {
diff --git a/modules/spring-data/src/main/java/org/apache/ignite/springdata/repository/support/IgniteRepositoryImpl.java b/modules/spring-data/src/main/java/org/apache/ignite/springdata/repository/support/IgniteRepositoryImpl.java
index 4290272..95d933b 100644
--- a/modules/spring-data/src/main/java/org/apache/ignite/springdata/repository/support/IgniteRepositoryImpl.java
+++ b/modules/spring-data/src/main/java/org/apache/ignite/springdata/repository/support/IgniteRepositoryImpl.java
@@ -17,7 +17,6 @@
 package org.apache.ignite.springdata.repository.support;
 
 import java.io.Serializable;
-import java.util.Collection;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Map;
@@ -28,6 +27,8 @@ import org.apache.ignite.IgniteCache;
 import org.apache.ignite.cache.CachePeekMode;
 import org.apache.ignite.springdata.repository.IgniteRepository;
 
+import static java.util.Collections.emptySet;
+
 /**
  * General Apache Ignite repository implementation.
  */
@@ -101,20 +102,37 @@ public class IgniteRepositoryImpl<T, ID extends Serializable> implements IgniteR
         };
     }
 
-    /** {@inheritDoc} */
-    @Override public Iterable<T> findAll(Iterable<ID> ids) {
+    /**
+     * @param ids Collection of IDs.
+     * @return Collection transformed to set.
+     */
+    private Set<ID> toSet(Iterable<ID> ids) {
         if (ids instanceof Set)
-            return cache.getAll((Set<ID>)ids).values();
+            return (Set<ID>)ids;
+
+        Iterator<ID> itr = ids.iterator();
+
+        if (!itr.hasNext())
+            return emptySet();
+
+        ID key = itr.next();
+
+        Set<ID> keys = key instanceof Comparable ? new TreeSet<>() : new HashSet<>();
 
-        if (ids instanceof Collection)
-            return cache.getAll(new HashSet<>((Collection<ID>)ids)).values();
+        keys.add(key);
 
-        TreeSet<ID> keys = new TreeSet<>();
+        while (itr.hasNext()) {
+            key = itr.next();
 
-        for (ID id : ids)
-            keys.add(id);
+            keys.add(key);
+        }
 
-        return cache.getAll(keys).values();
+        return keys;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Iterable<T> findAll(Iterable<ID> ids) {
+        return cache.getAll(toSet(ids)).values();
     }
 
     /** {@inheritDoc} */
@@ -139,18 +157,7 @@ public class IgniteRepositoryImpl<T, ID extends Serializable> implements IgniteR
 
     /** {@inheritDoc} */
     @Override public void deleteAll(Iterable<ID> ids) {
-        if (ids instanceof Set)
-            cache.removeAll((Set<ID>)ids);
-
-        if (ids instanceof Collection)
-            cache.removeAll(new HashSet<>((Collection<ID>)ids));
-
-        TreeSet<ID> keys = new TreeSet<>();
-
-        for (ID id : ids)
-            keys.add(id);
-
-        cache.removeAll(keys);
+        cache.removeAll(toSet(ids));
     }
 
     /** {@inheritDoc} */
diff --git a/modules/spring-data/src/test/java/org/apache/ignite/springdata/IgniteSpringDataCrudSelfTest.java b/modules/spring-data/src/test/java/org/apache/ignite/springdata/IgniteSpringDataCrudSelfTest.java
index e05024a..c055c90 100644
--- a/modules/spring-data/src/test/java/org/apache/ignite/springdata/IgniteSpringDataCrudSelfTest.java
+++ b/modules/spring-data/src/test/java/org/apache/ignite/springdata/IgniteSpringDataCrudSelfTest.java
@@ -20,38 +20,49 @@ package org.apache.ignite.springdata;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
+import java.util.List;
 import java.util.TreeSet;
 import org.apache.ignite.springdata.misc.ApplicationConfiguration;
 import org.apache.ignite.springdata.misc.Person;
+import org.apache.ignite.springdata.misc.PersonKey;
 import org.apache.ignite.springdata.misc.PersonRepository;
+import org.apache.ignite.springdata.misc.PersonRepositoryWithCompoundKey;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 
 /**
- *
+ * CRUD tests.
  */
 public class IgniteSpringDataCrudSelfTest extends GridCommonAbstractTest {
-    /** Repository. */
-    private static PersonRepository repo;
+    /** Number of entries to store. */
+    private static final int CACHE_SIZE = 1000;
 
     /** Context. */
     private static AnnotationConfigApplicationContext ctx;
 
-    /** Number of entries to store */
-    private static int CACHE_SIZE = 1000;
+    /** Repository. */
+    private static PersonRepository repo;
+
+    /** Repository. */
+    private static PersonRepositoryWithCompoundKey repoWithCompoundKey;
+
+    /** */
+    @Rule
+    public final ExpectedException expected = ExpectedException.none();
 
     /** {@inheritDoc} */
     @Override protected void beforeTestsStarted() throws Exception {
         super.beforeTestsStarted();
 
         ctx = new AnnotationConfigApplicationContext();
-
         ctx.register(ApplicationConfiguration.class);
-
         ctx.refresh();
 
         repo = ctx.getBean(PersonRepository.class);
+        repoWithCompoundKey = ctx.getBean(PersonRepositoryWithCompoundKey.class);
     }
 
     /** {@inheritDoc} */
@@ -73,13 +84,11 @@ public class IgniteSpringDataCrudSelfTest extends GridCommonAbstractTest {
     }
 
     /** {@inheritDoc} */
-    @Override protected void afterTestsStopped() throws Exception {
+    @Override protected void afterTestsStopped() {
         ctx.destroy();
     }
 
-    /**
-     *
-     */
+    /** */
     @Test
     public void testPutGet() {
         Person person = new Person("some_name", "some_surname");
@@ -92,19 +101,12 @@ public class IgniteSpringDataCrudSelfTest extends GridCommonAbstractTest {
 
         assertEquals(person, repo.findOne(id));
 
-        try {
-            repo.save(person);
-
-            fail("Managed to save a Person without ID");
-        }
-        catch (UnsupportedOperationException e) {
-            //excepted
-        }
+        expected.expect(UnsupportedOperationException.class);
+        expected.expectMessage("Use IgniteRepository.save(key,value) method instead.");
+        repo.save(person);
     }
 
-    /**
-     *
-     */
+    /** */
     @Test
     public void testPutAllGetAll() {
         LinkedHashMap<Integer, Person> map = new LinkedHashMap<>();
@@ -121,14 +123,9 @@ public class IgniteSpringDataCrudSelfTest extends GridCommonAbstractTest {
         while (persons.hasNext())
             assertEquals(origPersons.next(), persons.next());
 
-        try {
-            repo.save(map.values());
-
-            fail("Managed to save a list of Persons with ids");
-        }
-        catch (UnsupportedOperationException e) {
-            //expected
-        }
+        expected.expect(UnsupportedOperationException.class);
+        expected.expectMessage("Use IgniteRepository.save(Map<keys,value>) method instead.");
+        repo.save(map.values());
 
         persons = repo.findAll(map.keySet()).iterator();
 
@@ -142,9 +139,7 @@ public class IgniteSpringDataCrudSelfTest extends GridCommonAbstractTest {
         assertEquals(map.size(), counter);
     }
 
-    /**
-     *
-     */
+    /** */
     @Test
     public void testGetAll() {
         assertEquals(CACHE_SIZE, repo.count());
@@ -161,9 +156,7 @@ public class IgniteSpringDataCrudSelfTest extends GridCommonAbstractTest {
         assertEquals(repo.count(), counter);
     }
 
-    /**
-     *
-     */
+    /** */
     @Test
     public void testDelete() {
         assertEquals(CACHE_SIZE, repo.count());
@@ -173,14 +166,9 @@ public class IgniteSpringDataCrudSelfTest extends GridCommonAbstractTest {
         assertEquals(CACHE_SIZE - 1, repo.count());
         assertNull(repo.findOne(0));
 
-        try {
-            repo.delete(new Person("", ""));
-
-            fail("Managed to delete a Person without id");
-        }
-        catch (UnsupportedOperationException e) {
-            //expected
-        }
+        expected.expect(UnsupportedOperationException.class);
+        expected.expectMessage("Use IgniteRepository.delete(key) method instead.");
+        repo.delete(new Person("", ""));
     }
 
     /**
@@ -195,23 +183,18 @@ public class IgniteSpringDataCrudSelfTest extends GridCommonAbstractTest {
         for (int i = 0; i < CACHE_SIZE / 2; i++)
             ids.add(i);
 
+        expected.expect(UnsupportedOperationException.class);
+        expected.expectMessage("Use IgniteRepository.deleteAll(keys) method instead.");
         repo.deleteAll(ids);
 
         assertEquals(CACHE_SIZE / 2, repo.count());
 
-        try {
-            ArrayList<Person> persons = new ArrayList<>();
-
-            for (int i = 0; i < 3; i++)
-                persons.add(new Person(String.valueOf(i), String.valueOf(i)));
+        ArrayList<Person> persons = new ArrayList<>();
 
-            repo.delete(persons);
+        for (int i = 0; i < 3; i++)
+            persons.add(new Person(String.valueOf(i), String.valueOf(i)));
 
-            fail("Managed to delete Persons without ids");
-        }
-        catch (UnsupportedOperationException e) {
-            //expected
-        }
+        repo.delete(persons);
     }
 
     /**
@@ -226,12 +209,49 @@ public class IgniteSpringDataCrudSelfTest extends GridCommonAbstractTest {
         assertEquals(0, repo.count());
     }
 
-    /**
-     *
-     */
+    /** */
     private void fillInRepository() {
         for (int i = 0; i < CACHE_SIZE; i++)
             repo.save(i, new Person("person" + Integer.toHexString(i),
                 "lastName" + Integer.toHexString((i + 16) % 256)));
     }
+
+    /** */
+    @Test
+    public void shouldDeleteAll() {
+        List<PersonKey> ids = prepareDataWithNonComparableKeys();
+
+        repoWithCompoundKey.deleteAll(ids);
+
+        assertEquals(0, repoWithCompoundKey.count());
+    }
+
+    /** */
+    @Test
+    public void shouldFindAll() {
+        List<PersonKey> ids = prepareDataWithNonComparableKeys();
+
+        Iterable<Person> res = repoWithCompoundKey.findAll(ids);
+
+        assertEquals(2, res.spliterator().estimateSize());
+    }
+
+    /** */
+    private List<PersonKey> prepareDataWithNonComparableKeys() {
+        List<PersonKey> ids = new ArrayList<>();
+
+        PersonKey key = new PersonKey(1, 1);
+        ids.add(key);
+
+        repoWithCompoundKey.save(key, new Person("test1", "test1"));
+
+        key = new PersonKey(2, 2);
+        ids.add(key);
+
+        repoWithCompoundKey.save(key, new Person("test2", "test2"));
+
+        assertEquals(2, repoWithCompoundKey.count());
+
+        return ids;
+    }
 }
diff --git a/modules/spring-data/src/test/java/org/apache/ignite/springdata/misc/ApplicationConfiguration.java b/modules/spring-data/src/test/java/org/apache/ignite/springdata/misc/ApplicationConfiguration.java
index e460cda..ff1045e 100644
--- a/modules/spring-data/src/test/java/org/apache/ignite/springdata/misc/ApplicationConfiguration.java
+++ b/modules/spring-data/src/test/java/org/apache/ignite/springdata/misc/ApplicationConfiguration.java
@@ -23,9 +23,9 @@ import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
 import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
+import org.apache.ignite.springdata.repository.config.EnableIgniteRepositories;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
-import org.apache.ignite.springdata.repository.config.EnableIgniteRepositories;
 
 /**
  *
@@ -33,21 +33,18 @@ import org.apache.ignite.springdata.repository.config.EnableIgniteRepositories;
 @Configuration
 @EnableIgniteRepositories
 public class ApplicationConfiguration {
+    /**
+     * @return Ignite instance.
+     */
     @Bean
     public Ignite igniteInstance() {
-        IgniteConfiguration cfg = new IgniteConfiguration();
-
-        CacheConfiguration ccfg = new CacheConfiguration("PersonCache");
-
-        ccfg.setIndexedTypes(Integer.class, Person.class);
-
-        cfg.setCacheConfiguration(ccfg);
-
-        TcpDiscoverySpi spi = new TcpDiscoverySpi();
-
-        spi.setIpFinder(new TcpDiscoveryVmIpFinder(true));
-
-        cfg.setDiscoverySpi(spi);
+        IgniteConfiguration cfg = new IgniteConfiguration()
+            .setCacheConfiguration(
+                new CacheConfiguration<Integer, Person>("PersonCache")
+                    .setIndexedTypes(Integer.class, Person.class),
+                new CacheConfiguration<PersonKey, Person>("PersonWithKeyCache")
+            )
+            .setDiscoverySpi(new TcpDiscoverySpi().setIpFinder(new TcpDiscoveryVmIpFinder(true)));
 
         return Ignition.start(cfg);
     }
diff --git a/modules/spring-data/src/test/java/org/apache/ignite/springdata/misc/Person.java b/modules/spring-data/src/test/java/org/apache/ignite/springdata/misc/Person.java
index 0215ca6..154937f 100644
--- a/modules/spring-data/src/test/java/org/apache/ignite/springdata/misc/Person.java
+++ b/modules/spring-data/src/test/java/org/apache/ignite/springdata/misc/Person.java
@@ -17,8 +17,12 @@
 
 package org.apache.ignite.springdata.misc;
 
+import java.util.Objects;
 import org.apache.ignite.cache.query.annotations.QuerySqlField;
 
+/**
+ * DTO class.
+ */
 public class Person {
     /** First name. */
     @QuerySqlField(index = true)
@@ -38,7 +42,7 @@ public class Person {
     }
 
     /**
-     *
+     * @return First name.
      */
     public String getFirstName() {
         return firstName;
@@ -52,7 +56,7 @@ public class Person {
     }
 
     /**
-     *
+     * @return Second name.
      */
     public String getSecondName() {
         return secondName;
@@ -77,21 +81,18 @@ public class Person {
     @Override public boolean equals(Object o) {
         if (this == o)
             return true;
+
         if (o == null || getClass() != o.getClass())
             return false;
 
         Person person = (Person)o;
 
-        if (firstName != null ? !firstName.equals(person.firstName) : person.firstName != null)
-            return false;
-        return secondName != null ? secondName.equals(person.secondName) : person.secondName == null;
-
+        return Objects.equals(firstName, person.firstName) &&
+            Objects.equals(secondName, person.secondName);
     }
 
     /** {@inheritDoc} */
     @Override public int hashCode() {
-        int result = firstName != null ? firstName.hashCode() : 0;
-        result = 31 * result + (secondName != null ? secondName.hashCode() : 0);
-        return result;
+        return Objects.hash(firstName, secondName);
     }
 }
diff --git a/modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/misc/CacheNamesBean.java b/modules/spring-data/src/test/java/org/apache/ignite/springdata/misc/PersonKey.java
similarity index 65%
copy from modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/misc/CacheNamesBean.java
copy to modules/spring-data/src/test/java/org/apache/ignite/springdata/misc/PersonKey.java
index 464a6c1..2537c57 100644
--- a/modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/misc/CacheNamesBean.java
+++ b/modules/spring-data/src/test/java/org/apache/ignite/springdata/misc/PersonKey.java
@@ -17,22 +17,38 @@
 
 package org.apache.ignite.springdata.misc;
 
+import java.io.Serializable;
+
 /**
- * The bean with cache names
+ * Compound key.
  */
-public class CacheNamesBean {
+public class PersonKey implements Serializable {
+    /** */
+    private int id1;
 
-    private String personCacheName;
+    /** */
+    private int id2;
 
     /**
-     *  Get name of cache for persons
-     * @return name of cache
+     * @param id1 ID1.
+     * @param id2 ID2.
      */
-    public String getPersonCacheName() {
-        return personCacheName;
+    public PersonKey(int id1, int id2) {
+        this.id1 = id1;
+        this.id2 = id2;
     }
 
-    public void setPersonCacheName(String personCacheName) {
-        this.personCacheName = personCacheName;
+    /**
+     * @return ID1
+     */
+    public int getId1() {
+        return id1;
+    }
+
+    /**
+     * @return ID1
+     */
+    public int getId2() {
+        return id1;
     }
 }
diff --git a/modules/spring-data/src/test/java/org/apache/ignite/springdata/misc/PersonRepository.java b/modules/spring-data/src/test/java/org/apache/ignite/springdata/misc/PersonRepository.java
index aa89d43..db6ace7 100644
--- a/modules/spring-data/src/test/java/org/apache/ignite/springdata/misc/PersonRepository.java
+++ b/modules/spring-data/src/test/java/org/apache/ignite/springdata/misc/PersonRepository.java
@@ -21,14 +21,14 @@ package org.apache.ignite.springdata.misc;
 import java.util.Collection;
 import java.util.List;
 import javax.cache.Cache;
+import org.apache.ignite.springdata.repository.IgniteRepository;
 import org.apache.ignite.springdata.repository.config.Query;
 import org.apache.ignite.springdata.repository.config.RepositoryConfig;
 import org.springframework.data.domain.Pageable;
 import org.springframework.data.domain.Sort;
-import org.apache.ignite.springdata.repository.IgniteRepository;
 
 /**
- *
+ * Test repository.
  */
 @RepositoryConfig(cacheName = "PersonCache")
 public interface PersonRepository extends IgniteRepository<Person, Integer> {
diff --git a/modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/misc/CacheNamesBean.java b/modules/spring-data/src/test/java/org/apache/ignite/springdata/misc/PersonRepositoryWithCompoundKey.java
similarity index 69%
copy from modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/misc/CacheNamesBean.java
copy to modules/spring-data/src/test/java/org/apache/ignite/springdata/misc/PersonRepositoryWithCompoundKey.java
index 464a6c1..e868911 100644
--- a/modules/spring-data-2.2/src/test/java/org/apache/ignite/springdata/misc/CacheNamesBean.java
+++ b/modules/spring-data/src/test/java/org/apache/ignite/springdata/misc/PersonRepositoryWithCompoundKey.java
@@ -17,22 +17,12 @@
 
 package org.apache.ignite.springdata.misc;
 
+import org.apache.ignite.springdata.repository.IgniteRepository;
+import org.apache.ignite.springdata.repository.config.RepositoryConfig;
+
 /**
- * The bean with cache names
+ * Test repository.
  */
-public class CacheNamesBean {
-
-    private String personCacheName;
-
-    /**
-     *  Get name of cache for persons
-     * @return name of cache
-     */
-    public String getPersonCacheName() {
-        return personCacheName;
-    }
-
-    public void setPersonCacheName(String personCacheName) {
-        this.personCacheName = personCacheName;
-    }
+@RepositoryConfig(cacheName = "PersonWithKeyCache")
+public interface PersonRepositoryWithCompoundKey extends IgniteRepository<Person, PersonKey> {
 }