From 8237072f5be774a8de14ff737bd8aa93341c9a6b Mon Sep 17 00:00:00 2001 From: rbygrave Date: Mon, 1 Dec 2014 23:09:25 +1300 Subject: [PATCH] #217 - ENH: Restore findFutureList() removing its previous deprecated status. Change implementation to use its own PersistenceContext (aka PersistenceContextScope.QUERY) --- .../java/com/avaje/ebean/EbeanServer.java | 16 +- src/main/java/com/avaje/ebean/FutureList.java | 37 ++- src/main/java/com/avaje/ebean/Query.java | 6 +- .../server/core/DefaultServer.java | 14 +- .../server/expression/JunctionExpression.java | 72 +++++- .../server/query/QueryFutureList.java | 30 ++- .../util/DefaultExpressionList.java | 84 ++++++- .../util/FilterExpressionList.java | 213 ++++++++++-------- .../tests/query/TestQueryFindFutureList.java | 68 ++++++ 9 files changed, 399 insertions(+), 141 deletions(-) create mode 100644 src/test/java/com/avaje/tests/query/TestQueryFindFutureList.java diff --git a/src/main/java/com/avaje/ebean/EbeanServer.java b/src/main/java/com/avaje/ebean/EbeanServer.java index bab70c33e..3d506826f 100644 --- a/src/main/java/com/avaje/ebean/EbeanServer.java +++ b/src/main/java/com/avaje/ebean/EbeanServer.java @@ -545,19 +545,20 @@ public interface EbeanServer { public FutureIds findFutureIds(Query query, Transaction transaction); /** - * Execute find list query in a background thread. + * Execute find list query in a background thread returning a FutureList object. *

* This returns a Future object which can be used to cancel, check the - * execution status (isDone etc) and get the value (with or without a - * timeout). - *

- * + * execution status (isDone etc) and get the value (with or without a timeout). + *

+ * This query will execute in it's own PersistenceContext and using its own transaction. + * What that means is that it will not share any bean instances with other queries. + * + * * @param query * the query to execute in the background * @param transaction * the transaction (can be null). * @return a Future object for the list result of the query - * @deprecated */ public FutureList findFutureList(Query query, Transaction transaction); @@ -568,13 +569,12 @@ public interface EbeanServer { * execution status (isDone etc) and get the value (with or without a * timeout). *

