diff --git a/src/main/java/com/avaje/ebean/config/ServerConfig.java b/src/main/java/com/avaje/ebean/config/ServerConfig.java
index 8cea8842b..0d0ec8d7a 100644
--- a/src/main/java/com/avaje/ebean/config/ServerConfig.java
+++ b/src/main/java/com/avaje/ebean/config/ServerConfig.java
@@ -163,6 +163,17 @@ public class ServerConfig {
*/
private int databaseSequenceBatchSize = 20;
+ /**
+ * JDBC fetchSize hint when using findList. Defaults to 0 leaving it up to the JDBC driver.
+ */
+ private int jdbcFetchSizeFindList;
+
+ /**
+ * JDBC fetchSize hint when using findEach/findEachWhile. Defaults to 100. Note that this does
+ * not apply to MySql as that gets special treatment (forward only etc).
+ */
+ private int jdbcFetchSizeFindEach = 100;
+
/**
* Suffix appended to the base table to derive the view that contains the union
* of the base table and the history table in order to support asOf queries.
@@ -719,6 +730,34 @@ public class ServerConfig {
this.databaseSequenceBatchSize = databaseSequenceBatchSize;
}
+ /**
+ * Return the default JDBC fetchSize hint for findList queries.
+ */
+ public int getJdbcFetchSizeFindList() {
+ return jdbcFetchSizeFindList;
+ }
+
+ /**
+ * Set the default JDBC fetchSize hint for findList queries.
+ */
+ public void setJdbcFetchSizeFindList(int jdbcFetchSizeFindList) {
+ this.jdbcFetchSizeFindList = jdbcFetchSizeFindList;
+ }
+
+ /**
+ * Return the default JDBC fetchSize hint for findEach/findEachWhile queries.
+ */
+ public int getJdbcFetchSizeFindEach() {
+ return jdbcFetchSizeFindEach;
+ }
+
+ /**
+ * Set the default JDBC fetchSize hint for findEach/findEachWhile queries.
+ */
+ public void setJdbcFetchSizeFindEach(int jdbcFetchSizeFindEach) {
+ this.jdbcFetchSizeFindEach = jdbcFetchSizeFindEach;
+ }
+
/**
* Return the ChangeLogPrepare.
*
@@ -2405,6 +2444,8 @@ public class ServerConfig {
asOfSysPeriod = p.get("asOfSysPeriod", asOfSysPeriod);
historyTableSuffix = p.get("historyTableSuffix", historyTableSuffix);
dataSourceJndiName = p.get("dataSourceJndiName", dataSourceJndiName);
+ jdbcFetchSizeFindEach = p.getInt("jdbcFetchSizeFindEach", jdbcFetchSizeFindEach);
+ jdbcFetchSizeFindList = p.getInt("jdbcFetchSizeFindList", jdbcFetchSizeFindList);
databaseSequenceBatchSize = p.getInt("databaseSequenceBatchSize", databaseSequenceBatchSize);
databaseBooleanTrue = p.get("databaseBooleanTrue", databaseBooleanTrue);
databaseBooleanFalse = p.get("databaseBooleanFalse", databaseBooleanFalse);
diff --git a/src/main/java/com/avaje/ebeaninternal/api/SpiQuery.java b/src/main/java/com/avaje/ebeaninternal/api/SpiQuery.java
index 5cb45d3e0..40218a10c 100644
--- a/src/main/java/com/avaje/ebeaninternal/api/SpiQuery.java
+++ b/src/main/java/com/avaje/ebeaninternal/api/SpiQuery.java
@@ -625,6 +625,11 @@ public interface SpiQuery extends Query {
*/
void setGeneratedSql(String generatedSql);
+ /**
+ * Set the JDBC fetchSize buffer hint if not explicitly set.
+ */
+ void setDefaultFetchBuffer(int fetchSize);
+
/**
* Return the hint for Statement.setFetchSize().
*/
diff --git a/src/main/java/com/avaje/ebeaninternal/server/core/InternalConfiguration.java b/src/main/java/com/avaje/ebeaninternal/server/core/InternalConfiguration.java
index 45eceb8a4..219acce17 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/core/InternalConfiguration.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/core/InternalConfiguration.java
@@ -137,7 +137,7 @@ public class InternalConfiguration {
this.dataTimeZone = initDataTimeZone();
this.binder = getBinder(typeManager, databasePlatform, dataTimeZone);
- this.cQueryEngine = new CQueryEngine(databasePlatform, binder, asOfTableMapping, serverConfig.getAsOfSysPeriod(), draftTableMap);
+ this.cQueryEngine = new CQueryEngine(serverConfig, databasePlatform, binder, asOfTableMapping, draftTableMap);
}
/**
diff --git a/src/main/java/com/avaje/ebeaninternal/server/core/OrmQueryRequest.java b/src/main/java/com/avaje/ebeaninternal/server/core/OrmQueryRequest.java
index bfaf3207c..0aa5a472b 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/core/OrmQueryRequest.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/core/OrmQueryRequest.java
@@ -520,4 +520,11 @@ public final class OrmQueryRequest extends BeanRequest implements BeanQueryRe
public String getBaseTableAlias() {
return query.getAlias() == null ? beanDescriptor.getBaseTableAlias() : query.getAlias();
}
+
+ /**
+ * Set the JDBC buffer fetchSize hint if not set explicitly.
+ */
+ public void setDefaultFetchBuffer(int fetchSize) {
+ query.setDefaultFetchBuffer(fetchSize);
+ }
}
diff --git a/src/main/java/com/avaje/ebeaninternal/server/query/CQueryEngine.java b/src/main/java/com/avaje/ebeaninternal/server/query/CQueryEngine.java
index 839cb47df..425e488f8 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/query/CQueryEngine.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/query/CQueryEngine.java
@@ -1,5 +1,6 @@
package com.avaje.ebeaninternal.server.query;
+import com.avaje.ebean.config.ServerConfig;
import com.avaje.ebeaninternal.server.core.QueryIterator;
import com.avaje.ebean.ValuePair;
import com.avaje.ebean.Version;
@@ -35,15 +36,22 @@ public class CQueryEngine {
private static final String T0 = "t0";
+ private final int defaultFetchSizeFindList;
+
+ private final int defaultFetchSizeFindEach;
+
private final boolean forwardOnlyHintOnFindIterate;
private final CQueryBuilder queryBuilder;
private final CQueryHistorySupport historySupport;
- public CQueryEngine(DatabasePlatform dbPlatform, Binder binder, Map asOfTableMapping, String asOfSysPeriod, Map draftTableMap) {
+ public CQueryEngine(ServerConfig serverConfig, DatabasePlatform dbPlatform, Binder binder, Map asOfTableMapping, Map draftTableMap) {
+ this.defaultFetchSizeFindEach = serverConfig.getJdbcFetchSizeFindEach();
+ this.defaultFetchSizeFindList = serverConfig.getJdbcFetchSizeFindList();
this.forwardOnlyHintOnFindIterate = dbPlatform.isForwardOnlyHintOnFindIterate();
- this.historySupport = new CQueryHistorySupport(dbPlatform.getHistorySupport(), asOfTableMapping, asOfSysPeriod);
+
+ this.historySupport = new CQueryHistorySupport(dbPlatform.getHistorySupport(), asOfTableMapping, serverConfig.getAsOfSysPeriod());
this.queryBuilder = new CQueryBuilder(dbPlatform, binder, historySupport, new CQueryDraftSupport(draftTableMap));
}
@@ -91,11 +99,7 @@ public class CQueryEngine {
BeanIdList list = rcQuery.findIds();
if (request.isLogSql()) {
- String logSql = rcQuery.getGeneratedSql();
- if (TransactionManager.SQL_LOGGER.isTraceEnabled()) {
- logSql = Str.add(logSql, "; --bind(", rcQuery.getBindLog(), ")");
- }
- request.logSql(logSql);
+ logGeneratedSql(request, rcQuery.getGeneratedSql(), rcQuery.getBindLog());
}
if (request.isLogSummary()) {
@@ -115,6 +119,14 @@ public class CQueryEngine {
}
}
+ private void logGeneratedSql(OrmQueryRequest request, String sql, String bindLog) {
+ String logSql = sql;
+ if (TransactionManager.SQL_LOGGER.isTraceEnabled()) {
+ logSql = Str.add(logSql, "; --bind(", bindLog, ")");
+ }
+ request.logSql(logSql);
+ }
+
/**
* Build and execute the row count query.
*/
@@ -126,11 +138,7 @@ public class CQueryEngine {
int rowCount = rcQuery.findRowCount();
if (request.isLogSql()) {
- String logSql = rcQuery.getGeneratedSql();
- if (TransactionManager.SQL_LOGGER.isTraceEnabled()) {
- logSql = Str.add(logSql, "; --bind(", rcQuery.getBindLog(), ")");
- }
- request.logSql(logSql);
+ logGeneratedSql(request, rcQuery.getGeneratedSql(), rcQuery.getBindLog());
}
if (request.isLogSummary()) {
@@ -138,7 +146,6 @@ public class CQueryEngine {
}
if (request.getQuery().isFutureFetch()) {
- logger.debug("Future findRowCount completed!");
request.getTransaction().end();
}
@@ -159,7 +166,9 @@ public class CQueryEngine {
request.setCancelableQuery(cquery);
try {
-
+ if (defaultFetchSizeFindEach > 0) {
+ request.setDefaultFetchBuffer(defaultFetchSizeFindEach);
+ }
if (!cquery.prepareBindExecuteQueryForwardOnly(forwardOnlyHintOnFindIterate)) {
// query has been cancelled already
logger.trace("Future fetch already cancelled");
@@ -301,6 +310,9 @@ public class CQueryEngine {
request.setCancelableQuery(cquery);
try {
+ if (defaultFetchSizeFindList > 0) {
+ request.setDefaultFetchBuffer(defaultFetchSizeFindList);
+ }
if (!cquery.prepareBindExecuteQuery()) {
// query has been cancelled already
logger.trace("Future fetch already cancelled");
diff --git a/src/main/java/com/avaje/ebeaninternal/server/querydefn/DefaultOrmQuery.java b/src/main/java/com/avaje/ebeaninternal/server/querydefn/DefaultOrmQuery.java
index 996a4c087..4d74c5043 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/querydefn/DefaultOrmQuery.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/querydefn/DefaultOrmQuery.java
@@ -1366,6 +1366,13 @@ public class DefaultOrmQuery implements SpiQuery {
this.generatedSql = generatedSql;
}
+ @Override
+ public void setDefaultFetchBuffer(int fetchSize) {
+ if (bufferFetchSizeHint == 0) {
+ bufferFetchSizeHint = fetchSize;
+ }
+ }
+
@Override
public Query setBufferFetchSizeHint(int bufferFetchSizeHint) {
this.bufferFetchSizeHint = bufferFetchSizeHint;
diff --git a/src/test/java/com/avaje/ebean/config/ServerConfigTest.java b/src/test/java/com/avaje/ebean/config/ServerConfigTest.java
index 6701aa3dd..2f171ad7c 100644
--- a/src/test/java/com/avaje/ebean/config/ServerConfigTest.java
+++ b/src/test/java/com/avaje/ebean/config/ServerConfigTest.java
@@ -32,12 +32,16 @@ public class ServerConfigTest {
props.setProperty("persistBatch", "INSERT");
props.setProperty("persistBatchOnCascade", "INSERT");
props.setProperty("dbuuid","binary");
+ props.setProperty("jdbcFetchSizeFindEach", "42");
+ props.setProperty("jdbcFetchSizeFindList", "43");
serverConfig.loadFromProperties(props);
assertEquals(PersistBatch.INSERT, serverConfig.getPersistBatch());
assertEquals(PersistBatch.INSERT, serverConfig.getPersistBatchOnCascade());
assertEquals(ServerConfig.DbUuid.BINARY, serverConfig.getDbUuid());
+ assertEquals(42, serverConfig.getJdbcFetchSizeFindEach());
+ assertEquals(43, serverConfig.getJdbcFetchSizeFindList());
serverConfig.setPersistBatch(PersistBatch.NONE);
serverConfig.setPersistBatchOnCascade(PersistBatch.NONE);
diff --git a/src/test/java/com/avaje/tests/query/other/TestFindIterateHeapDump.java b/src/test/java/com/avaje/tests/query/other/TestFindIterateHeapDump.java
index bd7b2b8ac..652e6257e 100644
--- a/src/test/java/com/avaje/tests/query/other/TestFindIterateHeapDump.java
+++ b/src/test/java/com/avaje/tests/query/other/TestFindIterateHeapDump.java
@@ -1,19 +1,18 @@
package com.avaje.tests.query.other;
-import java.io.File;
-import java.lang.management.ManagementFactory;
-
-import javax.management.MBeanServer;
-
-import org.junit.Ignore;
-import org.junit.Test;
-
import com.avaje.ebean.BaseTestCase;
import com.avaje.ebean.Ebean;
import com.avaje.ebean.EbeanServer;
-import com.avaje.ebean.Transaction;
+import com.avaje.ebean.QueryEachConsumer;
import com.avaje.tests.model.basic.EBasic;
import com.sun.management.HotSpotDiagnosticMXBean;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import javax.management.MBeanServer;
+import java.io.File;
+import java.lang.management.ManagementFactory;
+import java.util.concurrent.atomic.AtomicInteger;
@SuppressWarnings("restriction")
public class TestFindIterateHeapDump extends BaseTestCase {
@@ -34,25 +33,43 @@ public class TestFindIterateHeapDump extends BaseTestCase {
@Test
public void test() {
- EbeanServer server = Ebean.getServer(null);
+ EbeanServer server = Ebean.getDefaultServer();
- Transaction transaction = server.beginTransaction();
- try {
- transaction.setBatchMode(true);
- transaction.setBatchSize(20);
- for (int i = 0; i < 10000; i++) {
- EBasic dumbModel = new EBasic();
- dumbModel.setName("Hello");
- server.save(dumbModel);
- }
- transaction.commit();
-
- } finally {
- transaction.end();
- }
+// Transaction transaction = server.beginTransaction();
+// try {
+// transaction.setBatchMode(true);
+// transaction.setBatchSize(20);
+// for (int i = 0; i < 20000; i++) {
+// EBasic dumbModel = new EBasic();
+// dumbModel.setName("Goodbye now");
+// server.save(dumbModel);
+// }
+// transaction.commit();
+//
+// } finally {
+// transaction.end();
+// }
+//
+// if (true) {
+// return;
+// }
// Intentionally not iterating through the iterator to
+ final AtomicInteger counter = new AtomicInteger();
+
+ server.find(EBasic.class)
+ .findEach(new QueryEachConsumer() {
+ @Override
+ public void accept(EBasic bean) {
+
+ int count = counter.incrementAndGet();
+ if (count == 1) {
+ dumpHeap("heap-dump13-initial.snapshot", true);
+ }
+ }
+ });
+
// try {
// while (iterate.hasNext()) {
// EBasic eBasic = iterate.next();
@@ -62,7 +79,7 @@ public class TestFindIterateHeapDump extends BaseTestCase {
// iterate.close();
// }
- String fileName = "heap-dump6.snapshot";
+ String fileName = "heap-dump13.snapshot";
File file = new File(fileName);
if (file.exists())