diff --git a/src/main/java/com/avaje/ebean/EbeanServer.java b/src/main/java/com/avaje/ebean/EbeanServer.java index 2956b51ce..f4710e709 100644 --- a/src/main/java/com/avaje/ebean/EbeanServer.java +++ b/src/main/java/com/avaje/ebean/EbeanServer.java @@ -757,9 +757,9 @@ public interface EbeanServer { /** * Return the Id values of the query as a List. * - * @see com.avaje.ebean.Query#findIds() + * @see Query#findIds() */ - List findIds(Query query, Transaction transaction); + List findIds(Query query, Transaction transaction); /** * Execute the query visiting the each bean one at a time. diff --git a/src/main/java/com/avaje/ebean/ExpressionList.java b/src/main/java/com/avaje/ebean/ExpressionList.java index 37a034d0b..c0c8f6512 100644 --- a/src/main/java/com/avaje/ebean/ExpressionList.java +++ b/src/main/java/com/avaje/ebean/ExpressionList.java @@ -174,7 +174,7 @@ public interface ExpressionList { * * @see Query#findIds() */ - List findIds(); + List findIds(); /** * Return the count of entities this query should return. diff --git a/src/main/java/com/avaje/ebean/FutureIds.java b/src/main/java/com/avaje/ebean/FutureIds.java index ab8d80a5d..fb280b349 100644 --- a/src/main/java/com/avaje/ebean/FutureIds.java +++ b/src/main/java/com/avaje/ebean/FutureIds.java @@ -9,8 +9,6 @@ import java.util.concurrent.Future; * It extends the java.util.concurrent.Future with the ability to get the Id's * while the query is still executing in the background. *

- * - * @author rbygrave */ public interface FutureIds extends Future> { @@ -19,16 +17,4 @@ public interface FutureIds extends Future> { */ Query getQuery(); - /** - * Return the list of Id's which could be partially populated. - *

- * That is the query getting the id's could still be running and adding id's - * to this list. - *

- *

- * To get the list of Id's ensuring the query has finished use the - * {@link Future#get()} method instead of this one. - *

- */ - List getPartialIds(); } diff --git a/src/main/java/com/avaje/ebean/Model.java b/src/main/java/com/avaje/ebean/Model.java index edf0572e1..3f0bf9606 100644 --- a/src/main/java/com/avaje/ebean/Model.java +++ b/src/main/java/com/avaje/ebean/Model.java @@ -598,7 +598,7 @@ public abstract class Model { *

* Equivalent to {@link Query#findIds()} */ - public List findIds() { + public List findIds() { return query().findIds(); } diff --git a/src/main/java/com/avaje/ebean/Query.java b/src/main/java/com/avaje/ebean/Query.java index 3baee31d8..7fb526336 100644 --- a/src/main/java/com/avaje/ebean/Query.java +++ b/src/main/java/com/avaje/ebean/Query.java @@ -542,7 +542,7 @@ public interface Query { * * @see EbeanServer#findIds(Query, Transaction) */ - List findIds(); + List findIds(); /** * Execute the query processing the beans one at a time. diff --git a/src/main/java/com/avaje/ebeaninternal/api/SpiEbeanServer.java b/src/main/java/com/avaje/ebeaninternal/api/SpiEbeanServer.java index 42b56053c..cc98af802 100644 --- a/src/main/java/com/avaje/ebeaninternal/api/SpiEbeanServer.java +++ b/src/main/java/com/avaje/ebeaninternal/api/SpiEbeanServer.java @@ -145,7 +145,7 @@ public interface SpiEbeanServer extends EbeanServer, BeanLoader, BeanCollectionL * the query has finished (if executing in a background thread). *

*/ - List findIdsWithCopy(Query query, Transaction t); + List findIdsWithCopy(Query query, Transaction t); /** * Execute the findRowCount query but without copying the query. diff --git a/src/main/java/com/avaje/ebeaninternal/api/SpiQuery.java b/src/main/java/com/avaje/ebeaninternal/api/SpiQuery.java index 7c9c10c62..b0254617b 100644 --- a/src/main/java/com/avaje/ebeaninternal/api/SpiQuery.java +++ b/src/main/java/com/avaje/ebeaninternal/api/SpiQuery.java @@ -251,21 +251,6 @@ public interface SpiQuery extends Query { List getSoftDeletePredicates(); - /** - * Set the list of Id's that is being populated. - *

- * This is a mutating list of id's and we are setting this so that other - * threads have access to the id's before the id query has finished. - *

- */ - void setIdList(List ids); - - /** - * Return the list of Id's that is currently being fetched by a background - * thread. - */ - List getIdList(); - /** * Return a copy of the query. */ diff --git a/src/main/java/com/avaje/ebeaninternal/server/core/DefaultServer.java b/src/main/java/com/avaje/ebeaninternal/server/core/DefaultServer.java index e6f062dcd..7b2af928f 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/core/DefaultServer.java +++ b/src/main/java/com/avaje/ebeaninternal/server/core/DefaultServer.java @@ -1191,16 +1191,14 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer { } } - public List findIds(Query query, Transaction t) { + public List findIds(Query query, Transaction t) { - SpiQuery copy = ((SpiQuery) query).copy(); - - return findIdsWithCopy(copy, t); + return findIdsWithCopy(((SpiQuery) query).copy(), t); } - public List findIdsWithCopy(Query query, Transaction t) { + public List findIdsWithCopy(Query query, Transaction t) { - SpiOrmQueryRequest request = createQueryRequest(Type.ID_LIST, query, t); + SpiOrmQueryRequest request = createQueryRequest(Type.ID_LIST, query, t); try { request.initTransIfRequired(); return request.findIds(); @@ -1258,12 +1256,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer { SpiQuery copy = ((SpiQuery) query).copy(); copy.setFutureFetch(true); - // this is the list we will put the id's in ... create it now so - // it is available for other threads to read while the id query - // is still executing (we don't need to wait for it to finish) - List idList = Collections.synchronizedList(new ArrayList()); - copy.setIdList(idList); - Transaction newTxn = createTransaction(); CallableQueryIds call = new CallableQueryIds(this, copy, newTxn); diff --git a/src/main/java/com/avaje/ebeaninternal/server/core/OrmQueryEngine.java b/src/main/java/com/avaje/ebeaninternal/server/core/OrmQueryEngine.java index a51b3a5b2..c38ce79ca 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/core/OrmQueryEngine.java +++ b/src/main/java/com/avaje/ebeaninternal/server/core/OrmQueryEngine.java @@ -44,7 +44,7 @@ public interface OrmQueryEngine { /** * Execute the find id's query. */ - BeanIdList findIds(OrmQueryRequest request); + List findIds(OrmQueryRequest request); /** * Execute the query as a delete statement. 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 e3d8a2126..c9bf91f82 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/core/OrmQueryRequest.java +++ b/src/main/java/com/avaje/ebeaninternal/server/core/OrmQueryRequest.java @@ -304,9 +304,8 @@ public final class OrmQueryRequest extends BeanRequest implements BeanQueryRe return queryEngine.findRowCount(this); } - public List findIds() { - BeanIdList idList = queryEngine.findIds(this); - return idList.getIdList(); + public List findIds() { + return queryEngine.findIds(this); } public void findEach(QueryEachConsumer consumer) { diff --git a/src/main/java/com/avaje/ebeaninternal/server/core/SpiOrmQueryRequest.java b/src/main/java/com/avaje/ebeaninternal/server/core/SpiOrmQueryRequest.java index ae0013f1a..b7ed67df4 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/core/SpiOrmQueryRequest.java +++ b/src/main/java/com/avaje/ebeaninternal/server/core/SpiOrmQueryRequest.java @@ -70,7 +70,7 @@ public interface SpiOrmQueryRequest extends DocQueryRequest { /** * Execute the find ids query. */ - List findIds(); + List findIds(); /** * Execute the find returning a QueryIterator and visitor pattern. diff --git a/src/main/java/com/avaje/ebeaninternal/server/expression/DefaultExpressionList.java b/src/main/java/com/avaje/ebeaninternal/server/expression/DefaultExpressionList.java index 83f1198b6..a1e97986c 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/expression/DefaultExpressionList.java +++ b/src/main/java/com/avaje/ebeaninternal/server/expression/DefaultExpressionList.java @@ -354,7 +354,7 @@ public class DefaultExpressionList implements SpiExpressionList { } @Override - public List findIds() { + public List findIds() { return query.findIds(); } diff --git a/src/main/java/com/avaje/ebeaninternal/server/query/CQueryBuilder.java b/src/main/java/com/avaje/ebeaninternal/server/query/CQueryBuilder.java index 73036ac06..ce8efe1fa 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/query/CQueryBuilder.java +++ b/src/main/java/com/avaje/ebeaninternal/server/query/CQueryBuilder.java @@ -189,33 +189,12 @@ public class CQueryBuilder { } /** - * Build the row count query. + * Build the find ids query. */ - public CQueryFetchIds buildFetchIdsQuery(OrmQueryRequest request) { + public CQueryFetchSingleAttribute buildFetchIdsQuery(OrmQueryRequest request) { - SpiQuery query = request.getQuery(); - query.setSelectId(); - - CQueryPredicates predicates = new CQueryPredicates(binder, request); - CQueryPlan queryPlan = request.getQueryPlan(); - if (queryPlan != null) { - // skip building the SqlTree and Sql string - predicates.prepare(false); - return new CQueryFetchIds(request, predicates, queryPlan.getSql()); - } - - // use RawSql or generated Sql - predicates.prepare(true); - - SqlTree sqlTree = createSqlTree(request, predicates, getHistorySupport(query), getDraftSupport(query)); - SqlLimitResponse s = buildSql(null, request, predicates, sqlTree); - String sql = s.getSql(); - - // cache the query plan - queryPlan = new CQueryPlan(request, sql, sqlTree, false, s.isIncludesRowNumberColumn(), predicates.getLogWhereSql()); - - request.putQueryPlan(queryPlan); - return new CQueryFetchIds(request, predicates, sql); + request.getQuery().setSelectId(); + return buildFetchAttributeQuery(request); } /** 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 bc105a514..bcf3d5da5 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/query/CQueryEngine.java +++ b/src/main/java/com/avaje/ebeaninternal/server/query/CQueryEngine.java @@ -1,17 +1,16 @@ 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; import com.avaje.ebean.bean.BeanCollection; import com.avaje.ebean.bean.EntityBean; import com.avaje.ebean.bean.ObjectGraphNode; +import com.avaje.ebean.config.ServerConfig; import com.avaje.ebean.config.dbplatform.DatabasePlatform; -import com.avaje.ebeaninternal.api.BeanIdList; import com.avaje.ebeaninternal.api.SpiQuery; import com.avaje.ebeaninternal.server.core.DiffHelp; import com.avaje.ebeaninternal.server.core.OrmQueryRequest; +import com.avaje.ebeaninternal.server.core.QueryIterator; import com.avaje.ebeaninternal.server.deploy.BeanDescriptor; import com.avaje.ebeaninternal.server.lib.util.Str; import com.avaje.ebeaninternal.server.persist.Binder; @@ -94,8 +93,13 @@ public class CQueryEngine { public List findSingleAttributeList(OrmQueryRequest request) { CQueryFetchSingleAttribute rcQuery = queryBuilder.buildFetchAttributeQuery(request); + return findAttributeList(request, rcQuery); + } + + @SuppressWarnings("unchecked") + private List findAttributeList(OrmQueryRequest request, CQueryFetchSingleAttribute rcQuery) { try { - List list = rcQuery.findList(); + List list = (List)rcQuery.findList(); if (request.isLogSql()) { logGeneratedSql(request, rcQuery.getGeneratedSql(), rcQuery.getBindLog()); } @@ -112,29 +116,10 @@ public class CQueryEngine { /** * Build and execute the find Id's query. */ - public BeanIdList findIds(OrmQueryRequest request) { + public List findIds(OrmQueryRequest request) { - CQueryFetchIds rcQuery = queryBuilder.buildFetchIdsQuery(request); - try { - - BeanIdList list = rcQuery.findIds(); - if (request.isLogSql()) { - logGeneratedSql(request, rcQuery.getGeneratedSql(), rcQuery.getBindLog()); - } - if (request.isLogSummary()) { - request.getTransaction().logSummary(rcQuery.getSummary()); - } - if (request.getQuery().isFutureFetch()) { - // end the transaction for futureFindIds (it had it's own one) - logger.debug("Future findIds completed!"); - request.getTransaction().end(); - } - - return list; - - } catch (SQLException e) { - throw CQuery.createPersistenceException(e, request.getTransaction(), rcQuery.getBindLog(), rcQuery.getGeneratedSql()); - } + CQueryFetchSingleAttribute rcQuery = queryBuilder.buildFetchIdsQuery(request); + return findAttributeList(request, rcQuery); } private void logGeneratedSql(OrmQueryRequest request, String sql, String bindLog) { diff --git a/src/main/java/com/avaje/ebeaninternal/server/query/CQueryFetchBase.java b/src/main/java/com/avaje/ebeaninternal/server/query/CQueryFetchBase.java deleted file mode 100644 index b25813bfc..000000000 --- a/src/main/java/com/avaje/ebeaninternal/server/query/CQueryFetchBase.java +++ /dev/null @@ -1,208 +0,0 @@ -package com.avaje.ebeaninternal.server.query; - -import com.avaje.ebean.bean.BeanCollection; -import com.avaje.ebean.bean.EntityBean; -import com.avaje.ebean.bean.EntityBeanIntercept; -import com.avaje.ebean.bean.PersistenceContext; -import com.avaje.ebeaninternal.api.SpiQuery; -import com.avaje.ebeaninternal.api.SpiQuery.Mode; -import com.avaje.ebeaninternal.api.SpiTransaction; -import com.avaje.ebeaninternal.server.core.OrmQueryRequest; -import com.avaje.ebeaninternal.server.deploy.BeanDescriptor; -import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocMany; -import com.avaje.ebeaninternal.server.deploy.DbReadContext; -import com.avaje.ebeaninternal.server.type.DataReader; -import com.avaje.ebeaninternal.server.type.RsetDataReader; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.Map; - -/** - * Base compiled query request for single attribute queries. - */ -public abstract class CQueryFetchBase { - - private static final Logger logger = LoggerFactory.getLogger(CQueryFetchBase.class); - - /** - * The overall find request wrapper object. - */ - protected final OrmQueryRequest request; - - protected final BeanDescriptor desc; - - protected final SpiQuery query; - - /** - * Where clause predicates. - */ - protected final CQueryPredicates predicates; - - /** - * The final sql that is generated. - */ - protected final String sql; - - protected RsetDataReader dataReader; - - /** - * The statement used to create the resultSet. - */ - protected PreparedStatement pstmt; - - protected String bindLog; - - protected int executionTimeMicros; - - protected int rowCount; - - protected final int maxRows; - - /** - * Create the Sql select based on the request. - */ - public CQueryFetchBase(OrmQueryRequest request, CQueryPredicates predicates, String sql) { - - this.request = request; - this.query = request.getQuery(); - this.sql = sql; - this.maxRows = query.getMaxRows(); - - query.setGeneratedSql(sql); - - this.desc = request.getBeanDescriptor(); - this.predicates = predicates; - } - - /** - * Return the bind log. - */ - public String getBindLog() { - return bindLog; - } - - /** - * Return the generated sql. - */ - public String getGeneratedSql() { - return sql; - } - - protected ResultSet prepareExecute() throws SQLException { - - SpiTransaction t = request.getTransaction(); - Connection conn = t.getInternalConnection(); - pstmt = conn.prepareStatement(sql); - - if (query.getBufferFetchSizeHint() > 0) { - pstmt.setFetchSize(query.getBufferFetchSizeHint()); - } - if (query.getTimeout() > 0) { - pstmt.setQueryTimeout(query.getTimeout()); - } - - bindLog = predicates.bind(pstmt, conn); - - ResultSet rset = pstmt.executeQuery(); - dataReader = new RsetDataReader(request.getDataTimeZone(), rset); - return rset; - } - - /** - * Close the resources. - *

- * The jdbc resultSet and statement need to be closed. Its important that - * this method is called. - *

- */ - protected void close() { - try { - if (dataReader != null) { - dataReader.close(); - dataReader = null; - } - } catch (SQLException e) { - logger.error("Error closing DataReader", e); - } - try { - if (pstmt != null) { - pstmt.close(); - pstmt = null; - } - } catch (SQLException e) { - logger.error("Error closing PreparedStatement", e); - } - } - - - protected class DbContext implements DbReadContext { - - public void propagateState(Object e) { - throw new RuntimeException("Not Called"); - } - - public Mode getQueryMode() { - return Mode.NORMAL; - } - - public DataReader getDataReader() { - return dataReader; - } - - public Boolean isReadOnly() { - return Boolean.FALSE; - } - - @Override - public boolean isDisableLazyLoading() { - return false; - } - - public boolean isRawSql() { - return false; - } - - public void register(String path, EntityBeanIntercept ebi) { - } - - public void register(String path, BeanCollection bc) { - } - - public BeanPropertyAssocMany getManyProperty() { - // always null - return null; - } - - public PersistenceContext getPersistenceContext() { - // always null - return null; - } - - public boolean isAutoTuneProfiling() { - return false; - } - - public void profileBean(EntityBeanIntercept ebi, String prefix) { - // no-op - } - - public void setCurrentPrefix(String currentPrefix, Map pathMap) { - // no-op - } - - public void setLazyLoadedChildBean(EntityBean loadedBean, Object lazyLoadParentId) { - // no-op - } - - @Override - public boolean isDraftQuery() { - return false; - } - } - -} diff --git a/src/main/java/com/avaje/ebeaninternal/server/query/CQueryFetchIds.java b/src/main/java/com/avaje/ebeaninternal/server/query/CQueryFetchIds.java deleted file mode 100644 index 96ecbc8ef..000000000 --- a/src/main/java/com/avaje/ebeaninternal/server/query/CQueryFetchIds.java +++ /dev/null @@ -1,96 +0,0 @@ -package com.avaje.ebeaninternal.server.query; - -import com.avaje.ebeaninternal.api.BeanIdList; -import com.avaje.ebeaninternal.server.core.OrmQueryRequest; -import com.avaje.ebeaninternal.server.deploy.DbReadContext; - -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * Executes the select row count query. - */ -public class CQueryFetchIds extends CQueryFetchBase { - - /** - * Create the Sql select based on the request. - */ - public CQueryFetchIds(OrmQueryRequest request, CQueryPredicates predicates, String sql) { - super(request, predicates, sql); - } - - /** - * Return a summary description of this query. - */ - public String getSummary() { - StringBuilder sb = new StringBuilder(80); - sb.append("FindIds exeMicros[").append(executionTimeMicros) - .append("] rows[").append(rowCount) - .append("] type[").append(desc.getName()) - .append("] predicates[").append(predicates.getLogWhereSql()) - .append("] bind[").append(bindLog).append("]"); - - return sb.toString(); - } - - /** - * Execute the query returning the row count. - */ - public BeanIdList findIds() throws SQLException { - - long startNano = System.nanoTime(); - - try { - // get the list that we are going to put the id's into. - // This was already set so that it is available to be - // read by other threads (it is a synchronised list) - List idList = query.getIdList(); - if (idList == null) { - // running in foreground thread (not FutureIds query) - idList = Collections.synchronizedList(new ArrayList()); - query.setIdList(idList); - } - - BeanIdList result = new BeanIdList(idList); - - ResultSet rset = prepareExecute(); - - boolean hitMaxRows = false; - boolean hasMoreRows = false; - rowCount = 0; - - DbReadContext ctx = new DbContext(); - - while (rset.next()) { - Object idValue = desc.getIdBinder().read(ctx); - idList.add(idValue); - // reset back to 0 - dataReader.resetColumnPosition(); - rowCount++; - - if (maxRows > 0 && rowCount == maxRows) { - hitMaxRows = true; - hasMoreRows = rset.next(); - break; - - } - } - - if (hitMaxRows) { - result.setHasMore(hasMoreRows); - } - - long exeNano = System.nanoTime() - startNano; - executionTimeMicros = (int) exeNano / 1000; - - return result; - - } finally { - close(); - } - } - -} diff --git a/src/main/java/com/avaje/ebeaninternal/server/query/CQueryFetchSingleAttribute.java b/src/main/java/com/avaje/ebeaninternal/server/query/CQueryFetchSingleAttribute.java index 324c80cac..431d84edd 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/query/CQueryFetchSingleAttribute.java +++ b/src/main/java/com/avaje/ebeaninternal/server/query/CQueryFetchSingleAttribute.java @@ -1,20 +1,58 @@ package com.avaje.ebeaninternal.server.query; +import com.avaje.ebeaninternal.api.SpiQuery; +import com.avaje.ebeaninternal.api.SpiTransaction; import com.avaje.ebeaninternal.server.core.OrmQueryRequest; -import com.avaje.ebeaninternal.server.deploy.BeanProperty; +import com.avaje.ebeaninternal.server.deploy.BeanDescriptor; +import com.avaje.ebeaninternal.server.type.RsetDataReader; import com.avaje.ebeaninternal.server.type.ScalarType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import java.sql.ResultSet; +import java.sql.Connection; +import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; /** - * Executes the select row count query. + * Base compiled query request for single attribute queries. */ -public class CQueryFetchSingleAttribute extends CQueryFetchBase { +class CQueryFetchSingleAttribute { - private final BeanProperty property; + private static final Logger logger = LoggerFactory.getLogger(CQueryFetchSingleAttribute.class); + + /** + * The overall find request wrapper object. + */ + private final OrmQueryRequest request; + + private final BeanDescriptor desc; + + private final SpiQuery query; + + /** + * Where clause predicates. + */ + private final CQueryPredicates predicates; + + /** + * The final sql that is generated. + */ + private final String sql; + + private RsetDataReader dataReader; + + /** + * The statement used to create the resultSet. + */ + private PreparedStatement pstmt; + + private String bindLog; + + private int executionTimeMicros; + + private int rowCount; private final ScalarType scalarType; @@ -22,15 +60,20 @@ public class CQueryFetchSingleAttribute extends CQueryFetchBase { * Create the Sql select based on the request. */ public CQueryFetchSingleAttribute(OrmQueryRequest request, CQueryPredicates predicates, CQueryPlan plan) { - super(request, predicates, plan.getSql()); - this.property = plan.getSingleProperty(); - this.scalarType = property.getScalarType(); + this.request = request; + this.query = request.getQuery(); + this.sql = plan.getSql(); + this.desc = request.getBeanDescriptor(); + this.predicates = predicates; + this.scalarType = plan.getSingleProperty().getScalarType(); + + query.setGeneratedSql(sql); } /** * Return a summary description of this query. */ - public String getSummary() { + protected String getSummary() { StringBuilder sb = new StringBuilder(80); sb.append("FindAttr exeMicros[").append(executionTimeMicros) .append("] rows[").append(rowCount) @@ -44,15 +87,16 @@ public class CQueryFetchSingleAttribute extends CQueryFetchBase { /** * Execute the query returning the row count. */ - public List findList() throws SQLException { + protected List findList() throws SQLException { long startNano = System.nanoTime(); try { + prepareExecute(); + List result = new ArrayList(); - ResultSet rset = prepareExecute(); - while (rset.next()) { + while (dataReader.next()) { result.add(scalarType.read(dataReader)); dataReader.resetColumnPosition(); rowCount++; @@ -68,4 +112,61 @@ public class CQueryFetchSingleAttribute extends CQueryFetchBase { } } + /** + * Return the bind log. + */ + protected String getBindLog() { + return bindLog; + } + + /** + * Return the generated sql. + */ + protected String getGeneratedSql() { + return sql; + } + + private void prepareExecute() throws SQLException { + + SpiTransaction t = request.getTransaction(); + Connection conn = t.getInternalConnection(); + pstmt = conn.prepareStatement(sql); + + if (query.getBufferFetchSizeHint() > 0) { + pstmt.setFetchSize(query.getBufferFetchSizeHint()); + } + if (query.getTimeout() > 0) { + pstmt.setQueryTimeout(query.getTimeout()); + } + + bindLog = predicates.bind(pstmt, conn); + dataReader = new RsetDataReader(request.getDataTimeZone(), pstmt.executeQuery()); + } + + /** + * Close the resources. + *

+ * The jdbc resultSet and statement need to be closed. Its important that + * this method is called. + *

+ */ + private void close() { + try { + if (dataReader != null) { + dataReader.close(); + dataReader = null; + } + } catch (SQLException e) { + logger.error("Error closing DataReader", e); + } + try { + if (pstmt != null) { + pstmt.close(); + pstmt = null; + } + } catch (SQLException e) { + logger.error("Error closing PreparedStatement", e); + } + } + } diff --git a/src/main/java/com/avaje/ebeaninternal/server/query/DefaultOrmQueryEngine.java b/src/main/java/com/avaje/ebeaninternal/server/query/DefaultOrmQueryEngine.java index 963e72e93..5a0a0112b 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/query/DefaultOrmQueryEngine.java +++ b/src/main/java/com/avaje/ebeaninternal/server/query/DefaultOrmQueryEngine.java @@ -65,7 +65,7 @@ public class DefaultOrmQueryEngine implements OrmQueryEngine { return queryEngine.findRowCount(request); } - public BeanIdList findIds(OrmQueryRequest request) { + public List findIds(OrmQueryRequest request) { flushJdbcBatchOnQuery(request); return queryEngine.findIds(request); diff --git a/src/main/java/com/avaje/ebeaninternal/server/query/QueryFutureIds.java b/src/main/java/com/avaje/ebeaninternal/server/query/QueryFutureIds.java index 85ff80907..bf0d595cf 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/query/QueryFutureIds.java +++ b/src/main/java/com/avaje/ebeaninternal/server/query/QueryFutureIds.java @@ -1,12 +1,12 @@ package com.avaje.ebeaninternal.server.query; -import java.util.List; -import java.util.concurrent.FutureTask; - import com.avaje.ebean.FutureIds; import com.avaje.ebean.Query; import com.avaje.ebean.Transaction; +import java.util.List; +import java.util.concurrent.FutureTask; + /** * Default implementation of FutureIds. */ @@ -31,10 +31,6 @@ public class QueryFutureIds extends BaseFuture> implements Futur return call.query; } - public List getPartialIds() { - return call.query.getIdList(); - } - public boolean cancel(boolean mayInterruptIfRunning) { call.query.cancel(); return super.cancel(mayInterruptIfRunning); 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 b3d3622db..179999d93 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/querydefn/DefaultOrmQuery.java +++ b/src/main/java/com/avaje/ebeaninternal/server/querydefn/DefaultOrmQuery.java @@ -123,8 +123,6 @@ public class DefaultOrmQuery implements SpiQuery { */ private ReadEvent futureFetchAudit; - private List partialIds; - private int timeout; /** @@ -1509,16 +1507,6 @@ public class DefaultOrmQuery implements SpiQuery { return disableReadAudit; } - @Override - public List getIdList() { - return partialIds; - } - - @Override - public void setIdList(List partialIds) { - this.partialIds = partialIds; - } - @Override public boolean isFutureFetch() { return futureFetch; diff --git a/src/test/java/com/avaje/ebeaninternal/api/TDSpiEbeanServer.java b/src/test/java/com/avaje/ebeaninternal/api/TDSpiEbeanServer.java index 030abb658..be387934e 100644 --- a/src/test/java/com/avaje/ebeaninternal/api/TDSpiEbeanServer.java +++ b/src/test/java/com/avaje/ebeaninternal/api/TDSpiEbeanServer.java @@ -186,7 +186,7 @@ public class TDSpiEbeanServer implements SpiEbeanServer { } @Override - public List findIdsWithCopy(Query query, Transaction t) { + public List findIdsWithCopy(Query query, Transaction t) { return null; } @@ -466,7 +466,7 @@ public class TDSpiEbeanServer implements SpiEbeanServer { } @Override - public List findIds(Query query, Transaction transaction) { + public List findIds(Query query, Transaction transaction) { return null; } diff --git a/src/test/java/com/avaje/tests/basic/TestFetchId.java b/src/test/java/com/avaje/tests/basic/TestFetchId.java index 06b046972..2e0908bfb 100644 --- a/src/test/java/com/avaje/tests/basic/TestFetchId.java +++ b/src/test/java/com/avaje/tests/basic/TestFetchId.java @@ -1,17 +1,17 @@ package com.avaje.tests.basic; -import java.util.List; -import java.util.concurrent.ExecutionException; - -import org.junit.Assert; -import org.junit.Test; - import com.avaje.ebean.BaseTestCase; import com.avaje.ebean.Ebean; import com.avaje.ebean.FutureIds; import com.avaje.ebean.Query; import com.avaje.tests.model.basic.Order; import com.avaje.tests.model.basic.ResetBasicData; +import org.junit.Test; + +import java.util.List; +import java.util.concurrent.ExecutionException; + +import static org.assertj.core.api.Assertions.assertThat; public class TestFetchId extends BaseTestCase { @@ -28,19 +28,12 @@ public class TestFetchId extends BaseTestCase { .query(); List ids = Ebean.getServer(null).findIds(query, null); + assertThat(ids).isNotEmpty(); FutureIds futureIds = Ebean.getServer(null).findFutureIds(query,null); - // this list is likely empty at this point and - // will get populated in the background - List partial = futureIds.getPartialIds(); - - // this is likely 0 or a small number - // wait for all the id's to be fetched List idList = futureIds.get(); - Assert.assertTrue("same instance", partial == idList); - - Assert.assertTrue("sz > 0", !ids.isEmpty()); + assertThat(idList).isNotEmpty(); } } diff --git a/src/test/java/com/avaje/tests/query/TestQueryPlanCacheRowCount.java b/src/test/java/com/avaje/tests/query/TestQueryPlanCacheRowCount.java index b31f33fe5..475fc4cfc 100644 --- a/src/test/java/com/avaje/tests/query/TestQueryPlanCacheRowCount.java +++ b/src/test/java/com/avaje/tests/query/TestQueryPlanCacheRowCount.java @@ -23,7 +23,7 @@ public class TestQueryPlanCacheRowCount extends BaseTestCase { int rc0 = query.findRowCount(); - List ids = query.findIds(); + List ids = query.findIds(); Assert.assertEquals(rc0, ids.size()); List list0 = query.findList(); @@ -32,7 +32,7 @@ public class TestQueryPlanCacheRowCount extends BaseTestCase { int rc1 = query.findCount(); Assert.assertEquals(rc0, rc1); - List ids1 = query.findIds(); + List ids1 = query.findIds(); Assert.assertEquals(rc0, ids1.size()); List list1 = query.findList(); @@ -53,7 +53,7 @@ public class TestQueryPlanCacheRowCount extends BaseTestCase { System.out.println("Expection Not same " + rc0 + " != " + rc2); Assert.assertNotSame(rc0, rc2); - List ids2 = query2.findIds(); + List ids2 = query2.findIds(); Assert.assertEquals(rc2, ids2.size()); List list2 = query2.findList(); diff --git a/src/test/java/com/avaje/tests/query/other/TestFindIdsWithInheritance.java b/src/test/java/com/avaje/tests/query/other/TestFindIdsWithInheritance.java index 511456106..fb65a46ee 100644 --- a/src/test/java/com/avaje/tests/query/other/TestFindIdsWithInheritance.java +++ b/src/test/java/com/avaje/tests/query/other/TestFindIdsWithInheritance.java @@ -20,8 +20,7 @@ public class TestFindIdsWithInheritance extends BaseTestCase { Ebean.save(truck); - List ids = Ebean.find(Vehicle.class).findIds(); - + List ids = Ebean.find(Vehicle.class).findIds(); Assert.assertNotNull(ids); Ebean.delete(truck); diff --git a/src/test/java/com/avaje/tests/query/other/TestObjectGraphNodeStatsCollection.java b/src/test/java/com/avaje/tests/query/other/TestObjectGraphNodeStatsCollection.java index 744559b44..9decc1dff 100644 --- a/src/test/java/com/avaje/tests/query/other/TestObjectGraphNodeStatsCollection.java +++ b/src/test/java/com/avaje/tests/query/other/TestObjectGraphNodeStatsCollection.java @@ -95,7 +95,7 @@ public class TestObjectGraphNodeStatsCollection extends BaseTestCase { ResetBasicData.reset(); - List ids = Ebean.find(Order.class).findIds(); + List ids = Ebean.find(Order.class).findIds(); Assert.assertTrue(!ids.isEmpty()); }