- * + * * @param query * the query to execute in the background * @param transaction * the transaction (can be null). * @return a Future object for the list result of the query - * @deprecated */ public SqlFutureList findFutureList(SqlQuery query, Transaction transaction); diff --git a/src/main/java/com/avaje/ebean/FutureList.java b/src/main/java/com/avaje/ebean/FutureList.java index c0eeb3523..cb4efcb7d 100644 --- a/src/main/java/com/avaje/ebean/FutureList.java +++ b/src/main/java/com/avaje/ebean/FutureList.java @@ -1,7 +1,11 @@ package com.avaje.ebean; +import javax.persistence.PersistenceException; import java.util.List; +import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; /** * FutureList represents the result of a background query execution that will @@ -15,13 +19,13 @@ import java.util.concurrent.Future; * A simple example: *

* - *
+ * 
{@code
  *  // create a query to find all orders
- * Query<Order> query = Ebean.find(Order.class);
+ * Query query = Ebean.find(Order.class);
  * 
  *  // execute the query in a background thread
  *  // immediately returning the futureList
- * FutureList<Order> futureList = query.findFutureList();
+ * FutureList futureList = query.findFutureList();
  * 
  *  // do something else ... 
  * 
@@ -35,13 +39,11 @@ import java.util.concurrent.Future;
  * 
  * if (!futureList.isCancelled()){
  * 	// wait for the query to finish and return the list
- * 	List<Order> list = futureList.get();
+ * 	List list = futureList.get();
  * 	...
  * }
  * 
- * 
- * - * @author rbygrave + * }
*/ public interface FutureList extends Future> { @@ -50,4 +52,25 @@ public interface FutureList extends Future> { */ public Query getQuery(); + /** + * Same as {@link #get()} but wraps InterruptedException and ExecutionException in the + * unchecked PersistenceException. + * + * @return The query list result + * + * @throws PersistenceException when a InterruptedException or ExecutionException occurs. + */ + public List getUnchecked(); + + /** + * Same as {@link #get(long, java.util.concurrent.TimeUnit)} but wraps InterruptedException + * and ExecutionException in the unchecked PersistenceException. + * + * @return The query list result + * + * @throws TimeoutException if the wait timed out + * @throws PersistenceException if a InterruptedException or ExecutionException occurs. + */ + public List getUnchecked(long timeout, TimeUnit unit) throws TimeoutException; + } diff --git a/src/main/java/com/avaje/ebean/Query.java b/src/main/java/com/avaje/ebean/Query.java index fc26f05f2..f817fb67f 100644 --- a/src/main/java/com/avaje/ebean/Query.java +++ b/src/main/java/com/avaje/ebean/Query.java @@ -676,11 +676,11 @@ public interface Query extends Serializable { /** * Execute find list query in a background thread. *

- * Deprecated with a view to simplifying internals. + * This query will execute in it's own PersistenceContext and using its own transaction. + * What that means is that it will not share any bean instances with other queries. *

- * + * * @return a Future object for the list result of the query - * @deprecated */ public FutureList findFutureList(); 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 3acd632d9..eeed0025e 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/core/DefaultServer.java +++ b/src/main/java/com/avaje/ebeaninternal/server/core/DefaultServer.java @@ -1317,24 +1317,14 @@ public final class DefaultServer implements SpiEbeanServer { SpiQuery spiQuery = (SpiQuery) query; spiQuery.setFutureFetch(true); - // transfer the persistence content from the transaction - if (spiQuery.getPersistenceContext() == null) { - if (t != null) { - spiQuery.setPersistenceContext(((SpiTransaction) t).getPersistenceContext()); - } else { - SpiTransaction st = getCurrentServerTransaction(); - if (st != null) { - spiQuery.setPersistenceContext(st.getPersistenceContext()); - } - } - } + // FutureList query always run in it's own persistence content + spiQuery.setPersistenceContext(new DefaultPersistenceContext()); // Create a new transaction solely to execute the findList() at some future time Transaction newTxn = createTransaction(); CallableQueryList call = new CallableQueryList(this, spiQuery, newTxn); QueryFutureList queryFuture = new QueryFutureList(call); backgroundExecutor.execute(queryFuture.getFutureTask()); - return queryFuture; } diff --git a/src/main/java/com/avaje/ebeaninternal/server/expression/JunctionExpression.java b/src/main/java/com/avaje/ebeaninternal/server/expression/JunctionExpression.java index 38ffba170..447034efd 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/expression/JunctionExpression.java +++ b/src/main/java/com/avaje/ebeaninternal/server/expression/JunctionExpression.java @@ -59,6 +59,7 @@ abstract class JunctionExpression implements Junction, SpiExpression, Expr this.exprList = new DefaultExpressionList(query, parent); } + @Override public void containsMany(BeanDescriptor desc, ManyWhereJoins manyWhereJoin) { List list = exprList.internalList(); @@ -79,17 +80,20 @@ abstract class JunctionExpression implements Junction, SpiExpression, Expr } } + @Override public Junction add(Expression item) { SpiExpression i = (SpiExpression) item; exprList.add(i); return this; } + @Override public Junction addAll(ExpressionList addList) { exprList.addAll(addList); return this; } - + + @Override public void addBindValues(SpiExpressionRequest request) { List list = exprList.internalList(); @@ -100,6 +104,7 @@ abstract class JunctionExpression implements Junction, SpiExpression, Expr } } + @Override public void addSql(SpiExpressionRequest request) { List list = exprList.internalList(); @@ -122,6 +127,7 @@ abstract class JunctionExpression implements Junction, SpiExpression, Expr /** * Based on Junction type and all the expression contained. */ + @Override public void queryAutoFetchHash(HashQueryPlanBuilder builder) { builder.add(JunctionExpression.class).add(joinType); List list = exprList.internalList(); @@ -130,6 +136,7 @@ abstract class JunctionExpression implements Junction, SpiExpression, Expr } } + @Override public void queryPlanHash(BeanQueryRequest request, HashQueryPlanBuilder builder) { builder.add(JunctionExpression.class).add(joinType); List list = exprList.internalList(); @@ -138,6 +145,7 @@ abstract class JunctionExpression implements Junction, SpiExpression, Expr } } + @Override public int queryBindHash() { int hc = JunctionExpression.class.getName().hashCode(); @@ -149,50 +157,62 @@ abstract class JunctionExpression implements Junction, SpiExpression, Expr return hc; } + @Override public ExpressionList endJunction() { return exprList.endJunction(); } + @Override public ExpressionList allEq(Map propertyMap) { return exprList.allEq(propertyMap); } + @Override public ExpressionList and(Expression expOne, Expression expTwo) { return exprList.and(expOne, expTwo); } + @Override public ExpressionList between(String propertyName, Object value1, Object value2) { return exprList.between(propertyName, value1, value2); } + @Override public ExpressionList betweenProperties(String lowProperty, String highProperty, Object value) { return exprList.betweenProperties(lowProperty, highProperty, value); } + @Override public Junction conjunction() { return exprList.conjunction(); } + @Override public ExpressionList contains(String propertyName, String value) { return exprList.contains(propertyName, value); } + @Override public Junction disjunction() { return exprList.disjunction(); } + @Override public ExpressionList endsWith(String propertyName, String value) { return exprList.endsWith(propertyName, value); } + @Override public ExpressionList eq(String propertyName, Object value) { return exprList.eq(propertyName, value); } + @Override public ExpressionList exampleLike(Object example) { return exprList.exampleLike(example); } + @Override public ExpressionList filterMany(String prop) { throw new RuntimeException("filterMany not allowed on Junction expression list"); } @@ -202,18 +222,22 @@ abstract class JunctionExpression implements Junction, SpiExpression, Expr return exprList.apply(pathProperties); } + @Override public FutureIds findFutureIds() { return exprList.findFutureIds(); } + @Override public FutureList findFutureList() { return exprList.findFutureList(); } + @Override public FutureRowCount findFutureRowCount() { return exprList.findFutureRowCount(); } + @Override public List findIds() { return exprList.findIds(); } @@ -228,22 +252,27 @@ abstract class JunctionExpression implements Junction, SpiExpression, Expr exprList.findEachWhile(consumer); } + @Override public void findVisit(QueryResultVisitor visitor) { exprList.findVisit(visitor); } + @Override public QueryIterator findIterate() { return exprList.findIterate(); } + @Override public List findList() { return exprList.findList(); } + @Override public Map findMap() { return exprList.findMap(); } + @Override public Map findMap(String keyProperty, Class keyType) { return exprList.findMap(keyProperty, keyType); } @@ -253,166 +282,207 @@ abstract class JunctionExpression implements Junction, SpiExpression, Expr return exprList.findPagedList(pageIndex, pageSize); } + @Override public int findRowCount() { return exprList.findRowCount(); } + @Override public Set findSet() { return exprList.findSet(); } + @Override public T findUnique() { return exprList.findUnique(); } + @Override public ExpressionList ge(String propertyName, Object value) { return exprList.ge(propertyName, value); } + @Override public ExpressionList gt(String propertyName, Object value) { return exprList.gt(propertyName, value); } + @Override public ExpressionList having() { throw new RuntimeException("having() not allowed on Junction expression list"); } + @Override public ExpressionList icontains(String propertyName, String value) { return exprList.icontains(propertyName, value); } + @Override public ExpressionList idEq(Object value) { return exprList.idEq(value); } + @Override public ExpressionList idIn(List idValues) { return exprList.idIn(idValues); } + @Override public ExpressionList iendsWith(String propertyName, String value) { return exprList.iendsWith(propertyName, value); } + @Override public ExpressionList ieq(String propertyName, String value) { return exprList.ieq(propertyName, value); } + @Override public ExpressionList iexampleLike(Object example) { return exprList.iexampleLike(example); } + @Override public ExpressionList ilike(String propertyName, String value) { return exprList.ilike(propertyName, value); } + @Override public ExpressionList in(String propertyName, Collection values) { return exprList.in(propertyName, values); } + @Override public ExpressionList in(String propertyName, Object... values) { return exprList.in(propertyName, values); } + @Override public ExpressionList in(String propertyName, com.avaje.ebean.Query subQuery) { return exprList.in(propertyName, subQuery); } + @Override public ExpressionList isNotNull(String propertyName) { return exprList.isNotNull(propertyName); } + @Override public ExpressionList isNull(String propertyName) { return exprList.isNull(propertyName); } + @Override public ExpressionList istartsWith(String propertyName, String value) { return exprList.istartsWith(propertyName, value); } + @Override public ExpressionList le(String propertyName, Object value) { return exprList.le(propertyName, value); } + @Override public ExpressionList like(String propertyName, String value) { return exprList.like(propertyName, value); } + @Override public ExpressionList lt(String propertyName, Object value) { return exprList.lt(propertyName, value); } + @Override public ExpressionList ne(String propertyName, Object value) { return exprList.ne(propertyName, value); } + @Override public ExpressionList not(Expression exp) { return exprList.not(exp); } + @Override public ExpressionList or(Expression expOne, Expression expTwo) { return exprList.or(expOne, expTwo); } + @Override public OrderBy order() { return exprList.order(); } + @Override public com.avaje.ebean.Query order(String orderByClause) { return exprList.order(orderByClause); } + @Override public OrderBy orderBy() { return exprList.orderBy(); } + @Override public com.avaje.ebean.Query orderBy(String orderBy) { return exprList.orderBy(orderBy); } + @Override public com.avaje.ebean.Query query() { return exprList.query(); } + @Override public ExpressionList raw(String raw, Object value) { return exprList.raw(raw, value); } + @Override public ExpressionList raw(String raw, Object[] values) { return exprList.raw(raw, values); } + @Override public ExpressionList raw(String raw) { return exprList.raw(raw); } + @Override public com.avaje.ebean.Query select(String properties) { return exprList.select(properties); } + @Override public com.avaje.ebean.Query setFirstRow(int firstRow) { return exprList.setFirstRow(firstRow); } + @Override public com.avaje.ebean.Query setMapKey(String mapKey) { return exprList.setMapKey(mapKey); } + @Override public com.avaje.ebean.Query setMaxRows(int maxRows) { return exprList.setMaxRows(maxRows); } + @Override public com.avaje.ebean.Query setOrderBy(String orderBy) { return exprList.setOrderBy(orderBy); } + @Override public com.avaje.ebean.Query setUseCache(boolean useCache) { return exprList.setUseCache(useCache); } + @Override public ExpressionList startsWith(String propertyName, String value) { return exprList.startsWith(propertyName, value); } + @Override public ExpressionList where() { return exprList.where(); } diff --git a/src/main/java/com/avaje/ebeaninternal/server/query/QueryFutureList.java b/src/main/java/com/avaje/ebeaninternal/server/query/QueryFutureList.java index 6424b9faa..5f7963859 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/query/QueryFutureList.java +++ b/src/main/java/com/avaje/ebeaninternal/server/query/QueryFutureList.java @@ -1,12 +1,17 @@ package com.avaje.ebeaninternal.server.query; import java.util.List; +import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import com.avaje.ebean.FutureList; import com.avaje.ebean.Query; import com.avaje.ebean.Transaction; +import javax.persistence.PersistenceException; + /** * Default implementation for FutureList. */ @@ -26,15 +31,38 @@ public class QueryFutureList extends BaseFuture> implements FutureLis public Transaction getTransaction() { return call.transaction; } - + + @Override public Query getQuery() { return call.query; } + @Override public boolean cancel(boolean mayInterruptIfRunning) { call.query.cancel(); return super.cancel(mayInterruptIfRunning); } + @Override + public List getUnchecked() { + try { + return get(); + } catch (InterruptedException e) { + throw new PersistenceException(e); + } catch (ExecutionException e) { + throw new PersistenceException(e); + } + } + + @Override + public List getUnchecked(long timeout, TimeUnit unit) throws TimeoutException { + try { + return get(timeout, unit); + } catch (InterruptedException e) { + throw new PersistenceException(e); + } catch (ExecutionException e) { + throw new PersistenceException(e); + } + } } diff --git a/src/main/java/com/avaje/ebeaninternal/util/DefaultExpressionList.java b/src/main/java/com/avaje/ebeaninternal/util/DefaultExpressionList.java index fe6134976..fe7efb65f 100644 --- a/src/main/java/com/avaje/ebeaninternal/util/DefaultExpressionList.java +++ b/src/main/java/com/avaje/ebeaninternal/util/DefaultExpressionList.java @@ -54,6 +54,7 @@ public class DefaultExpressionList implements SpiExpressionList { this.listAndJoin = " and "; } + @Override public SpiExpressionList trimPath(int prefixTrim) { throw new RuntimeException("Only allowed on FilterExpressionList"); } @@ -68,6 +69,7 @@ public class DefaultExpressionList implements SpiExpressionList { * After deserialisation so that it can be further modified. *

*/ + @Override public void setExpressionFactory(ExpressionFactory expr) { this.expr = expr; } @@ -87,6 +89,7 @@ public class DefaultExpressionList implements SpiExpressionList { /** * Return true if one of the expressions is related to a Many property. */ + @Override public void containsMany(BeanDescriptor desc, ManyWhereJoins whereManyJoins) { for (int i = 0; i < list.size(); i++) { @@ -94,34 +97,42 @@ public class DefaultExpressionList implements SpiExpressionList { } } + @Override public ExpressionList endJunction() { return parentExprList == null ? this : parentExprList; } + @Override public Query query() { return query; } + @Override public ExpressionList where() { return query.where(); } + @Override public OrderBy order() { return query.order(); } + @Override public OrderBy orderBy() { return query.order(); } + @Override public Query order(String orderByClause) { return query.order(orderByClause); } + @Override public Query orderBy(String orderBy) { return query.order(orderBy); } + @Override public Query setOrderBy(String orderBy) { return query.order(orderBy); } @@ -131,14 +142,17 @@ public class DefaultExpressionList implements SpiExpressionList { return query.apply(pathProperties); } + @Override public FutureIds findFutureIds() { return query.findFutureIds(); } + @Override public FutureRowCount findFutureRowCount() { return query.findFutureRowCount(); } + @Override public FutureList findFutureList() { return query.findFutureList(); } @@ -148,10 +162,12 @@ public class DefaultExpressionList implements SpiExpressionList { return query.findPagedList(pageIndex, pageSize); } + @Override public int findRowCount() { return query.findRowCount(); } + @Override public List findIds() { return query.findIds(); } @@ -166,89 +182,100 @@ public class DefaultExpressionList implements SpiExpressionList { query.findEachWhile(consumer); } + @Override public void findVisit(QueryResultVisitor visitor) { query.findVisit(visitor); } + @Override public QueryIterator findIterate() { return query.findIterate(); } + @Override public List findList() { return query.findList(); } + @Override public Set findSet() { return query.findSet(); } + @Override public Map findMap() { return query.findMap(); } + @Override public Map findMap(String keyProperty, Class keyType) { return query.findMap(keyProperty, keyType); } + @Override public T findUnique() { return query.findUnique(); } + @Override public ExpressionList filterMany(String prop) { return query.filterMany(prop); } + @Override public Query select(String fetchProperties) { return query.select(fetchProperties); } - public Query join(String assocProperties) { - return query.fetch(assocProperties); - } - - public Query join(String assocProperty, String assocProperties) { - return query.fetch(assocProperty, assocProperties); - } - + @Override public Query setFirstRow(int firstRow) { return query.setFirstRow(firstRow); } + @Override public Query setMaxRows(int maxRows) { return query.setMaxRows(maxRows); } + @Override public Query setMapKey(String mapKey) { return query.setMapKey(mapKey); } + @Override public Query setUseCache(boolean useCache) { return query.setUseCache(useCache); } + @Override public ExpressionList having() { return query.having(); } + @Override public ExpressionList add(Expression expr) { list.add((SpiExpression) expr); return this; } + @Override public ExpressionList addAll(ExpressionList exprList) { SpiExpressionList spiList = (SpiExpressionList)exprList; list.addAll(spiList.getUnderlyingList()); return this; } - + + @Override public List getUnderlyingList() { return list; } - + + @Override public boolean isEmpty() { return list.isEmpty(); } + @Override public String buildSql(SpiExpressionRequest request) { request.append(listAndStart); @@ -263,6 +290,7 @@ public class DefaultExpressionList implements SpiExpressionList { return request.getSql(); } + @Override public ArrayList buildBindValues(SpiExpressionRequest request) { for (int i = 0, size = list.size(); i < size; i++) { @@ -288,6 +316,7 @@ public class DefaultExpressionList implements SpiExpressionList { * Calculate a hash based on the expressions but excluding the actual bind * values. */ + @Override public void queryPlanHash(BeanQueryRequest request, HashQueryPlanBuilder builder) { builder.add(DefaultExpressionList.class); for (int i = 0, size = list.size(); i < size; i++) { @@ -308,83 +337,99 @@ public class DefaultExpressionList implements SpiExpressionList { return hash; } + @Override public ExpressionList eq(String propertyName, Object value) { add(expr.eq(propertyName, value)); return this; } + @Override public ExpressionList ieq(String propertyName, String value) { add(expr.ieq(propertyName, value)); return this; } + @Override public ExpressionList ne(String propertyName, Object value) { add(expr.ne(propertyName, value)); return this; } + @Override public ExpressionList allEq(Map propertyMap) { add(expr.allEq(propertyMap)); return this; } + @Override public ExpressionList and(Expression expOne, Expression expTwo) { add(expr.and(expOne, expTwo)); return this; } + @Override public ExpressionList between(String propertyName, Object value1, Object value2) { add(expr.between(propertyName, value1, value2)); return this; } + @Override public ExpressionList betweenProperties(String lowProperty, String highProperty, Object value) { add(expr.betweenProperties(lowProperty, highProperty, value)); return this; } + @Override public Junction conjunction() { Junction conjunction = expr.conjunction(query, this); add(conjunction); return conjunction; } + @Override public ExpressionList contains(String propertyName, String value) { add(expr.contains(propertyName, value)); return this; } + @Override public Junction disjunction() { Junction disjunction = expr.disjunction(query, this); add(disjunction); return disjunction; } + @Override public ExpressionList endsWith(String propertyName, String value) { add(expr.endsWith(propertyName, value)); return this; } + @Override public ExpressionList ge(String propertyName, Object value) { add(expr.ge(propertyName, value)); return this; } + @Override public ExpressionList gt(String propertyName, Object value) { add(expr.gt(propertyName, value)); return this; } + @Override public ExpressionList icontains(String propertyName, String value) { add(expr.icontains(propertyName, value)); return this; } + @Override public ExpressionList idIn(List idList) { add(expr.idIn(idList)); return this; } + @Override public ExpressionList idEq(Object value) { if (query != null && parentExprList == null) { query.setId(value); @@ -394,96 +439,115 @@ public class DefaultExpressionList implements SpiExpressionList { return this; } + @Override public ExpressionList iendsWith(String propertyName, String value) { add(expr.iendsWith(propertyName, value)); return this; } + @Override public ExpressionList ilike(String propertyName, String value) { add(expr.ilike(propertyName, value)); return this; } + @Override public ExpressionList in(String propertyName, Query subQuery) { add(expr.in(propertyName, subQuery)); return this; } + @Override public ExpressionList in(String propertyName, Collection values) { add(expr.in(propertyName, values)); return this; } + @Override public ExpressionList in(String propertyName, Object... values) { add(expr.in(propertyName, values)); return this; } + @Override public ExpressionList isNotNull(String propertyName) { add(expr.isNotNull(propertyName)); return this; } + @Override public ExpressionList isNull(String propertyName) { add(expr.isNull(propertyName)); return this; } + @Override public ExpressionList istartsWith(String propertyName, String value) { add(expr.istartsWith(propertyName, value)); return this; } + @Override public ExpressionList le(String propertyName, Object value) { add(expr.le(propertyName, value)); return this; } + @Override public ExpressionList exampleLike(Object example) { add(expr.exampleLike(example)); return this; } + @Override public ExpressionList iexampleLike(Object example) { add(expr.iexampleLike(example)); return this; } + @Override public ExpressionList like(String propertyName, String value) { add(expr.like(propertyName, value)); return this; } + @Override public ExpressionList lt(String propertyName, Object value) { add(expr.lt(propertyName, value)); return this; } + @Override public ExpressionList not(Expression exp) { add(expr.not(exp)); return this; } + @Override public ExpressionList or(Expression expOne, Expression expTwo) { add(expr.or(expOne, expTwo)); return this; } + @Override public ExpressionList raw(String raw, Object value) { add(expr.raw(raw, value)); return this; } + @Override public ExpressionList raw(String raw, Object[] values) { add(expr.raw(raw, values)); return this; } + @Override public ExpressionList raw(String raw) { add(expr.raw(raw)); return this; } + @Override public ExpressionList startsWith(String propertyName, String value) { add(expr.startsWith(propertyName, value)); return this; diff --git a/src/main/java/com/avaje/ebeaninternal/util/FilterExpressionList.java b/src/main/java/com/avaje/ebeaninternal/util/FilterExpressionList.java index c2eeadd3b..32d92df6d 100644 --- a/src/main/java/com/avaje/ebeaninternal/util/FilterExpressionList.java +++ b/src/main/java/com/avaje/ebeaninternal/util/FilterExpressionList.java @@ -11,129 +11,144 @@ import java.util.Set; public class FilterExpressionList extends DefaultExpressionList { - private static final long serialVersionUID = 2226895827150099020L; + private static final long serialVersionUID = 2226895827150099020L; - private final Query rootQuery; - - private final FilterExprPath pathPrefix; + private final Query rootQuery; - public FilterExpressionList(FilterExprPath pathPrefix, FilterExpressionList original) { - super(null, original.expr, null, original.getUnderlyingList()); - this.pathPrefix = pathPrefix; - this.rootQuery = original.rootQuery; - } - - public FilterExpressionList(FilterExprPath pathPrefix, ExpressionFactory expr, Query rootQuery) { - super(null, expr, null); - this.pathPrefix = pathPrefix; - this.rootQuery = rootQuery; - } - - public SpiExpressionList trimPath(int prefixTrim) { - return new FilterExpressionList(pathPrefix.trimPath(prefixTrim), this); - } - - public FilterExprPath getPathPrefix() { - return pathPrefix; - } + private final FilterExprPath pathPrefix; - private String notAllowedMessage = "This method is not allowed on a filter"; - - public ExpressionList filterMany(String prop) { - return rootQuery.filterMany(prop); - } - - public FutureIds findFutureIds() { - return rootQuery.findFutureIds(); - } + public FilterExpressionList(FilterExprPath pathPrefix, FilterExpressionList original) { + super(null, original.expr, null, original.getUnderlyingList()); + this.pathPrefix = pathPrefix; + this.rootQuery = original.rootQuery; + } - public FutureList findFutureList() { - return rootQuery.findFutureList(); - } + public FilterExpressionList(FilterExprPath pathPrefix, ExpressionFactory expr, Query rootQuery) { + super(null, expr, null); + this.pathPrefix = pathPrefix; + this.rootQuery = rootQuery; + } - public FutureRowCount findFutureRowCount() { - return rootQuery.findFutureRowCount(); - } + @Override + public SpiExpressionList trimPath(int prefixTrim) { + return new FilterExpressionList(pathPrefix.trimPath(prefixTrim), this); + } - public List findList() { - return rootQuery.findList(); - } + public FilterExprPath getPathPrefix() { + return pathPrefix; + } - public Map findMap() { - return rootQuery.findMap(); - } + private String notAllowedMessage = "This method is not allowed on a filter"; - public int findRowCount() { - return rootQuery.findRowCount(); - } + @Override + public ExpressionList filterMany(String prop) { + return rootQuery.filterMany(prop); + } - public Set findSet() { - return rootQuery.findSet(); - } + @Override + public FutureIds findFutureIds() { + return rootQuery.findFutureIds(); + } - public T findUnique() { - return rootQuery.findUnique(); - } + @Override + public FutureList findFutureList() { + return rootQuery.findFutureList(); + } - public ExpressionList having() { - throw new PersistenceException(notAllowedMessage); - } + @Override + public FutureRowCount findFutureRowCount() { + return rootQuery.findFutureRowCount(); + } - public ExpressionList idEq(Object value) { - throw new PersistenceException(notAllowedMessage); - } + @Override + public List findList() { + return rootQuery.findList(); + } - public ExpressionList idIn(List idValues) { - throw new PersistenceException(notAllowedMessage); - } + @Override + public Map findMap() { + return rootQuery.findMap(); + } - public Query join(String assocProperty, String assocProperties) { - throw new PersistenceException(notAllowedMessage); - } + @Override + public int findRowCount() { + return rootQuery.findRowCount(); + } - public Query join(String assocProperties) { - throw new PersistenceException(notAllowedMessage); - } + @Override + public Set findSet() { + return rootQuery.findSet(); + } - public OrderBy order() { - return rootQuery.order(); - } + @Override + public T findUnique() { + return rootQuery.findUnique(); + } - public Query order(String orderByClause) { - return rootQuery.order(orderByClause); - } + @Override + public ExpressionList having() { + throw new PersistenceException(notAllowedMessage); + } - public Query orderBy(String orderBy) { - return rootQuery.orderBy(orderBy); - } + @Override + public ExpressionList idEq(Object value) { + throw new PersistenceException(notAllowedMessage); + } - public Query query() { - return rootQuery; - } + @Override + public ExpressionList idIn(List idValues) { + throw new PersistenceException(notAllowedMessage); + } - public Query select(String properties) { - throw new PersistenceException(notAllowedMessage); - } + @Override + public OrderBy order() { + return rootQuery.order(); + } - public Query setFirstRow(int firstRow) { - return rootQuery.setFirstRow(firstRow); - } + @Override + public Query order(String orderByClause) { + return rootQuery.order(orderByClause); + } - public Query setMapKey(String mapKey) { - return rootQuery.setMapKey(mapKey); - } + @Override + public Query orderBy(String orderBy) { + return rootQuery.orderBy(orderBy); + } - public Query setMaxRows(int maxRows) { - return rootQuery.setMaxRows(maxRows); - } + @Override + public Query query() { + return rootQuery; + } - public Query setUseCache(boolean useCache) { - return rootQuery.setUseCache(useCache); - } + @Override + public Query select(String properties) { + throw new PersistenceException(notAllowedMessage); + } + + @Override + public Query setFirstRow(int firstRow) { + return rootQuery.setFirstRow(firstRow); + } + + @Override + public Query setMapKey(String mapKey) { + return rootQuery.setMapKey(mapKey); + } + + @Override + public Query setMaxRows(int maxRows) { + return rootQuery.setMaxRows(maxRows); + } + + @Override + public Query setUseCache(boolean useCache) { + return rootQuery.setUseCache(useCache); + } + + @Override + public ExpressionList where() { + return rootQuery.where(); + } - public ExpressionList where() { - return rootQuery.where(); - } - } diff --git a/src/test/java/com/avaje/tests/query/TestQueryFindFutureList.java b/src/test/java/com/avaje/tests/query/TestQueryFindFutureList.java new file mode 100644 index 000000000..51d92f922 --- /dev/null +++ b/src/test/java/com/avaje/tests/query/TestQueryFindFutureList.java @@ -0,0 +1,68 @@ +package com.avaje.tests.query; + +import com.avaje.ebean.BaseTestCase; +import com.avaje.ebean.Ebean; +import com.avaje.ebean.FutureList; +import com.avaje.ebean.Transaction; +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.TimeUnit; +import java.util.concurrent.TimeoutException; + +import static org.junit.Assert.assertEquals; + +public class TestQueryFindFutureList extends BaseTestCase { + + @Test + public void test_cancel() throws InterruptedException { + + ResetBasicData.reset(); + + // warm the connection pool + Transaction t0 = Ebean.getServer(null).createTransaction(); + Transaction t1 = Ebean.getServer(null).createTransaction(); + Transaction t2 = Ebean.getServer(null).createTransaction(); + t0.end(); + t1.end(); + t2.end(); + + FutureList futureList = Ebean.find(Order.class).findFutureList(); + + Thread.sleep(10); + futureList.cancel(true); + + // don't shutdown immediately + Thread.sleep(50); + } + + @Test + public void test_findFutureList() throws InterruptedException { + + ResetBasicData.reset(); + + FutureList futureList = Ebean.find(Order.class).findFutureList(); + + // wait for it to complete + List orders = futureList.getUnchecked(); + + assertEquals(Ebean.find(Order.class).findRowCount(), orders.size()); + } + + @Test + public void test_findFutureListWithTimeout() throws InterruptedException, TimeoutException { + + ResetBasicData.reset(); + + FutureList futureList = Ebean.find(Order.class).findFutureList(); + + // wait for it to complete + List orders = futureList.getUnchecked(1, TimeUnit.SECONDS); + + assertEquals(Ebean.find(Order.class).findRowCount(), orders.size()); + } + +} +