mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Revert "[15x] Remove "Future queries" findFutureList, findFutureIds, findFutureCount"
This commit is contained in:
@@ -412,6 +412,42 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
Optional<T> findOneOrEmpty();
|
||||
|
||||
/**
|
||||
* Execute find row count query in a background thread.
|
||||
* <p>
|
||||
* 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).
|
||||
* </p>
|
||||
*
|
||||
* @return a Future object for the row count query
|
||||
*/
|
||||
FutureRowCount<T> findFutureCount();
|
||||
|
||||
/**
|
||||
* Execute find Id's query in a background thread.
|
||||
* <p>
|
||||
* 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).
|
||||
* </p>
|
||||
*
|
||||
* @return a Future object for the list of Id's
|
||||
*/
|
||||
FutureIds<T> findFutureIds();
|
||||
|
||||
/**
|
||||
* Execute find list query in a background thread.
|
||||
* <p>
|
||||
* 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).
|
||||
* </p>
|
||||
*
|
||||
* @return a Future object for the list result of the query
|
||||
*/
|
||||
FutureList<T> findFutureList();
|
||||
|
||||
/**
|
||||
* Return a PagedList for this query using firstRow and maxRows.
|
||||
* <p>
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package io.ebean;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
/**
|
||||
* FutureIds represents the result of a background query execution for the Id's.
|
||||
* <p>
|
||||
* It extends the java.util.concurrent.Future with the ability to get the Id's
|
||||
* while the query is still executing in the background.
|
||||
* </p>
|
||||
*/
|
||||
public interface FutureIds<T> extends Future<List<Object>> {
|
||||
|
||||
/**
|
||||
* Returns the original query used to fetch the Id's.
|
||||
*/
|
||||
Query<T> getQuery();
|
||||
|
||||
}
|
||||
@@ -1087,6 +1087,41 @@ public interface Query<T> extends CancelableQuery {
|
||||
*/
|
||||
int findCount();
|
||||
|
||||
/**
|
||||
* Execute find row count query in a background thread.
|
||||
* <p>
|
||||
* 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).
|
||||
* </p>
|
||||
*
|
||||
* @return a Future object for the row count query
|
||||
*/
|
||||
FutureRowCount<T> findFutureCount();
|
||||
|
||||
/**
|
||||
* Execute find Id's query in a background thread.
|
||||
* <p>
|
||||
* 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).
|
||||
* </p>
|
||||
*
|
||||
* @return a Future object for the list of Id's
|
||||
*/
|
||||
FutureIds<T> findFutureIds();
|
||||
|
||||
/**
|
||||
* Execute find list query in a background thread.
|
||||
* <p>
|
||||
* 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.
|
||||
* </p>
|
||||
*
|
||||
* @return a Future object for the list result of the query
|
||||
*/
|
||||
FutureList<T> findFutureList();
|
||||
|
||||
/**
|
||||
* Return a PagedList for this query using firstRow and maxRows.
|
||||
* <p>
|
||||
|
||||
@@ -336,6 +336,10 @@ public interface SpiEbeanServer extends SpiServer, ExtendedServer, BeanCollectio
|
||||
|
||||
<T> FutureRowCount<T> findFutureCount(SpiQuery<T> query);
|
||||
|
||||
<T> FutureIds<T> findFutureIds(SpiQuery<T> query);
|
||||
|
||||
<T> FutureList<T> findFutureList(SpiQuery<T> query);
|
||||
|
||||
<T> PagedList<T> findPagedList(SpiQuery<T> query);
|
||||
|
||||
<T> Set<T> findSet(SpiQuery<T> query);
|
||||
|
||||
@@ -1200,6 +1200,45 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
return queryFuture;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> FutureIds<T> findFutureIds(SpiQuery<T> query) {
|
||||
SpiQuery<T> copy = query.copy();
|
||||
boolean createdTransaction = false;
|
||||
SpiTransaction transaction = query.transaction();
|
||||
if (transaction == null) {
|
||||
transaction = currentServerTransaction();
|
||||
if (transaction == null) {
|
||||
transaction = (SpiTransaction) createTransaction();
|
||||
createdTransaction = true;
|
||||
}
|
||||
copy.usingTransaction(transaction);
|
||||
}
|
||||
QueryFutureIds<T> queryFuture = new QueryFutureIds<>(new CallableQueryIds<>(this, copy, createdTransaction));
|
||||
backgroundExecutor.execute(queryFuture.futureTask());
|
||||
return queryFuture;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> FutureList<T> findFutureList(SpiQuery<T> query) {
|
||||
SpiQuery<T> spiQuery = query.copy();
|
||||
// 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
|
||||
boolean createdTransaction = false;
|
||||
SpiTransaction transaction = query.transaction();
|
||||
if (transaction == null) {
|
||||
transaction = currentServerTransaction();
|
||||
if (transaction == null) {
|
||||
transaction = (SpiTransaction) createTransaction();
|
||||
createdTransaction = true;
|
||||
}
|
||||
spiQuery.usingTransaction(transaction);
|
||||
}
|
||||
QueryFutureList<T> queryFuture = new QueryFutureList<>(new CallableQueryList<>(this, spiQuery, createdTransaction));
|
||||
backgroundExecutor.execute(queryFuture.futureTask());
|
||||
return queryFuture;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> PagedList<T> findPagedList(SpiQuery<T> query) {
|
||||
int maxRows = query.getMaxRows();
|
||||
|
||||
+15
@@ -218,6 +218,21 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
return query.update(transaction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FutureIds<T> findFutureIds() {
|
||||
return query.findFutureIds();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FutureRowCount<T> findFutureCount() {
|
||||
return query.findFutureCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FutureList<T> findFutureList() {
|
||||
return query.findFutureList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PagedList<T> findPagedList() {
|
||||
return query.findPagedList();
|
||||
|
||||
@@ -49,6 +49,21 @@ public final class FilterExpressionList<T> extends DefaultExpressionList<T> {
|
||||
return rootQuery.filterMany(prop);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FutureIds<T> findFutureIds() {
|
||||
return rootQuery.findFutureIds();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FutureList<T> findFutureList() {
|
||||
return rootQuery.findFutureList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FutureRowCount<T> findFutureCount() {
|
||||
return rootQuery.findFutureCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<T> findList() {
|
||||
return rootQuery.findList();
|
||||
|
||||
@@ -328,6 +328,21 @@ final class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, Expr
|
||||
return exprList.exists();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FutureIds<T> findFutureIds() {
|
||||
return exprList.findFutureIds();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FutureList<T> findFutureList() {
|
||||
return exprList.findFutureList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FutureRowCount<T> findFutureCount() {
|
||||
return exprList.findFutureCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <A> List<A> findIds() {
|
||||
return exprList.findIds();
|
||||
|
||||
@@ -12,6 +12,9 @@ import io.ebean.ExpressionList;
|
||||
import io.ebean.FetchConfig;
|
||||
import io.ebean.FetchGroup;
|
||||
import io.ebean.FetchPath;
|
||||
import io.ebean.FutureIds;
|
||||
import io.ebean.FutureList;
|
||||
import io.ebean.FutureRowCount;
|
||||
import io.ebean.OrderBy;
|
||||
import io.ebean.PagedList;
|
||||
import io.ebean.PersistenceContextScope;
|
||||
@@ -348,6 +351,21 @@ final class DefaultFetchGroupQuery<T> implements SpiFetchGroupQuery<T>, SpiQuery
|
||||
throw new RuntimeException("EB102: Only select() and fetch() clause is allowed on FetchGroup");
|
||||
}
|
||||
|
||||
@Override
|
||||
public FutureRowCount<T> findFutureCount() {
|
||||
throw new RuntimeException("EB102: Only select() and fetch() clause is allowed on FetchGroup");
|
||||
}
|
||||
|
||||
@Override
|
||||
public FutureIds<T> findFutureIds() {
|
||||
throw new RuntimeException("EB102: Only select() and fetch() clause is allowed on FetchGroup");
|
||||
}
|
||||
|
||||
@Override
|
||||
public FutureList<T> findFutureList() {
|
||||
throw new RuntimeException("EB102: Only select() and fetch() clause is allowed on FetchGroup");
|
||||
}
|
||||
|
||||
@Override
|
||||
public PagedList<T> findPagedList() {
|
||||
throw new RuntimeException("EB102: Only select() and fetch() clause is allowed on FetchGroup");
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package io.ebeaninternal.server.query;
|
||||
|
||||
import io.ebean.FutureIds;
|
||||
import io.ebean.Query;
|
||||
import io.ebean.Transaction;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.FutureTask;
|
||||
|
||||
/**
|
||||
* Default implementation of FutureIds.
|
||||
*/
|
||||
public final class QueryFutureIds<T> extends BaseFuture<List<Object>> implements FutureIds<T> {
|
||||
|
||||
private final CallableQueryIds<T> call;
|
||||
|
||||
public QueryFutureIds(CallableQueryIds<T> call) {
|
||||
super(new FutureTask<>(call));
|
||||
this.call = call;
|
||||
}
|
||||
|
||||
public FutureTask<List<Object>> futureTask() {
|
||||
return futureTask;
|
||||
}
|
||||
|
||||
public Transaction transaction() {
|
||||
return call.transaction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query<T> getQuery() {
|
||||
return call.query;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean cancel(boolean mayInterruptIfRunning) {
|
||||
call.query.cancel();
|
||||
return super.cancel(mayInterruptIfRunning);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package io.ebeaninternal.server.query;
|
||||
|
||||
import io.ebean.FutureList;
|
||||
import io.ebean.Query;
|
||||
import io.ebean.Transaction;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.FutureTask;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
/**
|
||||
* Default implementation for FutureList.
|
||||
*/
|
||||
public final class QueryFutureList<T> extends BaseFuture<List<T>> implements FutureList<T> {
|
||||
|
||||
private final CallableQueryList<T> call;
|
||||
|
||||
public QueryFutureList(CallableQueryList<T> call) {
|
||||
super(new FutureTask<>(call));
|
||||
this.call = call;
|
||||
}
|
||||
|
||||
public FutureTask<List<T>> futureTask() {
|
||||
return futureTask;
|
||||
}
|
||||
|
||||
public Transaction transaction() {
|
||||
return call.transaction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query<T> getQuery() {
|
||||
return call.query;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean cancel(boolean mayInterruptIfRunning) {
|
||||
call.query.cancel();
|
||||
return super.cancel(mayInterruptIfRunning);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<T> getUnchecked() {
|
||||
try {
|
||||
return get();
|
||||
|
||||
} catch (InterruptedException e) {
|
||||
// restore the interrupted status (so client can check for that)
|
||||
Thread.currentThread().interrupt();
|
||||
throw new PersistenceException(e);
|
||||
|
||||
} catch (ExecutionException e) {
|
||||
throw new PersistenceException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<T> getUnchecked(long timeout, TimeUnit unit) throws TimeoutException {
|
||||
try {
|
||||
return get(timeout, unit);
|
||||
|
||||
} catch (InterruptedException e) {
|
||||
// restore the interrupted status (so client can check for that)
|
||||
Thread.currentThread().interrupt();
|
||||
throw new PersistenceException(e);
|
||||
|
||||
} catch (ExecutionException e) {
|
||||
throw new PersistenceException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1489,6 +1489,21 @@ public class DefaultOrmQuery<T> extends AbstractQuery implements SpiQuery<T> {
|
||||
return server.findOneOrEmpty(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final FutureIds<T> findFutureIds() {
|
||||
return server.findFutureIds(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final FutureList<T> findFutureList() {
|
||||
return server.findFutureList(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final FutureRowCount<T> findFutureCount() {
|
||||
return server.findFutureCount(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final PagedList<T> findPagedList() {
|
||||
return server.findPagedList(this);
|
||||
|
||||
@@ -1782,6 +1782,47 @@ public abstract class TQRootBean<T, R> {
|
||||
return query.findCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute find row count query in a background thread.
|
||||
* <p>
|
||||
* 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).
|
||||
* </p>
|
||||
*
|
||||
* @return a Future object for the row count query
|
||||
*/
|
||||
public FutureRowCount<T> findFutureCount() {
|
||||
return query.findFutureCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute find Id's query in a background thread.
|
||||
* <p>
|
||||
* 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).
|
||||
* </p>
|
||||
*
|
||||
* @return a Future object for the list of Id's
|
||||
*/
|
||||
public FutureIds<T> findFutureIds() {
|
||||
return query.findFutureIds();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute find list query in a background thread.
|
||||
* <p>
|
||||
* 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.
|
||||
* </p>
|
||||
*
|
||||
* @return a Future object for the list result of the query
|
||||
*/
|
||||
public FutureList<T> findFutureList() {
|
||||
return query.findFutureList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a PagedList for this query using firstRow and maxRows.
|
||||
* <p>
|
||||
|
||||
@@ -574,6 +574,16 @@ public class TDSpiEbeanServer extends TDSpiServer implements SpiEbeanServer {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> FutureIds<T> findFutureIds(SpiQuery<T> query) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> FutureList<T> findFutureList(SpiQuery<T> query) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> PagedList<T> findPagedList(SpiQuery<T> query) {
|
||||
return null;
|
||||
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
package io.ebean.xtest.internal.server.query;
|
||||
|
||||
import io.ebean.*;
|
||||
import io.ebean.xtest.BaseTestCase;
|
||||
import io.ebeaninternal.server.query.QueryFutureIds;
|
||||
import io.ebeaninternal.server.query.QueryFutureList;
|
||||
import io.ebeaninternal.server.query.QueryFutureRowCount;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.tests.model.basic.Customer;
|
||||
import org.tests.model.basic.ResetBasicData;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
public class TestFutureRowCountErrorHandling extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void testFutureRowCount() throws InterruptedException {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
Database server = DB.getDefault();
|
||||
|
||||
Query<Customer> query = server.createQuery(Customer.class)
|
||||
.where().eq("doesNotExist", "this will fail")
|
||||
.query();
|
||||
|
||||
FutureRowCount<Customer> futureRowCount = query.findFutureCount();
|
||||
|
||||
QueryFutureRowCount<Customer> internalRowCount = (QueryFutureRowCount<Customer>) futureRowCount;
|
||||
Transaction t = internalRowCount.transaction();
|
||||
|
||||
try {
|
||||
futureRowCount.get();
|
||||
fail("never get here as the SQL is invalid");
|
||||
|
||||
} catch (ExecutionException e) {
|
||||
// Confirm the Transaction has been rolled back
|
||||
assertFalse(t.isActive());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFutureIds() throws InterruptedException {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
Database server = DB.getDefault();
|
||||
|
||||
Query<Customer> query = server.createQuery(Customer.class)
|
||||
.where().eq("doesNotExist", "this will fail")
|
||||
.query();
|
||||
|
||||
FutureIds<Customer> futureIds = query.findFutureIds();
|
||||
|
||||
QueryFutureIds<Customer> internalFuture = (QueryFutureIds<Customer>) futureIds;
|
||||
Transaction t = internalFuture.transaction();
|
||||
|
||||
try {
|
||||
internalFuture.get();
|
||||
fail("never get here as the SQL is invalid");
|
||||
|
||||
} catch (ExecutionException e) {
|
||||
// Confirm the Transaction has been rolled back
|
||||
assertFalse(t.isActive());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testFutureList() throws InterruptedException {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
Database server = DB.getDefault();
|
||||
|
||||
Query<Customer> query = server.createQuery(Customer.class)
|
||||
.where().eq("doesNotExist", "this will fail")
|
||||
.query();
|
||||
|
||||
FutureList<Customer> futureList = query.findFutureList();
|
||||
|
||||
QueryFutureList<Customer> internalFuture = (QueryFutureList<Customer>) futureList;
|
||||
Transaction t = internalFuture.transaction();
|
||||
|
||||
try {
|
||||
internalFuture.get();
|
||||
fail("never get here as the SQL is invalid");
|
||||
|
||||
} catch (ExecutionException e) {
|
||||
// Confirm the Transaction has been rolled back
|
||||
assertFalse(t.isActive());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package org.tests.basic;
|
||||
|
||||
import io.ebean.xtest.BaseTestCase;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.FutureIds;
|
||||
import io.ebean.Query;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.tests.model.basic.Order;
|
||||
@@ -29,6 +30,12 @@ public class TestFetchId extends BaseTestCase {
|
||||
|
||||
List<Object> ids = query.findIds();
|
||||
assertThat(ids).isNotEmpty();
|
||||
|
||||
FutureIds<Order> futureIds = query.findFutureIds();
|
||||
|
||||
// wait for all the id's to be fetched
|
||||
List<Object> idList = futureIds.get();
|
||||
assertThat(idList).isNotEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -46,6 +53,11 @@ public class TestFetchId extends BaseTestCase {
|
||||
List<Object> ids = query.findIds();
|
||||
// TODO: assert(query.getGeneratedSql())
|
||||
assertThat(ids).isNotEmpty();
|
||||
FutureIds<Order> futureIds = query.findFutureIds();
|
||||
|
||||
// wait for all the id's to be fetched
|
||||
List<Object> idList = futureIds.get();
|
||||
assertThat(idList).isNotEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -29,7 +29,118 @@ class TestFindFutureRowCount extends BaseTestCase {
|
||||
pagedList.loadCount();
|
||||
assertThat(pagedList.getList()).hasSize(1);
|
||||
assertThat(pagedList.getTotalCount()).isEqualTo(1);
|
||||
|
||||
FutureRowCount<EBasic> futureCount = DB.find(EBasic.class)
|
||||
.where().eq("name", "count_when_inTransaction")
|
||||
.findFutureCount();
|
||||
|
||||
assertThat(futureCount.get()).isEqualTo(1);
|
||||
|
||||
FutureRowCount<EBasic> futureCountUsingTxn = DB.find(EBasic.class)
|
||||
.usingTransaction(transaction)
|
||||
.where().eq("name", "count_when_inTransaction")
|
||||
.findFutureCount();
|
||||
|
||||
assertThat(futureCountUsingTxn.get()).isEqualTo(1);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void findFutureIds_when_inTransaction() throws Exception {
|
||||
try (Transaction transaction = DB.beginTransaction()) {
|
||||
EBasic basic = new EBasic("findFutureIds_when_inTransaction");
|
||||
DB.save(basic);
|
||||
|
||||
List<Object> ids = DB.find(EBasic.class)
|
||||
.where().eq("name", "findFutureIds_when_inTransaction")
|
||||
.findIds();
|
||||
|
||||
Object expectedIdValue = ids.get(0);
|
||||
|
||||
FutureIds<EBasic> futureIds = DB.find(EBasic.class)
|
||||
.where().eq("name", "findFutureIds_when_inTransaction")
|
||||
.findFutureIds();
|
||||
|
||||
List<Object> fids = futureIds.get();
|
||||
assertThat(fids).hasSize(1);
|
||||
assertThat(fids.get(0)).isEqualTo(expectedIdValue);
|
||||
|
||||
FutureIds<EBasic> futureIdsUsingTxn = DB.find(EBasic.class)
|
||||
.usingTransaction(transaction)
|
||||
.where().eq("name", "findFutureIds_when_inTransaction")
|
||||
.findFutureIds();
|
||||
|
||||
List<Object> fids2 = futureIdsUsingTxn.get();
|
||||
assertThat(fids2).hasSize(1);
|
||||
assertThat(fids2.get(0)).isEqualTo(expectedIdValue);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void findFutureList_when_inTransaction() throws Exception {
|
||||
try (Transaction transaction = DB.beginTransaction()) {
|
||||
EBasic basic = new EBasic("findFutureList_when_inTransaction");
|
||||
DB.save(basic);
|
||||
|
||||
List<EBasic> list = DB.find(EBasic.class)
|
||||
.where().eq("name", "findFutureList_when_inTransaction")
|
||||
.findList();
|
||||
|
||||
Object expectedIdValue = list.get(0).getId();
|
||||
|
||||
FutureList<EBasic> futureIds = DB.find(EBasic.class)
|
||||
.where().eq("name", "findFutureList_when_inTransaction")
|
||||
.findFutureList();
|
||||
|
||||
List<EBasic> fids = futureIds.get();
|
||||
assertThat(fids).hasSize(1);
|
||||
assertThat(fids.get(0).getId()).isEqualTo(expectedIdValue);
|
||||
|
||||
FutureList<EBasic> futureUsingTxn = DB.find(EBasic.class)
|
||||
.usingTransaction(transaction)
|
||||
.where().eq("name", "findFutureList_when_inTransaction")
|
||||
.findFutureList();
|
||||
|
||||
List<EBasic> fids2 = futureUsingTxn.get();
|
||||
assertThat(fids2).hasSize(1);
|
||||
assertThat(fids2.get(0).getId()).isEqualTo(expectedIdValue);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void findFutures_when_newTransaction() throws Exception {
|
||||
EBasic basic = new EBasic("findFutures_when_newTransaction");
|
||||
DB.save(basic);
|
||||
|
||||
List<EBasic> list = DB.find(EBasic.class)
|
||||
.where().eq("name", "findFutures_when_newTransaction")
|
||||
.findList();
|
||||
|
||||
Object expectedIdValue = list.get(0).getId();
|
||||
|
||||
FutureList<EBasic> futureList = DB.find(EBasic.class)
|
||||
.where().eq("name", "findFutures_when_newTransaction")
|
||||
.findFutureList();
|
||||
|
||||
List<EBasic> flist = futureList.get();
|
||||
assertThat(flist).hasSize(1);
|
||||
assertThat(flist.get(0).getId()).isEqualTo(expectedIdValue);
|
||||
|
||||
FutureIds<EBasic> futureIds = DB.find(EBasic.class)
|
||||
.where().eq("name", "findFutures_when_newTransaction")
|
||||
.findFutureIds();
|
||||
|
||||
List<Object> fids = futureIds.get();
|
||||
assertThat(fids).hasSize(1);
|
||||
assertThat(fids.get(0)).isEqualTo(expectedIdValue);
|
||||
|
||||
FutureRowCount<EBasic> futureCount = DB.find(EBasic.class)
|
||||
.where().eq("name", "findFutures_when_newTransaction")
|
||||
.findFutureCount();
|
||||
|
||||
assertThat(futureCount.get()).isEqualTo(1);
|
||||
|
||||
DB.delete(basic);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
package org.tests.query;
|
||||
|
||||
import io.ebean.xtest.BaseTestCase;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.FutureList;
|
||||
import io.ebean.Transaction;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.tests.model.basic.Order;
|
||||
import org.tests.model.basic.ResetBasicData;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class TestQueryFindFutureList extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void test_cancel() throws InterruptedException {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
// warm the connection pool
|
||||
Transaction t0 = DB.createTransaction();
|
||||
Transaction t1 = DB.createTransaction();
|
||||
Transaction t2 = DB.createTransaction();
|
||||
t0.end();
|
||||
t1.end();
|
||||
t2.end();
|
||||
|
||||
FutureList<Order> futureList = DB.find(Order.class).findFutureList();
|
||||
|
||||
Thread.sleep(10);
|
||||
futureList.cancel(true);
|
||||
// calling again is ignored
|
||||
futureList.cancel(true);
|
||||
|
||||
// don't shutdown immediately
|
||||
Thread.sleep(50);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_findFutureList() throws InterruptedException {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
FutureList<Order> futureList = DB.find(Order.class).findFutureList();
|
||||
|
||||
// wait for it to complete
|
||||
List<Order> orders = futureList.getUnchecked();
|
||||
|
||||
assertEquals(DB.find(Order.class).findCount(), orders.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_findFutureListWithTimeout() throws InterruptedException, TimeoutException {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
FutureList<Order> futureList = DB.find(Order.class).findFutureList();
|
||||
|
||||
// wait for it to complete
|
||||
List<Order> orders = futureList.getUnchecked(1, TimeUnit.SECONDS);
|
||||
|
||||
assertEquals(DB.find(Order.class).findCount(), orders.size());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -99,7 +99,10 @@ class SqlQueryCancelTest extends BaseTestCase {
|
||||
@Test
|
||||
public void cancelOrmQueryAtBegin() throws SQLException {
|
||||
doCancelOrmAtBegin(Query::findCount);
|
||||
doCancelOrmAtBegin(Query::findFutureCount);
|
||||
// We cannot test 'findCount' due H2 restrictions
|
||||
doCancelOrmAtBegin(Query::findFutureIds);
|
||||
doCancelOrmAtBegin(Query::findFutureList);
|
||||
doCancelOrmAtBegin(Query::findIds);
|
||||
doCancelOrmAtBegin(Query::findIterate);
|
||||
doCancelOrmAtBegin(Query::findList);
|
||||
@@ -123,6 +126,8 @@ class SqlQueryCancelTest extends BaseTestCase {
|
||||
// doCancelOrmDuringRun(Query::findCount);
|
||||
// testDuringRunFuture(Query::findFutureCount);
|
||||
// We cannot test 'findCount' due H2 restrictions
|
||||
doCancelOrmFutureDuringRun(Query::findFutureIds);
|
||||
doCancelOrmFutureDuringRun(Query::findFutureList);
|
||||
doCancelOrmDuringRun(Query::findIds);
|
||||
doCancelOrmDuringRun(Query::findIterate);
|
||||
doCancelOrmDuringRun(Query::findList);
|
||||
|
||||
@@ -138,7 +138,10 @@ class TestRawSqlOrmQuery extends BaseTestCase {
|
||||
List<Customer> list = query.findList();
|
||||
|
||||
int rowCount = query.findCount();
|
||||
FutureRowCount<Customer> futureRowCount = query.findFutureCount();
|
||||
|
||||
assertEquals(initialRowCount, rowCount);
|
||||
assertEquals(initialRowCount, futureRowCount.get().intValue());
|
||||
|
||||
// check that lazy loading still executes
|
||||
for (Customer customer : list) {
|
||||
|
||||
Reference in New Issue
Block a user