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 15:27:40 UTC

[ignite] branch master updated: IGNITE-13105 Fixed cursors leak in RunningQueryManager. Code cleanup. #7888 - Fixes #7888.

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 f151563  IGNITE-13105 Fixed cursors leak in RunningQueryManager. Code cleanup. #7888 - Fixes #7888.
f151563 is described below

commit f15156375da16bd960bcf0c36c96bf8f26398ba7
Author: Alexey Kuznetsov <ak...@apache.org>
AuthorDate: Fri Jun 5 22:27:14 2020 +0700

    IGNITE-13105 Fixed cursors leak in RunningQueryManager. Code cleanup. #7888 - Fixes #7888.
    
    Signed-off-by: Alexey Kuznetsov <ak...@apache.org>
---
 .../repository/query/IgniteRepositoryQuery.java    | 52 ++++++++++------
 .../springdata/IgniteSpringDataCrudSelfTest.java   | 33 ++++++++++
 .../repository/query/IgniteRepositoryQuery.java    | 52 ++++++++++------
 .../springdata/IgniteSpringDataCrudSelfTest.java   | 33 ++++++++++
 .../repository/query/IgniteRepositoryQuery.java    | 72 +++++++++++++---------
 .../springdata/IgniteSpringDataCrudSelfTest.java   | 33 ++++++++++
 .../ignite/springdata/misc/PersonRepository.java   |  3 +
 7 files changed, 212 insertions(+), 66 deletions(-)

diff --git a/modules/spring-data-2.0/src/main/java/org/apache/ignite/springdata20/repository/query/IgniteRepositoryQuery.java b/modules/spring-data-2.0/src/main/java/org/apache/ignite/springdata20/repository/query/IgniteRepositoryQuery.java
index 3bae2cc..e445e78 100644
--- a/modules/spring-data-2.0/src/main/java/org/apache/ignite/springdata20/repository/query/IgniteRepositoryQuery.java
+++ b/modules/spring-data-2.0/src/main/java/org/apache/ignite/springdata20/repository/query/IgniteRepositoryQuery.java
@@ -20,10 +20,10 @@ package org.apache.ignite.springdata20.repository.query;
 import java.lang.reflect.Method;
 import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
-import java.util.List;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Iterator;
+import java.util.List;
 import javax.cache.Cache;
 import org.apache.ignite.IgniteCache;
 import org.apache.ignite.cache.query.Query;
@@ -42,10 +42,13 @@ import org.springframework.data.repository.core.RepositoryMetadata;
 import org.springframework.data.repository.query.QueryMethod;
 import org.springframework.data.repository.query.RepositoryQuery;
 
+import static org.apache.ignite.springdata20.repository.query.IgniteQueryGenerator.addPaging;
+import static org.apache.ignite.springdata20.repository.query.IgniteQueryGenerator.addSorting;
+
 /**
  * Ignite SQL query implementation.
  */
