From 9080a307ba0243648229e3778fe900a3493214ad Mon Sep 17 00:00:00 2001 From: Rich DiCroce Date: Thu, 5 Jul 2018 16:10:08 -0400 Subject: [PATCH 1/2] Fix bugs when using a cursor with EclipseLink: - Some environments (e.g. WildFly) wrap the Query, causing the instanceof check to fail, which prevents a cursor from being used. Fix this by unwrapping the Query first. - Telling EclipseLink to use a scrollable cursor, then telling it to use a result set type of FORWARD_ONLY, makes no sense and causes the SQL Server JDBC driver to throw an exception. Fix this by using a regular CursoredStream instead. - The original code never tells EclipseLink to release objects, causing any benefit from using a cursor to be lost since all objects are retained until the cursor is closed. Fix this by releasing objects after completing each page. --- .../com/querydsl/jpa/EclipseLinkHandler.java | 35 +++++++++++++++---- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/querydsl-jpa/src/main/java/com/querydsl/jpa/EclipseLinkHandler.java b/querydsl-jpa/src/main/java/com/querydsl/jpa/EclipseLinkHandler.java index 93978a50f..cf6e95956 100644 --- a/querydsl-jpa/src/main/java/com/querydsl/jpa/EclipseLinkHandler.java +++ b/querydsl-jpa/src/main/java/com/querydsl/jpa/EclipseLinkHandler.java @@ -17,10 +17,11 @@ import java.io.Closeable; import java.io.IOException; import java.util.Iterator; +import javax.persistence.PersistenceException; import javax.persistence.Query; +import org.eclipse.persistence.config.HintValues; import org.eclipse.persistence.config.QueryHints; -import org.eclipse.persistence.config.ResultSetType; import org.eclipse.persistence.jpa.JpaQuery; import org.eclipse.persistence.queries.Cursor; @@ -54,20 +55,40 @@ class EclipseLinkHandler implements QueryHandler { @SuppressWarnings("unchecked") @Override public CloseableIterator iterate(Query query, FactoryExpression projection) { + boolean canUseCursor = false; + try { + canUseCursor = query.unwrap(Query.class) instanceof JpaQuery; + } catch (PersistenceException e) {} // can't unwrap, just ignore the exception + Iterator iterator = null; Closeable closeable = null; - if (query instanceof JpaQuery) { - JpaQuery elQuery = (JpaQuery) query; - elQuery.setHint(QueryHints.RESULT_SET_TYPE, ResultSetType.ForwardOnly); - elQuery.setHint(QueryHints.SCROLLABLE_CURSOR, true); - final Cursor cursor = elQuery.getResultCursor(); + if (canUseCursor) { + query.setHint(QueryHints.CURSOR, HintValues.TRUE); + final Cursor cursor = (Cursor) query.getSingleResult(); + final int pageSize = cursor.getPageSize(); closeable = new Closeable() { @Override public void close() throws IOException { cursor.close(); } }; - iterator = cursor; + iterator = new Iterator() { + private int rowsSinceLastClear = 0; + + @Override + public boolean hasNext() { + return cursor.hasNext(); + } + + @Override + public T next() { + if (rowsSinceLastClear++ == pageSize) { + rowsSinceLastClear = 0; + cursor.clear(); + } + return (T) cursor.next(); + } + }; } else { iterator = query.getResultList().iterator(); } From 18b0920c47666a761be1989271029e97f24827b7 Mon Sep 17 00:00:00 2001 From: Rich DiCroce Date: Fri, 6 Jul 2018 08:41:52 -0400 Subject: [PATCH 2/2] Fix checkstyle errors --- .../src/main/java/com/querydsl/jpa/EclipseLinkHandler.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/querydsl-jpa/src/main/java/com/querydsl/jpa/EclipseLinkHandler.java b/querydsl-jpa/src/main/java/com/querydsl/jpa/EclipseLinkHandler.java index cf6e95956..30f344edd 100644 --- a/querydsl-jpa/src/main/java/com/querydsl/jpa/EclipseLinkHandler.java +++ b/querydsl-jpa/src/main/java/com/querydsl/jpa/EclipseLinkHandler.java @@ -58,7 +58,7 @@ class EclipseLinkHandler implements QueryHandler { boolean canUseCursor = false; try { canUseCursor = query.unwrap(Query.class) instanceof JpaQuery; - } catch (PersistenceException e) {} // can't unwrap, just ignore the exception + } catch (PersistenceException e) { } // can't unwrap, just ignore the exception Iterator iterator = null; Closeable closeable = null; @@ -74,7 +74,7 @@ class EclipseLinkHandler implements QueryHandler { }; iterator = new Iterator() { private int rowsSinceLastClear = 0; - + @Override public boolean hasNext() { return cursor.hasNext();