[#1080] Add support for JDBC's Statement.setFetchSize() in ResultQuery.fetchLazy()
This commit is contained in:
parent
15e62bbae6
commit
21837feaff
@ -990,87 +990,89 @@ public abstract class jOOQAbstractTest<
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLazyFetching() throws Exception {
|
||||
public void testFetchLazy() throws Exception {
|
||||
for (int fetchSize : Arrays.asList(0, 1)) {
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// A regular pass through the cursor
|
||||
// ---------------------------------------------------------------------
|
||||
Cursor<B> cursor = create().selectFrom(TBook()).orderBy(TBook_ID()).fetchLazy();
|
||||
// ---------------------------------------------------------------------
|
||||
// A regular pass through the cursor
|
||||
// ---------------------------------------------------------------------
|
||||
Cursor<B> cursor = create().selectFrom(TBook()).orderBy(TBook_ID()).fetchLazy(fetchSize);
|
||||
|
||||
assertTrue(cursor.hasNext());
|
||||
assertTrue(cursor.hasNext());
|
||||
assertEquals(Integer.valueOf(1), cursor.fetchOne().getValue(TBook_ID()));
|
||||
assertEquals(Integer.valueOf(2), cursor.fetchOne().getValue(TBook_ID()));
|
||||
assertTrue(cursor.hasNext());
|
||||
assertTrue(cursor.hasNext());
|
||||
assertEquals(Integer.valueOf(1), cursor.fetchOne().getValue(TBook_ID()));
|
||||
assertEquals(Integer.valueOf(2), cursor.fetchOne().getValue(TBook_ID()));
|
||||
|
||||
assertTrue(cursor.hasNext());
|
||||
assertTrue(cursor.hasNext());
|
||||
assertFalse(cursor.isClosed());
|
||||
assertTrue(cursor.hasNext());
|
||||
assertTrue(cursor.hasNext());
|
||||
assertFalse(cursor.isClosed());
|
||||
|
||||
Iterator<B> it = cursor.iterator();
|
||||
assertTrue(it.hasNext());
|
||||
assertTrue(cursor.hasNext());
|
||||
assertTrue(it.hasNext());
|
||||
assertTrue(cursor.hasNext());
|
||||
assertTrue(it.hasNext());
|
||||
assertTrue(cursor.hasNext());
|
||||
assertEquals(Integer.valueOf(3), it.next().getValue(TBook_ID()));
|
||||
assertEquals(Integer.valueOf(4), it.next().getValue(TBook_ID()));
|
||||
assertFalse(cursor.isClosed());
|
||||
Iterator<B> it = cursor.iterator();
|
||||
assertTrue(it.hasNext());
|
||||
assertTrue(cursor.hasNext());
|
||||
assertTrue(it.hasNext());
|
||||
assertTrue(cursor.hasNext());
|
||||
assertTrue(it.hasNext());
|
||||
assertTrue(cursor.hasNext());
|
||||
assertEquals(Integer.valueOf(3), it.next().getValue(TBook_ID()));
|
||||
assertEquals(Integer.valueOf(4), it.next().getValue(TBook_ID()));
|
||||
assertFalse(cursor.isClosed());
|
||||
|
||||
assertFalse(it.hasNext());
|
||||
assertFalse(cursor.hasNext());
|
||||
assertFalse(it.hasNext());
|
||||
assertFalse(cursor.hasNext());
|
||||
assertFalse(it.hasNext());
|
||||
assertFalse(cursor.hasNext());
|
||||
assertTrue(cursor.isClosed());
|
||||
assertFalse(it.hasNext());
|
||||
assertFalse(cursor.hasNext());
|
||||
assertFalse(it.hasNext());
|
||||
assertFalse(cursor.hasNext());
|
||||
assertFalse(it.hasNext());
|
||||
assertFalse(cursor.hasNext());
|
||||
assertTrue(cursor.isClosed());
|
||||
|
||||
assertEquals(null, it.next());
|
||||
assertEquals(null, it.next());
|
||||
assertEquals(null, cursor.fetchOne());
|
||||
assertEquals(null, cursor.fetchOne());
|
||||
assertEquals(null, it.next());
|
||||
assertEquals(null, it.next());
|
||||
assertEquals(null, cursor.fetchOne());
|
||||
assertEquals(null, cursor.fetchOne());
|
||||
|
||||
cursor.close();
|
||||
cursor.close();
|
||||
assertTrue(cursor.isClosed());
|
||||
cursor.close();
|
||||
cursor.close();
|
||||
assertTrue(cursor.isClosed());
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Prematurely closing the cursor
|
||||
// ---------------------------------------------------------------------
|
||||
cursor = create().selectFrom(TBook()).orderBy(TBook_ID()).fetchLazy();
|
||||
// ---------------------------------------------------------------------
|
||||
// Prematurely closing the cursor
|
||||
// ---------------------------------------------------------------------
|
||||
cursor = create().selectFrom(TBook()).orderBy(TBook_ID()).fetchLazy(fetchSize);
|
||||
|
||||
assertTrue(cursor.hasNext());
|
||||
assertTrue(cursor.hasNext());
|
||||
assertEquals(Integer.valueOf(1), cursor.fetchOne().getValue(TBook_ID()));
|
||||
assertEquals(Integer.valueOf(2), cursor.fetchOne().getValue(TBook_ID()));
|
||||
assertFalse(cursor.isClosed());
|
||||
assertTrue(cursor.hasNext());
|
||||
assertTrue(cursor.hasNext());
|
||||
assertEquals(Integer.valueOf(1), cursor.fetchOne().getValue(TBook_ID()));
|
||||
assertEquals(Integer.valueOf(2), cursor.fetchOne().getValue(TBook_ID()));
|
||||
assertFalse(cursor.isClosed());
|
||||
|
||||
cursor.close();
|
||||
assertTrue(cursor.isClosed());
|
||||
assertFalse(cursor.hasNext());
|
||||
assertNull(cursor.fetchOne());
|
||||
cursor.close();
|
||||
assertTrue(cursor.isClosed());
|
||||
assertFalse(cursor.hasNext());
|
||||
assertNull(cursor.fetchOne());
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Fetching several records at once
|
||||
// ---------------------------------------------------------------------
|
||||
cursor = create().selectFrom(TBook()).orderBy(TBook_ID()).fetchLazy();
|
||||
// ---------------------------------------------------------------------
|
||||
// Fetching several records at once
|
||||
// ---------------------------------------------------------------------
|
||||
cursor = create().selectFrom(TBook()).orderBy(TBook_ID()).fetchLazy(fetchSize);
|
||||
|
||||
assertTrue(cursor.fetch(0).isEmpty());
|
||||
assertTrue(cursor.fetch(0).isEmpty());
|
||||
List<B> list = cursor.fetch(1);
|
||||
assertTrue(cursor.fetch(0).isEmpty());
|
||||
assertTrue(cursor.fetch(0).isEmpty());
|
||||
List<B> list = cursor.fetch(1);
|
||||
|
||||
assertEquals(1, list.size());
|
||||
assertEquals(Integer.valueOf(1), list.get(0).getValue(TBook_ID()));
|
||||
assertEquals(1, list.size());
|
||||
assertEquals(Integer.valueOf(1), list.get(0).getValue(TBook_ID()));
|
||||
|
||||
list = cursor.fetch(2);
|
||||
assertEquals(2, list.size());
|
||||
assertEquals(Integer.valueOf(2), list.get(0).getValue(TBook_ID()));
|
||||
assertEquals(Integer.valueOf(3), list.get(1).getValue(TBook_ID()));
|
||||
list = cursor.fetch(2);
|
||||
assertEquals(2, list.size());
|
||||
assertEquals(Integer.valueOf(2), list.get(0).getValue(TBook_ID()));
|
||||
assertEquals(Integer.valueOf(3), list.get(1).getValue(TBook_ID()));
|
||||
|
||||
list = cursor.fetch(2);
|
||||
assertTrue(cursor.isClosed());
|
||||
assertEquals(1, list.size());
|
||||
assertEquals(Integer.valueOf(4), list.get(0).getValue(TBook_ID()));
|
||||
list = cursor.fetch(2);
|
||||
assertTrue(cursor.isClosed());
|
||||
assertEquals(1, list.size());
|
||||
assertEquals(Integer.valueOf(4), list.get(0).getValue(TBook_ID()));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@ -38,6 +38,7 @@ package org.jooq;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.Statement;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
@ -83,20 +84,47 @@ public interface ResultQuery<R extends Record> extends Query {
|
||||
Result<R> fetch() throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Execute the query and return the generated result
|
||||
* Execute the query and "lazily" return the generated result
|
||||
* <p>
|
||||
* The returned {@link Cursor} holds a reference to the executed
|
||||
* {@link PreparedStatement} and the associated {@link ResultSet}. Data can
|
||||
* be fetched (or iterated over) lazily, fetching records from the
|
||||
* {@link ResultSet} one by one.
|
||||
* <p>
|
||||
* Depending on your JDBC driver's default behaviour, this may load the
|
||||
* whole database result into the driver's memory. In order to indicate to
|
||||
* the driver that you may not want to fetch all records at once, use
|
||||
* {@link #fetchLazy(int)}
|
||||
* <p>
|
||||
* Client code is responsible for closing the cursor after use.
|
||||
*
|
||||
* @return The resulting cursor.
|
||||
* @throws DataAccessException if something went wrong executing the query
|
||||
* @see #fetchLazy(int)
|
||||
*/
|
||||
Cursor<R> fetchLazy() throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Execute the query and "lazily" return the generated result
|
||||
* <p>
|
||||
* The returned {@link Cursor} holds a reference to the executed
|
||||
* {@link PreparedStatement} and the associated {@link ResultSet}. Data can
|
||||
* be fetched (or iterated over) lazily, fetching records from the
|
||||
* {@link ResultSet} one by one.
|
||||
* <p>
|
||||
* Depending on your JDBC driver's behaviour, this will load only
|
||||
* <code>fetchSize</code> records from the database into memory at once. For
|
||||
* more details, see also {@link Statement#setFetchSize(int)}
|
||||
* <p>
|
||||
* Client code is responsible for closing the cursor after use.
|
||||
*
|
||||
* @return The resulting cursor.
|
||||
* @throws DataAccessException if something went wrong executing the query
|
||||
* @see #fetchLazy()
|
||||
* @see Statement#setFetchSize(int)
|
||||
*/
|
||||
Cursor<R> fetchLazy(int fetchSize) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Execute a query, possibly returning several result sets.
|
||||
* <p>
|
||||
|
||||
@ -101,6 +101,11 @@ abstract class AbstractDelegatingSelect<R extends Record>
|
||||
return getDelegate().fetchLazy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Cursor<R> fetchLazy(int fetchSize) {
|
||||
return getDelegate().fetchLazy(fetchSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final List<Result<Record>> fetchMany() {
|
||||
return getDelegate().fetchMany();
|
||||
|
||||
@ -78,13 +78,14 @@ abstract class AbstractResultQuery<R extends Record> extends AbstractQuery imple
|
||||
/**
|
||||
* Generated UID
|
||||
*/
|
||||
private static final long serialVersionUID = -5588344253566055707L;
|
||||
private static final long serialVersionUID = -5588344253566055707L;
|
||||
|
||||
private transient boolean lazy;
|
||||
private transient boolean many;
|
||||
private transient Cursor<R> cursor;
|
||||
private Result<R> result;
|
||||
private List<Result<Record>> results;
|
||||
private transient boolean lazy;
|
||||
private transient int size;
|
||||
private transient boolean many;
|
||||
private transient Cursor<R> cursor;
|
||||
private Result<R> result;
|
||||
private List<Result<Record>> results;
|
||||
|
||||
AbstractResultQuery(Configuration configuration) {
|
||||
super(configuration);
|
||||
@ -107,6 +108,17 @@ abstract class AbstractResultQuery<R extends Record> extends AbstractQuery imple
|
||||
return (ResultQuery<R>) super.bind(index, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final PreparedStatement prepare(Configuration configuration, String sql) throws SQLException {
|
||||
PreparedStatement statement = super.prepare(configuration, sql);
|
||||
|
||||
if (size > 0) {
|
||||
statement.setFetchSize(size);
|
||||
}
|
||||
|
||||
return statement;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final int execute(Configuration configuration, PreparedStatement statement) throws SQLException {
|
||||
Connection connection = configuration.getConnection();
|
||||
@ -184,9 +196,21 @@ abstract class AbstractResultQuery<R extends Record> extends AbstractQuery imple
|
||||
|
||||
@Override
|
||||
public final Cursor<R> fetchLazy() {
|
||||
return fetchLazy(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Cursor<R> fetchLazy(int fetchSize) throws DataAccessException {
|
||||
lazy = true;
|
||||
execute();
|
||||
lazy = false;
|
||||
size = fetchSize;
|
||||
|
||||
try {
|
||||
execute();
|
||||
}
|
||||
finally {
|
||||
lazy = false;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
return cursor;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user