-@SuppressWarnings("unchecked")
+@SuppressWarnings({"unchecked", "rawtypes"})
 public class IgniteRepositoryQuery implements RepositoryQuery {
     /** Defines the way how to process query result */
     private enum ReturnStrategy {
@@ -118,9 +121,9 @@ public class IgniteRepositoryQuery implements RepositoryQuery {
     @Override public Object execute(Object[] prmtrs) {
         Query qry = prepareQuery(prmtrs);
 
-        QueryCursor qryCursor = cache.query(qry);
-
-        return transformQueryCursor(prmtrs, qryCursor);
+        try (QueryCursor qryCursor = cache.query(qry)) {
+            return transformQueryCursor(prmtrs, qryCursor);
+        }
     }
 
     /** {@inheritDoc} */
@@ -196,7 +199,7 @@ public class IgniteRepositoryQuery implements RepositoryQuery {
      * @return Query cursor or slice
      */
     @Nullable private Object transformQueryCursor(Object[] prmtrs, QueryCursor qryCursor) {
-        if (this.qry.isFieldQuery()) {
+        if (qry.isFieldQuery()) {
             Iterable<List> qryIter = (Iterable<List>)qryCursor;
 
             switch (returnStgy) {
@@ -207,6 +210,7 @@ public class IgniteRepositoryQuery implements RepositoryQuery {
                         list.add(entry.get(0));
 
                     return list;
+
                 case ONE_VALUE:
                     Iterator<List> iter = qryIter.iterator();
 
@@ -214,6 +218,7 @@ public class IgniteRepositoryQuery implements RepositoryQuery {
                         return iter.next().get(0);
 
                     return null;
+
                 case SLICE_OF_VALUES:
                     List content = new ArrayList<>();
 
@@ -221,10 +226,13 @@ public class IgniteRepositoryQuery implements RepositoryQuery {
                         content.add(entry.get(0));
 
                     return new SliceImpl(content, (Pageable)prmtrs[prmtrs.length - 1], true);
+
                 case SLICE_OF_LISTS:
                     return new SliceImpl(qryCursor.getAll(), (Pageable)prmtrs[prmtrs.length - 1], true);
+
                 case LIST_OF_LISTS:
                     return qryCursor.getAll();
+
                 default:
                     throw new IllegalStateException();
             }
@@ -240,6 +248,7 @@ public class IgniteRepositoryQuery implements RepositoryQuery {
                         list.add(entry.getValue());
 
                     return list;
+
                 case ONE_VALUE:
                     Iterator<CacheEntryImpl> iter1 = qryIter.iterator();
 
@@ -247,6 +256,7 @@ public class IgniteRepositoryQuery implements RepositoryQuery {
                         return iter1.next().getValue();
 
                     return null;
+
                 case CACHE_ENTRY:
                     Iterator<CacheEntryImpl> iter2 = qryIter.iterator();
 
@@ -254,6 +264,7 @@ public class IgniteRepositoryQuery implements RepositoryQuery {
                         return iter2.next();
 
                     return null;
+
                 case SLICE_OF_VALUES:
                     List content = new ArrayList<>();
 
@@ -261,10 +272,13 @@ public class IgniteRepositoryQuery implements RepositoryQuery {
                         content.add(entry.getValue());
 
                     return new SliceImpl(content, (Pageable)prmtrs[prmtrs.length - 1], true);
+
                 case SLICE_OF_CACHE_ENTRIES:
                     return new SliceImpl(qryCursor.getAll(), (Pageable)prmtrs[prmtrs.length - 1], true);
+
                 case LIST_OF_CACHE_ENTRIES:
                     return qryCursor.getAll();
+
                 default:
                     throw new IllegalStateException();
             }
@@ -275,38 +289,38 @@ public class IgniteRepositoryQuery implements RepositoryQuery {
      * @param prmtrs Prmtrs.
      * @return prepared query for execution
      */
+    @SuppressWarnings("deprecation")
     @NotNull private Query prepareQuery(Object[] prmtrs) {
         Object[] parameters = prmtrs;
         String sql = qry.sql();
 
-        Query query;
-
         switch (qry.options()) {
             case SORTING:
-                sql = IgniteQueryGenerator.addSorting(new StringBuilder(sql),
-                    (Sort)parameters[parameters.length - 1]).toString();
+                sql = addSorting(new StringBuilder(sql), (Sort)parameters[parameters.length - 1]).toString();
                 parameters = Arrays.copyOfRange(parameters, 0, parameters.length - 1);
+
                 break;
+
             case PAGINATION:
-                sql = IgniteQueryGenerator.addPaging(new StringBuilder(sql),
-                    (Pageable)parameters[parameters.length - 1]).toString();
+                sql = addPaging(new StringBuilder(sql), (Pageable)parameters[parameters.length - 1]).toString();
                 parameters = Arrays.copyOfRange(parameters, 0, parameters.length - 1);
+
                 break;
+
+            case NONE:
+                // No-op.
         }
 
         if (qry.isFieldQuery()) {
             SqlFieldsQuery sqlFieldsQry = new SqlFieldsQuery(sql);
             sqlFieldsQry.setArgs(parameters);
 
-            query = sqlFieldsQry;
+            return sqlFieldsQry;
         }
-        else {
-            SqlQuery sqlQry = new SqlQuery(type, sql);
-            sqlQry.setArgs(parameters);
 
-            query = sqlQry;
-        }
+        SqlQuery sqlQry = new SqlQuery(type, sql);
+        sqlQry.setArgs(parameters);
 
-        return query;
+        return sqlQry;
     }
 }
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 b2dce2f..b4dcf23 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
@@ -24,6 +24,9 @@ import java.util.List;
 import java.util.Optional;
 import java.util.TreeSet;
 import javax.cache.CacheException;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.processors.query.RunningQueryManager;
+import org.apache.ignite.internal.processors.query.h2.IgniteH2Indexing;
 import org.apache.ignite.springdata.misc.ApplicationConfiguration;
 import org.apache.ignite.springdata.misc.Person;
 import org.apache.ignite.springdata.misc.PersonKey;
@@ -55,6 +58,9 @@ public class IgniteSpringDataCrudSelfTest extends GridCommonAbstractTest {
     @Rule
     public final ExpectedException expected = ExpectedException.none();
 
+    /** */
+    private static IgniteEx ignite;
+
     /** {@inheritDoc} */
     @Override protected void beforeTestsStarted() throws Exception {
         super.beforeTestsStarted();
@@ -65,6 +71,7 @@ public class IgniteSpringDataCrudSelfTest extends GridCommonAbstractTest {
 
         repo = ctx.getBean(PersonRepository.class);
         repoWithCompoundKey = ctx.getBean(PersonRepositoryWithCompoundKey.class);
+        ignite = ctx.getBean(IgniteEx.class);
     }
 
     /** {@inheritDoc} */
@@ -356,4 +363,30 @@ public class IgniteSpringDataCrudSelfTest extends GridCommonAbstractTest {
 
         return ids;
     }
+
+    /** */
+    @Test
+    public void shouldNotLeakCursorsInRunningQueryManager() {
+        RunningQueryManager runningQryMgr = ((IgniteH2Indexing)ignite.context().query().getIndexing()).runningQueryManager();
+
+        assertEquals(0, runningQryMgr.longRunningQueries(0).size());
+
+        List<Person> res = repo.simpleQuery("person0");
+
+        assertEquals(1, res.size());
+
+        assertEquals(0, runningQryMgr.longRunningQueries(0).size());
+
+        Person person = repo.findTopBySecondNameStartingWith("lastName");
+
+        assertNotNull(person);
+
+        assertEquals(0, runningQryMgr.longRunningQueries(0).size());
+
+        long cnt = repo.countByFirstName("person0");
+
+        assertEquals(1, cnt);
+
+        assertEquals(0, runningQryMgr.longRunningQueries(0).size());
+    }
 }
diff --git a/modules/spring-data-2.2/src/main/java/org/apache/ignite/springdata22/repository/query/IgniteRepositoryQuery.java b/modules/spring-data-2.2/src/main/java/org/apache/ignite/springdata22/repository/query/IgniteRepositoryQuery.java
index 0d99c59..9f27a95 100644
--- a/modules/spring-data-2.2/src/main/java/org/apache/ignite/springdata22/repository/query/IgniteRepositoryQuery.java
+++ b/modules/spring-data-2.2/src/main/java/org/apache/ignite/springdata22/repository/query/IgniteRepositoryQuery.java
@@ -20,10 +20,10 @@ package org.apache.ignite.springdata22.repository.query;
 import java.lang.reflect.Method;
 import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
-import java.util.List;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Iterator;
+import java.util.List;
 import javax.cache.Cache;
 import org.apache.ignite.IgniteCache;
 import org.apache.ignite.cache.query.Query;
@@ -42,10 +42,13 @@ import org.springframework.data.repository.core.RepositoryMetadata;
 import org.springframework.data.repository.query.QueryMethod;
 import org.springframework.data.repository.query.RepositoryQuery;
 
+import static org.apache.ignite.springdata22.repository.query.IgniteQueryGenerator.addPaging;
+import static org.apache.ignite.springdata22.repository.query.IgniteQueryGenerator.addSorting;
+
 /**
  * Ignite SQL query implementation.
  */
-@SuppressWarnings("unchecked")
+@SuppressWarnings({"unchecked", "rawtypes"})
 public class IgniteRepositoryQuery implements RepositoryQuery {
     /** Defines the way how to process query result */
     private enum ReturnStrategy {
@@ -118,9 +121,9 @@ public class IgniteRepositoryQuery implements RepositoryQuery {
     @Override public Object execute(Object[] prmtrs) {
         Query qry = prepareQuery(prmtrs);
 
-        QueryCursor qryCursor = cache.query(qry);
-
-        return transformQueryCursor(prmtrs, qryCursor);
+        try (QueryCursor qryCursor = cache.query(qry)) {
+            return transformQueryCursor(prmtrs, qryCursor);
+        }
     }
 
     /** {@inheritDoc} */
@@ -196,7 +199,7 @@ public class IgniteRepositoryQuery implements RepositoryQuery {
      * @return Query cursor or slice
      */
     @Nullable private Object transformQueryCursor(Object[] prmtrs, QueryCursor qryCursor) {
-        if (this.qry.isFieldQuery()) {
+        if (qry.isFieldQuery()) {
             Iterable<List> qryIter = (Iterable<List>)qryCursor;
 
             switch (returnStgy) {
@@ -207,6 +210,7 @@ public class IgniteRepositoryQuery implements RepositoryQuery {
                         list.add(entry.get(0));
 
                     return list;
+
                 case ONE_VALUE:
                     Iterator<List> iter = qryIter.iterator();
 
@@ -214,6 +218,7 @@ public class IgniteRepositoryQuery implements RepositoryQuery {
                         return iter.next().get(0);
 
                     return null;
+
                 case SLICE_OF_VALUES:
                     List content = new ArrayList<>();
 
@@ -221,10 +226,13 @@ public class IgniteRepositoryQuery implements RepositoryQuery {
                         content.add(entry.get(0));
 
                     return new SliceImpl(content, (Pageable)prmtrs[prmtrs.length - 1], true);
+
                 case SLICE_OF_LISTS:
                     return new SliceImpl(qryCursor.getAll(), (Pageable)prmtrs[prmtrs.length - 1], true);
+
                 case LIST_OF_LISTS:
                     return qryCursor.getAll();
+
                 default:
                     throw new IllegalStateException();
             }
@@ -240,6 +248,7 @@ public class IgniteRepositoryQuery implements RepositoryQuery {
                         list.add(entry.getValue());
 
                     return list;
+
                 case ONE_VALUE:
                     Iterator<CacheEntryImpl> iter1 = qryIter.iterator();
 
@@ -247,6 +256,7 @@ public class IgniteRepositoryQuery implements RepositoryQuery {
                         return iter1.next().getValue();
 
                     return null;
+
                 case CACHE_ENTRY:
                     Iterator<CacheEntryImpl> iter2 = qryIter.iterator();
 
@@ -254,6 +264,7 @@ public class IgniteRepositoryQuery implements RepositoryQuery {
                         return iter2.next();
 
                     return null;
+
                 case SLICE_OF_VALUES:
                     List content = new ArrayList<>();
 
@@ -261,10 +272,13 @@ public class IgniteRepositoryQuery implements RepositoryQuery {
                         content.add(entry.getValue());
 
                     return new SliceImpl(content, (Pageable)prmtrs[prmtrs.length - 1], true);
+
                 case SLICE_OF_CACHE_ENTRIES:
                     return new SliceImpl(qryCursor.getAll(), (Pageable)prmtrs[prmtrs.length - 1], true);
+
                 case LIST_OF_CACHE_ENTRIES:
                     return qryCursor.getAll();
+
                 default:
                     throw new IllegalStateException();
             }
@@ -275,38 +289,38 @@ public class IgniteRepositoryQuery implements RepositoryQuery {
      * @param prmtrs Prmtrs.
      * @return prepared query for execution
      */
+    @SuppressWarnings("deprecation")
     @NotNull private Query prepareQuery(Object[] prmtrs) {
         Object[] parameters = prmtrs;
         String sql = qry.sql();
 
-        Query query;
-
         switch (qry.options()) {
             case SORTING:
-                sql = IgniteQueryGenerator.addSorting(new StringBuilder(sql),
-                    (Sort)parameters[parameters.length - 1]).toString();
+                sql = addSorting(new StringBuilder(sql), (Sort)parameters[parameters.length - 1]).toString();
                 parameters = Arrays.copyOfRange(parameters, 0, parameters.length - 1);
+
                 break;
+
             case PAGINATION:
-                sql = IgniteQueryGenerator.addPaging(new StringBuilder(sql),
-                    (Pageable)parameters[parameters.length - 1]).toString();
+                sql = addPaging(new StringBuilder(sql), (Pageable)parameters[parameters.length - 1]).toString();
                 parameters = Arrays.copyOfRange(parameters, 0, parameters.length - 1);
+
                 break;
+
+            case NONE:
+                // No-op.
         }
 
         if (qry.isFieldQuery()) {
             SqlFieldsQuery sqlFieldsQry = new SqlFieldsQuery(sql);
             sqlFieldsQry.setArgs(parameters);
 
-            query = sqlFieldsQry;
+            return sqlFieldsQry;
         }
-        else {
-            SqlQuery sqlQry = new SqlQuery(type, sql);
-            sqlQry.setArgs(parameters);
 
-            query = sqlQry;
-        }
+        SqlQuery sqlQry = new SqlQuery(type, sql);
+        sqlQry.setArgs(parameters);
 
-        return query;
+        return sqlQry;
     }
 }
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 19ee296..5d863e4 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
@@ -24,6 +24,9 @@ import java.util.List;
 import java.util.Optional;
 import java.util.TreeSet;
 import javax.cache.CacheException;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.processors.query.RunningQueryManager;
+import org.apache.ignite.internal.processors.query.h2.IgniteH2Indexing;
 import org.apache.ignite.springdata.misc.ApplicationConfiguration;
 import org.apache.ignite.springdata.misc.Person;
 import org.apache.ignite.springdata.misc.PersonKey;
@@ -55,6 +58,9 @@ public class IgniteSpringDataCrudSelfTest extends GridCommonAbstractTest {
     @Rule
     public final ExpectedException expected = ExpectedException.none();
 
+    /** */
+    private static IgniteEx ignite;
+
     /** {@inheritDoc} */
     @Override protected void beforeTestsStarted() throws Exception {
         super.beforeTestsStarted();
@@ -65,6 +71,7 @@ public class IgniteSpringDataCrudSelfTest extends GridCommonAbstractTest {
 
         repo = ctx.getBean(PersonRepository.class);
         repoWithCompoundKey = ctx.getBean(PersonRepositoryWithCompoundKey.class);
+        ignite = ctx.getBean(IgniteEx.class);
     }
 
     /** {@inheritDoc} */
@@ -356,4 +363,30 @@ public class IgniteSpringDataCrudSelfTest extends GridCommonAbstractTest {
 
         return ids;
     }
+
+    /** */
+    @Test
+    public void shouldNotLeakCursorsInRunningQueryManager() {
+        RunningQueryManager runningQryMgr = ((IgniteH2Indexing)ignite.context().query().getIndexing()).runningQueryManager();
+
+        assertEquals(0, runningQryMgr.longRunningQueries(0).size());
+
+        List<Person> res = repo.simpleQuery("person0");
+
+        assertEquals(1, res.size());
+
+        assertEquals(0, runningQryMgr.longRunningQueries(0).size());
+
+        Person person = repo.findTopBySecondNameStartingWith("lastName");
+
+        assertNotNull(person);
+
+        assertEquals(0, runningQryMgr.longRunningQueries(0).size());
+
+        long cnt = repo.countByFirstName("person0");
+
+        assertEquals(1, cnt);
+
+        assertEquals(0, runningQryMgr.longRunningQueries(0).size());
+    }
 }
diff --git a/modules/spring-data/src/main/java/org/apache/ignite/springdata/repository/query/IgniteRepositoryQuery.java b/modules/spring-data/src/main/java/org/apache/ignite/springdata/repository/query/IgniteRepositoryQuery.java
index 7b0c98a..e351c61 100644
--- a/modules/spring-data/src/main/java/org/apache/ignite/springdata/repository/query/IgniteRepositoryQuery.java
+++ b/modules/spring-data/src/main/java/org/apache/ignite/springdata/repository/query/IgniteRepositoryQuery.java
@@ -23,6 +23,7 @@ import java.lang.reflect.Type;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Iterator;
+import java.util.List;
 import javax.cache.Cache;
 import org.apache.ignite.IgniteCache;
 import org.apache.ignite.cache.query.Query;
@@ -41,10 +42,13 @@ import org.springframework.data.repository.core.RepositoryMetadata;
 import org.springframework.data.repository.query.QueryMethod;
 import org.springframework.data.repository.query.RepositoryQuery;
 
+import static org.apache.ignite.springdata.repository.query.IgniteQueryGenerator.addPaging;
+import static org.apache.ignite.springdata.repository.query.IgniteQueryGenerator.addSorting;
+
 /**
  * Ignite SQL query implementation.
  */
-@SuppressWarnings("unchecked")
+@SuppressWarnings({"unchecked", "rawtypes"})
 public class IgniteRepositoryQuery implements RepositoryQuery {
     /** Defines the way how to process query result */
     private enum ReturnStrategy {
@@ -106,7 +110,6 @@ public class IgniteRepositoryQuery implements RepositoryQuery {
         type = metadata.getDomainType();
         this.qry = qry;
         this.cache = cache;
-
         this.metadata = metadata;
         this.mtd = mtd;
         this.factory = factory;
@@ -118,9 +121,9 @@ public class IgniteRepositoryQuery implements RepositoryQuery {
     @Override public Object execute(Object[] prmtrs) {
         Query qry = prepareQuery(prmtrs);
 
-        QueryCursor qryCursor = cache.query(qry);
-
-        return transformQueryCursor(prmtrs, qryCursor);
+        try (QueryCursor qryCursor = cache.query(qry)) {
+            return transformQueryCursor(prmtrs, qryCursor);
+        }
     }
 
     /** {@inheritDoc} */
@@ -131,6 +134,7 @@ public class IgniteRepositoryQuery implements RepositoryQuery {
     /**
      * @param mtd Method.
      * @param isFieldQry Is field query.
+     * @return Return strategy type.
      */
     private ReturnStrategy calcReturnType(Method mtd, boolean isFieldQry) {
         Class<?> returnType = mtd.getReturnType();
@@ -164,6 +168,7 @@ public class IgniteRepositoryQuery implements RepositoryQuery {
     /**
      * @param cls Class 1.
      * @param mtd Method.
+     * @return if {@code mtd} return type is assignable from {@code cls}
      */
     private boolean hasAssignableGenericReturnTypeFrom(Class<?> cls, Method mtd) {
         Type[] actualTypeArguments = ((ParameterizedType)mtd.getGenericReturnType()).getActualTypeArguments();
@@ -191,37 +196,43 @@ public class IgniteRepositoryQuery implements RepositoryQuery {
     /**
      * @param prmtrs Prmtrs.
      * @param qryCursor Query cursor.
+     * @return Query cursor or slice
      */
     @Nullable private Object transformQueryCursor(Object[] prmtrs, QueryCursor qryCursor) {
-        if (this.qry.isFieldQuery()) {
-            Iterable<ArrayList> qryIter = (Iterable<ArrayList>)qryCursor;
+        if (qry.isFieldQuery()) {
+            Iterable<List> qryIter = (Iterable<List>)qryCursor;
 
             switch (returnStgy) {
                 case LIST_OF_VALUES:
-                    ArrayList list = new ArrayList();
+                    List list = new ArrayList<>();
 
-                    for (ArrayList entry : qryIter)
+                    for (List entry : qryIter)
                         list.add(entry.get(0));
 
                     return list;
+
                 case ONE_VALUE:
-                    Iterator<ArrayList> iter = qryIter.iterator();
+                    Iterator<List> iter = qryIter.iterator();
 
                     if (iter.hasNext())
                         return iter.next().get(0);
 
                     return null;
+
                 case SLICE_OF_VALUES:
-                    ArrayList content = new ArrayList();
+                    List content = new ArrayList<>();
 
-                    for (ArrayList entry : qryIter)
+                    for (List entry : qryIter)
                         content.add(entry.get(0));
 
                     return new SliceImpl(content, (Pageable)prmtrs[prmtrs.length - 1], true);
+
                 case SLICE_OF_LISTS:
                     return new SliceImpl(qryCursor.getAll(), (Pageable)prmtrs[prmtrs.length - 1], true);
+
                 case LIST_OF_LISTS:
                     return qryCursor.getAll();
+
                 default:
                     throw new IllegalStateException();
             }
@@ -231,12 +242,13 @@ public class IgniteRepositoryQuery implements RepositoryQuery {
 
             switch (returnStgy) {
                 case LIST_OF_VALUES:
-                    ArrayList list = new ArrayList();
+                    List list = new ArrayList<>();
 
                     for (CacheEntryImpl entry : qryIter)
                         list.add(entry.getValue());
 
                     return list;
+
                 case ONE_VALUE:
                     Iterator<CacheEntryImpl> iter1 = qryIter.iterator();
 
@@ -244,6 +256,7 @@ public class IgniteRepositoryQuery implements RepositoryQuery {
                         return iter1.next().getValue();
 
                     return null;
+
                 case CACHE_ENTRY:
                     Iterator<CacheEntryImpl> iter2 = qryIter.iterator();
 
@@ -251,17 +264,21 @@ public class IgniteRepositoryQuery implements RepositoryQuery {
                         return iter2.next();
 
                     return null;
+
                 case SLICE_OF_VALUES:
-                    ArrayList content = new ArrayList();
+                    List content = new ArrayList<>();
 
                     for (CacheEntryImpl entry : qryIter)
                         content.add(entry.getValue());
 
                     return new SliceImpl(content, (Pageable)prmtrs[prmtrs.length - 1], true);
+
                 case SLICE_OF_CACHE_ENTRIES:
                     return new SliceImpl(qryCursor.getAll(), (Pageable)prmtrs[prmtrs.length - 1], true);
+
                 case LIST_OF_CACHE_ENTRIES:
                     return qryCursor.getAll();
+
                 default:
                     throw new IllegalStateException();
             }
@@ -272,39 +289,38 @@ public class IgniteRepositoryQuery implements RepositoryQuery {
      * @param prmtrs Prmtrs.
      * @return prepared query for execution
      */
+    @SuppressWarnings("deprecation")
     @NotNull private Query prepareQuery(Object[] prmtrs) {
         Object[] parameters = prmtrs;
         String sql = qry.sql();
 
-        Query query;
-
         switch (qry.options()) {
             case SORTING:
-                sql = IgniteQueryGenerator.addSorting(new StringBuilder(sql),
-                    (Sort)parameters[parameters.length - 1]).toString();
+                sql = addSorting(new StringBuilder(sql), (Sort)parameters[parameters.length - 1]).toString();
                 parameters = Arrays.copyOfRange(parameters, 0, parameters.length - 1);
+
                 break;
+
             case PAGINATION:
-                sql = IgniteQueryGenerator.addPaging(new StringBuilder(sql),
-                    (Pageable)parameters[parameters.length - 1]).toString();
+                sql = addPaging(new StringBuilder(sql), (Pageable)parameters[parameters.length - 1]).toString();
                 parameters = Arrays.copyOfRange(parameters, 0, parameters.length - 1);
+
                 break;
+
+            case NONE:
+                // No-op.
         }
 
         if (qry.isFieldQuery()) {
             SqlFieldsQuery sqlFieldsQry = new SqlFieldsQuery(sql);
             sqlFieldsQry.setArgs(parameters);
 
-            query = sqlFieldsQry;
+            return sqlFieldsQry;
         }
-        else {
-            SqlQuery sqlQry = new SqlQuery(type, sql);
-            sqlQry.setArgs(parameters);
 
-            query = sqlQry;
-        }
+        SqlQuery sqlQry = new SqlQuery(type, sql);
+        sqlQry.setArgs(parameters);
 
-        return query;
+        return sqlQry;
     }
 }
-
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 c055c90..65f9239 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
@@ -22,6 +22,9 @@ import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.TreeSet;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.processors.query.RunningQueryManager;
+import org.apache.ignite.internal.processors.query.h2.IgniteH2Indexing;
 import org.apache.ignite.springdata.misc.ApplicationConfiguration;
 import org.apache.ignite.springdata.misc.Person;
 import org.apache.ignite.springdata.misc.PersonKey;
@@ -53,6 +56,9 @@ public class IgniteSpringDataCrudSelfTest extends GridCommonAbstractTest {
     @Rule
     public final ExpectedException expected = ExpectedException.none();
 
+    /** */
+    private static IgniteEx ignite;
+
     /** {@inheritDoc} */
     @Override protected void beforeTestsStarted() throws Exception {
         super.beforeTestsStarted();
@@ -63,6 +69,7 @@ public class IgniteSpringDataCrudSelfTest extends GridCommonAbstractTest {
 
         repo = ctx.getBean(PersonRepository.class);
         repoWithCompoundKey = ctx.getBean(PersonRepositoryWithCompoundKey.class);
+        ignite = ctx.getBean(IgniteEx.class);
     }
 
     /** {@inheritDoc} */
@@ -254,4 +261,30 @@ public class IgniteSpringDataCrudSelfTest extends GridCommonAbstractTest {
 
         return ids;
     }
+
+    /** */
+    @Test
+    public void shouldNotLeakCursorsInRunningQueryManager() {
+        RunningQueryManager runningQryMgr = ((IgniteH2Indexing)ignite.context().query().getIndexing()).runningQueryManager();
+
+        assertEquals(0, runningQryMgr.longRunningQueries(0).size());
+
+        List<Person> res = repo.simpleQuery("person0");
+
+        assertEquals(1, res.size());
+
+        assertEquals(0, runningQryMgr.longRunningQueries(0).size());
+
+        Person person = repo.findTopBySecondNameStartingWith("lastName");
+
+        assertNotNull(person);
+
+        assertEquals(0, runningQryMgr.longRunningQueries(0).size());
+
+        long cnt = repo.countByFirstName("person0");
+
+        assertEquals(1, cnt);
+
+        assertEquals(0, runningQryMgr.longRunningQueries(0).size());
+    }
 }
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 db6ace7..d8444d1 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
@@ -48,6 +48,9 @@ public interface PersonRepository extends IgniteRepository<Person, Integer> {
     public Iterable<Person> findFirst10ByFirstNameLike(String val);
 
     /** */
+    public int countByFirstName(String val);
+
+    /** */
     public int countByFirstNameLike(String val);
 
     /** */