mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
#599 - ElasticSearch - add query join support for find, findList, findPagedList, findEach, findEachWhile
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
package com.avaje.ebean;
|
||||
|
||||
import com.avaje.ebeanservice.docstore.api.DocQueryRequest;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -48,12 +49,12 @@ public interface DocumentStore {
|
||||
* If the document is not found null is returned.
|
||||
*/
|
||||
@Nullable
|
||||
<T> T find(Class<T> beanType, Object id);
|
||||
<T> T find(DocQueryRequest<T> request);
|
||||
|
||||
/**
|
||||
* Execute the query against the document store returning the list.
|
||||
* Execute the find list query. This request is prepared to execute secondary queries.
|
||||
*/
|
||||
<T> List<T> findList(Query<T> query);
|
||||
<T> List<T> findList(DocQueryRequest<T> request);
|
||||
|
||||
/**
|
||||
* Execute the query against the document store returning the paged list.
|
||||
@@ -61,7 +62,7 @@ public interface DocumentStore {
|
||||
* The query should have <code>firstRow</code> or <code>maxRows</code> set prior to calling this method.
|
||||
* </p>
|
||||
*/
|
||||
<T> PagedList<T> findPagedList(Query<T> query);
|
||||
<T> PagedList<T> findPagedList(DocQueryRequest<T> request);
|
||||
|
||||
/**
|
||||
* Execute the query against the document store with the expectation of a large set of results
|
||||
@@ -70,7 +71,7 @@ public interface DocumentStore {
|
||||
* For example, with the ElasticSearch doc store this uses SCROLL.
|
||||
* </p>
|
||||
*/
|
||||
<T> void findEach(Query<T> query, QueryEachConsumer<T> consumer);
|
||||
<T> void findEach(DocQueryRequest<T> query, QueryEachConsumer<T> consumer);
|
||||
|
||||
/**
|
||||
* Execute the query against the document store with the expectation of a large set of results
|
||||
@@ -82,7 +83,7 @@ public interface DocumentStore {
|
||||
* For example, with the ElasticSearch doc store this uses SCROLL.
|
||||
* </p>
|
||||
*/
|
||||
<T> void findEachWhile(Query<T> query, QueryEachWhileConsumer<T> consumer);
|
||||
<T> void findEachWhile(DocQueryRequest<T> query, QueryEachWhileConsumer<T> consumer);
|
||||
|
||||
/**
|
||||
* Process the queue entries sending updates to the document store or queuing them for later processing.
|
||||
|
||||
@@ -31,6 +31,11 @@ public interface BeanCollection<E> extends Serializable {
|
||||
ALL
|
||||
}
|
||||
|
||||
/**
|
||||
* Load bean from another collection.
|
||||
*/
|
||||
void loadFrom(BeanCollection<?> other);
|
||||
|
||||
/**
|
||||
* Add a bean to the list/set with modifyListen notification.
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.avaje.ebean.common;
|
||||
|
||||
import com.avaje.ebean.bean.BeanCollection;
|
||||
import com.avaje.ebean.bean.BeanCollectionAdd;
|
||||
import com.avaje.ebean.bean.BeanCollectionLoader;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
@@ -64,6 +65,15 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
list.add((E) bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void loadFrom(BeanCollection<?> other) {
|
||||
if (list == null) {
|
||||
list = new ArrayList<E>();
|
||||
}
|
||||
list.addAll((Collection<? extends E>) other.getActualDetails());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void internalAdd(Object bean) {
|
||||
if (list == null) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.avaje.ebean.common;
|
||||
|
||||
import com.avaje.ebean.bean.BeanCollection;
|
||||
import com.avaje.ebean.bean.BeanCollectionLoader;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
|
||||
@@ -51,6 +52,14 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
|
||||
return !touched && (map == null || map.isEmpty());
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void loadFrom(BeanCollection<?> other) {
|
||||
BeanMap<K,E> otherMap = (BeanMap<K,E>)other;
|
||||
internalPutNull();
|
||||
map.putAll(otherMap.getActualMap());
|
||||
}
|
||||
|
||||
public void internalPutNull() {
|
||||
if (map == null) {
|
||||
map = new LinkedHashMap<K, E>();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.avaje.ebean.common;
|
||||
|
||||
import com.avaje.ebean.bean.BeanCollection;
|
||||
import com.avaje.ebean.bean.BeanCollectionAdd;
|
||||
import com.avaje.ebean.bean.BeanCollectionLoader;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
@@ -57,6 +58,15 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
|
||||
set.add((E) bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void loadFrom(BeanCollection<?> other) {
|
||||
if (set == null) {
|
||||
set = new LinkedHashSet<E>();
|
||||
}
|
||||
set.addAll((Collection<? extends E>) other.getActualDetails());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void internalAddWithCheck(Object bean) {
|
||||
if (set == null || !set.contains(bean)) {
|
||||
|
||||
@@ -20,7 +20,7 @@ public interface JsonBeanReader<T> {
|
||||
/**
|
||||
* Create a new reader taking the context from the existing one but using a new JsonParser.
|
||||
*/
|
||||
JsonBeanReader<T> forJson(JsonParser moreJson);
|
||||
JsonBeanReader<T> forJson(JsonParser moreJson, boolean resetContext);
|
||||
|
||||
/**
|
||||
* Add a bean explicitly to the persistence context.
|
||||
|
||||
@@ -23,6 +23,8 @@ public class JsonReadOptions {
|
||||
|
||||
protected PersistenceContext persistenceContext;
|
||||
|
||||
protected Object loadContext;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
@@ -100,4 +102,19 @@ public class JsonReadOptions {
|
||||
public PersistenceContext getPersistenceContext() {
|
||||
return persistenceContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the load context to use.
|
||||
*/
|
||||
public Object getLoadContext() {
|
||||
return loadContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the load context to use.
|
||||
*/
|
||||
public void setLoadContext(Object loadContext) {
|
||||
this.loadContext = loadContext;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -16,38 +16,40 @@ public interface LoadContext {
|
||||
*/
|
||||
int getSecondaryQueriesMinBatchSize(int defaultQueryBatch);
|
||||
|
||||
/**
|
||||
* Execute any secondary (+query) queries if there are any defined.
|
||||
* @param parentRequest the originating query request
|
||||
*/
|
||||
void executeSecondaryQueries(OrmQueryRequest<?> parentRequest);
|
||||
/**
|
||||
* Execute any secondary (+query) queries if there are any defined.
|
||||
*
|
||||
* @param parentRequest the originating query request
|
||||
* @param forEach set true when using findEach iteration
|
||||
*/
|
||||
void executeSecondaryQueries(OrmQueryRequest<?> parentRequest, boolean forEach);
|
||||
|
||||
/**
|
||||
* Return the node for a given path which is used by AutoTune profiling.
|
||||
*/
|
||||
ObjectGraphNode getObjectGraphNode(String path);
|
||||
* Return the node for a given path which is used by AutoTune profiling.
|
||||
*/
|
||||
ObjectGraphNode getObjectGraphNode(String path);
|
||||
|
||||
/**
|
||||
* Return the persistence context used by this query and future lazy loading.
|
||||
*/
|
||||
PersistenceContext getPersistenceContext();
|
||||
/**
|
||||
* Return the persistence context used by this query and future lazy loading.
|
||||
*/
|
||||
PersistenceContext getPersistenceContext();
|
||||
|
||||
/**
|
||||
* Set the persistence context used by this query and future lazy loading.
|
||||
* <p>
|
||||
* Used by query iterator when processing large result sets.
|
||||
* </p>
|
||||
*/
|
||||
void resetPersistenceContext(PersistenceContext persistenceContext);
|
||||
/**
|
||||
* Set the persistence context used by this query and future lazy loading.
|
||||
* <p>
|
||||
* Used by query iterator when processing large result sets.
|
||||
* </p>
|
||||
*/
|
||||
void resetPersistenceContext(PersistenceContext persistenceContext);
|
||||
|
||||
/**
|
||||
* Register a Bean for lazy loading.
|
||||
*/
|
||||
void register(String path, EntityBeanIntercept ebi);
|
||||
/**
|
||||
* Register a Bean for lazy loading.
|
||||
*/
|
||||
void register(String path, EntityBeanIntercept ebi);
|
||||
|
||||
/**
|
||||
* Register a collection for lazy loading.
|
||||
*/
|
||||
void register(String path, BeanCollection<?> bc);
|
||||
/**
|
||||
* Register a collection for lazy loading.
|
||||
*/
|
||||
void register(String path, BeanCollection<?> bc);
|
||||
|
||||
}
|
||||
|
||||
@@ -14,5 +14,5 @@ public interface LoadSecondaryQuery {
|
||||
/**
|
||||
* Execute the secondary query with a given batch size.
|
||||
*/
|
||||
void loadSecondaryQuery(OrmQueryRequest<?> parentRequest);
|
||||
void loadSecondaryQuery(OrmQueryRequest<?> parentRequest, boolean forEach);
|
||||
}
|
||||
|
||||
@@ -1124,7 +1124,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
|
||||
SpiOrmQueryRequest<T> request = createQueryRequest(spiQuery, t);
|
||||
if (request.isUseDocStore()) {
|
||||
return docStore().find(query.getBeanType(), query.getId());
|
||||
return docStore().find(request);
|
||||
}
|
||||
try {
|
||||
request.initTransIfRequired();
|
||||
@@ -1329,7 +1329,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
}
|
||||
|
||||
if (spiQuery.isUseDocStore()) {
|
||||
return docStore().findPagedList(query);
|
||||
return docStore().findPagedList(createQueryRequest(Type.LIST, query, transaction));
|
||||
}
|
||||
|
||||
return new LimitOffsetPagedList<T>(this, spiQuery);
|
||||
@@ -1340,7 +1340,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
SpiOrmQueryRequest<T> request = createQueryRequest(Type.ITERATE, query, t);
|
||||
|
||||
if (request.isUseDocStore()) {
|
||||
docStore().findEach(query, consumer);
|
||||
docStore().findEach(request, consumer);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1353,7 +1353,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
|
||||
SpiOrmQueryRequest<T> request = createQueryRequest(Type.ITERATE, query, t);
|
||||
if (request.isUseDocStore()) {
|
||||
docStore().findEachWhile(query, consumer);
|
||||
docStore().findEachWhile(request, consumer);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1398,7 +1398,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
return (List<T>) result;
|
||||
}
|
||||
if (request.isUseDocStore()) {
|
||||
return docStore().findList(query);
|
||||
return docStore().findList(request);
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.avaje.ebean.bean.PersistenceContext;
|
||||
import com.avaje.ebean.event.BeanFindController;
|
||||
import com.avaje.ebean.event.BeanQueryAdapter;
|
||||
import com.avaje.ebean.event.BeanQueryRequest;
|
||||
import com.avaje.ebean.text.json.JsonReadOptions;
|
||||
import com.avaje.ebeaninternal.api.BeanIdList;
|
||||
import com.avaje.ebeaninternal.api.CQueryPlanKey;
|
||||
import com.avaje.ebeaninternal.api.HashQuery;
|
||||
@@ -59,6 +60,8 @@ public final class OrmQueryRequest<T> extends BeanRequest implements BeanQueryRe
|
||||
|
||||
private PersistenceContext persistenceContext;
|
||||
|
||||
private JsonReadOptions jsonRead;
|
||||
|
||||
private HashQuery cacheKey;
|
||||
|
||||
private CQueryPlanKey queryPlanKey;
|
||||
@@ -94,8 +97,11 @@ public final class OrmQueryRequest<T> extends BeanRequest implements BeanQueryRe
|
||||
return ebeanServer.getDatabasePlatform().getLikeClause();
|
||||
}
|
||||
|
||||
public void executeSecondaryQueries() {
|
||||
loadContext.executeSecondaryQueries(this);
|
||||
public void executeSecondaryQueries(boolean forEach) {
|
||||
// disable lazy loading leaves loadContext null
|
||||
if (loadContext != null) {
|
||||
loadContext.executeSecondaryQueries(this, forEach);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -152,7 +158,6 @@ public final class OrmQueryRequest<T> extends BeanRequest implements BeanQueryRe
|
||||
public void prepareQuery() {
|
||||
|
||||
adapterPreQuery();
|
||||
|
||||
this.secondaryQueries = query.convertJoins();
|
||||
this.queryPlanKey = query.prepare(this);
|
||||
}
|
||||
@@ -213,9 +218,27 @@ public final class OrmQueryRequest<T> extends BeanRequest implements BeanQueryRe
|
||||
createdTransaction = true;
|
||||
}
|
||||
}
|
||||
// initialise the persistenceContext and loadContext
|
||||
this.persistenceContext = getPersistenceContext(query, transaction);
|
||||
this.loadContext = new DLoadContext(this, secondaryQueries);
|
||||
persistenceContext = getPersistenceContext(query, transaction);
|
||||
loadContext = new DLoadContext(this, secondaryQueries);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the JsonReadOptions taking into account lazy loading and persistence context.
|
||||
*/
|
||||
public JsonReadOptions createJsonReadOptions() {
|
||||
|
||||
persistenceContext = getPersistenceContext(query, transaction);
|
||||
if (query.getPersistenceContext() == null) {
|
||||
query.setPersistenceContext(persistenceContext);
|
||||
}
|
||||
jsonRead = new JsonReadOptions();
|
||||
jsonRead.setPersistenceContext(persistenceContext);
|
||||
if (!query.isDisableLazyLoading()) {
|
||||
loadContext = new DLoadContext(this, secondaryQueries);
|
||||
jsonRead.setLoadContext(loadContext);
|
||||
}
|
||||
|
||||
return jsonRead;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -224,6 +247,10 @@ public final class OrmQueryRequest<T> extends BeanRequest implements BeanQueryRe
|
||||
public void flushPersistenceContextOnIterate() {
|
||||
persistenceContext = new DefaultPersistenceContext();
|
||||
loadContext.resetPersistenceContext(persistenceContext);
|
||||
if (jsonRead != null) {
|
||||
jsonRead.setPersistenceContext(persistenceContext);
|
||||
jsonRead.setLoadContext(loadContext);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -239,7 +266,7 @@ public final class OrmQueryRequest<T> extends BeanRequest implements BeanQueryRe
|
||||
|
||||
// determine the scope (from the query and then server)
|
||||
PersistenceContextScope scope = ebeanServer.getPersistenceContextScope(query);
|
||||
return (scope == PersistenceContextScope.QUERY) ? new DefaultPersistenceContext() : t.getPersistenceContext();
|
||||
return (scope == PersistenceContextScope.QUERY || t == null) ? new DefaultPersistenceContext() : t.getPersistenceContext();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,6 +7,7 @@ import com.avaje.ebean.Version;
|
||||
import com.avaje.ebean.bean.BeanCollection;
|
||||
import com.avaje.ebeaninternal.api.SpiQuery;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import com.avaje.ebeanservice.docstore.api.DocQueryRequest;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -15,7 +16,7 @@ import java.util.Set;
|
||||
/**
|
||||
* Defines the ORM query request api.
|
||||
*/
|
||||
public interface SpiOrmQueryRequest<T> {
|
||||
public interface SpiOrmQueryRequest<T> extends DocQueryRequest<T> {
|
||||
|
||||
/**
|
||||
* Return the query.
|
||||
|
||||
@@ -107,6 +107,28 @@ public class BeanDescriptor<T> implements MetaBeanInfo, BeanType<T> {
|
||||
|
||||
private final ConcurrentHashMap<String, ElComparator<T>> comparatorCache = new ConcurrentHashMap<String, ElComparator<T>>();
|
||||
|
||||
public void merge(EntityBean bean, EntityBean existing) {
|
||||
|
||||
EntityBeanIntercept fromEbi = bean._ebean_getIntercept();
|
||||
EntityBeanIntercept toEbi = existing._ebean_getIntercept();
|
||||
|
||||
int propertyLength = toEbi.getPropertyLength();
|
||||
String[] names = getProperties();
|
||||
|
||||
for (int i = 0; i < propertyLength; i++) {
|
||||
|
||||
if (fromEbi.isLoadedProperty(i) ) {
|
||||
BeanProperty property = getBeanProperty(names[i]);
|
||||
if (!toEbi.isLoadedProperty(i)) {
|
||||
Object val = property.getValue(bean);
|
||||
property.setValue(existing, val);
|
||||
} else if (property.isMany()) {
|
||||
property.merge(bean, existing);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum EntityType {
|
||||
ORM, EMBEDDED, SQL
|
||||
}
|
||||
|
||||
@@ -1329,4 +1329,7 @@ public class BeanProperty implements ElPropertyValue, Property {
|
||||
return DocPropertyType.STRING == type && (id || discriminator);
|
||||
}
|
||||
|
||||
public void merge(EntityBean bean, EntityBean existing) {
|
||||
// do nothing unless Many property
|
||||
}
|
||||
}
|
||||
|
||||
@@ -201,6 +201,27 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> {
|
||||
// by default not including "Many" properties in document store
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy collection value if existing is empty.
|
||||
*/
|
||||
@Override
|
||||
public void merge(EntityBean bean, EntityBean existing) {
|
||||
|
||||
Object existingCollection = getVal(existing);
|
||||
if (existingCollection instanceof BeanCollection<?>) {
|
||||
BeanCollection<?> toBC = (BeanCollection<?>)existingCollection;
|
||||
if (!toBC.isPopulated()) {
|
||||
Object fromCollection = getVal(bean);
|
||||
if (fromCollection instanceof BeanCollection<?>) {
|
||||
BeanCollection<?> fromBC = (BeanCollection<?>)fromCollection;
|
||||
if (fromBC.isPopulated()) {
|
||||
toBC.loadFrom(fromBC);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the bean to the appropriate collection on the parent bean.
|
||||
*/
|
||||
|
||||
@@ -70,13 +70,12 @@ public class DLoadBeanContext extends DLoadBaseContext implements LoadBeanContex
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public void loadSecondaryQuery(OrmQueryRequest<?> parentRequest) {
|
||||
public void loadSecondaryQuery(OrmQueryRequest<?> parentRequest, boolean forEach) {
|
||||
|
||||
if (!queryFetch) {
|
||||
throw new IllegalStateException("Not expecting loadSecondaryQuery() to be called?");
|
||||
}
|
||||
synchronized (this) {
|
||||
|
||||
if (bufferList != null) {
|
||||
for (LoadBuffer loadBuffer : bufferList) {
|
||||
if (!loadBuffer.list.isEmpty()) {
|
||||
@@ -87,8 +86,12 @@ public class DLoadBeanContext extends DLoadBaseContext implements LoadBeanContex
|
||||
break;
|
||||
}
|
||||
}
|
||||
// this is only run once - secondary query is a one shot deal
|
||||
this.bufferList = null;
|
||||
if (forEach) {
|
||||
clear();
|
||||
} else {
|
||||
// this is only run once - secondary query is a one shot deal
|
||||
this.bufferList = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,12 +182,12 @@ public class DLoadContext implements LoadContext {
|
||||
/**
|
||||
* Execute all the secondary queries.
|
||||
*/
|
||||
public void executeSecondaryQueries(OrmQueryRequest<?> parentRequest) {
|
||||
public void executeSecondaryQueries(OrmQueryRequest<?> parentRequest, boolean forEach) {
|
||||
|
||||
if (secQuery != null) {
|
||||
for (int i = 0; i < secQuery.size(); i++) {
|
||||
LoadSecondaryQuery load = getLoadSecondaryQuery(secQuery.get(i).getPath());
|
||||
load.loadSecondaryQuery(parentRequest);
|
||||
load.loadSecondaryQuery(parentRequest, forEach);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,8 @@ public class DLoadManyContext extends DLoadBaseContext implements LoadManyContex
|
||||
|
||||
protected final BeanPropertyAssocMany<?> property;
|
||||
|
||||
private final boolean docStoreMapped;
|
||||
|
||||
private List<LoadBuffer> bufferList;
|
||||
|
||||
private LoadBuffer currentBuffer;
|
||||
@@ -31,6 +33,7 @@ public class DLoadManyContext extends DLoadBaseContext implements LoadManyContex
|
||||
super(parent, property.getBeanDescriptor(), path, defaultBatchSize, queryProps);
|
||||
|
||||
this.property = property;
|
||||
this.docStoreMapped = property.getTargetDescriptor().isDocStoreMapped();
|
||||
// bufferList only required when using query joins (queryFetch)
|
||||
this.bufferList = (!queryFetch) ? null : new ArrayList<DLoadManyContext.LoadBuffer>();
|
||||
this.currentBuffer = createBuffer(firstBatchSize);
|
||||
@@ -56,7 +59,7 @@ public class DLoadManyContext extends DLoadBaseContext implements LoadManyContex
|
||||
|
||||
public void configureQuery(SpiQuery<?> query) {
|
||||
|
||||
parent.propagateQueryState(query, desc.isDocStoreMapped());
|
||||
parent.propagateQueryState(query, docStoreMapped);
|
||||
query.setParentNode(objectGraphNode);
|
||||
if (queryProps != null) {
|
||||
queryProps.configureBeanQuery(query);
|
||||
@@ -85,7 +88,7 @@ public class DLoadManyContext extends DLoadBaseContext implements LoadManyContex
|
||||
bc.setLoader(currentBuffer);
|
||||
}
|
||||
|
||||
public void loadSecondaryQuery(OrmQueryRequest<?> parentRequest) {
|
||||
public void loadSecondaryQuery(OrmQueryRequest<?> parentRequest, boolean forEach) {
|
||||
|
||||
if (!queryFetch) {
|
||||
throw new IllegalStateException("Not expecting loadSecondaryQuery() to be called?");
|
||||
@@ -103,8 +106,12 @@ public class DLoadManyContext extends DLoadBaseContext implements LoadManyContex
|
||||
}
|
||||
}
|
||||
|
||||
// this is only run once - secondary query is a one shot deal
|
||||
this.bufferList = null;
|
||||
if (forEach) {
|
||||
clear();
|
||||
} else {
|
||||
// this is only run once - secondary query is a one shot deal
|
||||
this.bufferList = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -131,7 +138,7 @@ public class DLoadManyContext extends DLoadBaseContext implements LoadManyContex
|
||||
|
||||
@Override
|
||||
public boolean isUseDocStore() {
|
||||
return context.parent.useDocStore;
|
||||
return context.parent.useDocStore && context.docStoreMapped;
|
||||
}
|
||||
|
||||
public int getBatchSize() {
|
||||
|
||||
@@ -316,7 +316,7 @@ public class CQueryEngine {
|
||||
cquery.auditFindMany();
|
||||
}
|
||||
|
||||
request.executeSecondaryQueries();
|
||||
request.executeSecondaryQueries(false);
|
||||
|
||||
return beanCollection;
|
||||
|
||||
@@ -365,7 +365,7 @@ public class CQueryEngine {
|
||||
cquery.auditFind(bean);
|
||||
}
|
||||
|
||||
request.executeSecondaryQueries();
|
||||
request.executeSecondaryQueries(false);
|
||||
|
||||
return (T) bean;
|
||||
|
||||
|
||||
@@ -42,8 +42,7 @@ class CQueryIteratorWithBuffer<T> implements QueryIterator<T> {
|
||||
moreToLoad = false;
|
||||
}
|
||||
}
|
||||
// execute secondary queries
|
||||
request.executeSecondaryQueries();
|
||||
request.executeSecondaryQueries(true);
|
||||
}
|
||||
return !buffer.isEmpty();
|
||||
|
||||
|
||||
@@ -462,10 +462,10 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
|
||||
@Override
|
||||
public SpiQuerySecondary convertJoins() {
|
||||
|
||||
createExtraJoinsToSupportManyWhereClause();
|
||||
if (!useDocStore) {
|
||||
createExtraJoinsToSupportManyWhereClause();
|
||||
}
|
||||
markQueryJoins();
|
||||
|
||||
return new OrmQuerySecondary(removeQueryJoins(), removeLazyJoins());
|
||||
}
|
||||
|
||||
@@ -845,7 +845,6 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
public CQueryPlanKey prepare(BeanQueryRequest<?> request) {
|
||||
|
||||
prepareExpressions(request);
|
||||
|
||||
queryPlanKey = createQueryPlanKey();
|
||||
return queryPlanKey;
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ public class DJsonBeanReader<T> implements JsonBeanReader<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonBeanReader<T> forJson(JsonParser moreJson) {
|
||||
return new DJsonBeanReader(desc, readJson.forJson(moreJson));
|
||||
public JsonBeanReader<T> forJson(JsonParser moreJson, boolean resetContext) {
|
||||
return new DJsonBeanReader(desc, readJson.forJson(moreJson, resetContext));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,21 +63,31 @@ public class ReadJson {
|
||||
/**
|
||||
* Construct when transferring load context, persistence context, object mapper etc to a new ReadJson instance.
|
||||
*/
|
||||
private ReadJson(JsonParser moreJson, ReadJson source) {
|
||||
private ReadJson(JsonParser moreJson, ReadJson source, boolean resetContext) {
|
||||
this.parser = moreJson;
|
||||
this.rootDesc = source.rootDesc;
|
||||
this.pathStack = source.pathStack;
|
||||
this.visitorMap = source.visitorMap;
|
||||
this.objectMapper = source.objectMapper;
|
||||
this.persistenceContext = source.persistenceContext;
|
||||
this.loadContext = source.loadContext;
|
||||
if (resetContext) {
|
||||
this.persistenceContext = new DefaultPersistenceContext();
|
||||
this.loadContext = source.loadContext;
|
||||
if (loadContext != null) {
|
||||
loadContext.resetPersistenceContext(persistenceContext);
|
||||
}
|
||||
} else {
|
||||
this.persistenceContext = source.persistenceContext;
|
||||
this.loadContext = source.loadContext;
|
||||
}
|
||||
}
|
||||
|
||||
private LoadContext initLoadContext(BeanDescriptor<?> desc, JsonReadOptions readOptions) {
|
||||
if (readOptions != null && readOptions.isEnableLazyLoading()) {
|
||||
if (readOptions == null) return null;
|
||||
if (readOptions.isEnableLazyLoading() && readOptions.getLoadContext() == null) {
|
||||
return new DLoadContext(desc, persistenceContext);
|
||||
} else {
|
||||
return (LoadContext) readOptions.getLoadContext();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private PersistenceContext initPersistenceContext(JsonReadOptions readOptions) {
|
||||
@@ -97,8 +107,8 @@ public class ReadJson {
|
||||
/**
|
||||
* Return a new instance of ReadJson using the existing context but with a new JsonParser.
|
||||
*/
|
||||
public ReadJson forJson(JsonParser moreJson) {
|
||||
return new ReadJson(moreJson, this);
|
||||
public ReadJson forJson(JsonParser moreJson, boolean resetContext) {
|
||||
return new ReadJson(moreJson, this, resetContext);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -120,8 +130,11 @@ public class ReadJson {
|
||||
return null;
|
||||
}
|
||||
|
||||
Object contextBean = beanDesc.contextPutIfAbsent(persistenceContext, id, bean);
|
||||
if (contextBean == null) {
|
||||
Object existing = beanDesc.contextPutIfAbsent(persistenceContext, id, bean);
|
||||
if (existing != null) {
|
||||
beanDesc.merge(bean, (EntityBean)existing);
|
||||
|
||||
} else {
|
||||
if (loadContext != null) {
|
||||
EntityBeanIntercept ebi = bean._ebean_getIntercept();
|
||||
if (ebi.isPartial()) {
|
||||
@@ -134,7 +147,7 @@ public class ReadJson {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return contextBean;
|
||||
return existing;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.avaje.ebeanservice.docstore.api;
|
||||
|
||||
import com.avaje.ebean.text.json.JsonReadOptions;
|
||||
import com.avaje.ebeaninternal.api.SpiQuery;
|
||||
|
||||
/**
|
||||
* A Query request for the document store.
|
||||
*/
|
||||
public interface DocQueryRequest<T> {
|
||||
|
||||
/**
|
||||
* Return the query for this request.
|
||||
*/
|
||||
SpiQuery<T> getQuery();
|
||||
|
||||
/**
|
||||
* Create JsonReadOptions taking into account persistence context and lazy loading support.
|
||||
*/
|
||||
JsonReadOptions createJsonReadOptions();
|
||||
|
||||
/**
|
||||
* Execute secondary queries.
|
||||
*/
|
||||
void executeSecondaryQueries(boolean forEach);
|
||||
|
||||
}
|
||||
@@ -6,7 +6,7 @@ import com.avaje.ebean.PagedList;
|
||||
import com.avaje.ebean.Query;
|
||||
import com.avaje.ebean.QueryEachConsumer;
|
||||
import com.avaje.ebean.QueryEachWhileConsumer;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import com.avaje.ebeanservice.docstore.api.DocQueryRequest;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
@@ -60,29 +60,28 @@ public class NoneDocStore implements DocumentStore {
|
||||
throw implementationNotInClassPath();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public <T> T find(Class<T> beanType, Object id) {
|
||||
public <T> T find(DocQueryRequest<T> request) {
|
||||
throw implementationNotInClassPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> PagedList<T> findPagedList(Query<T> query) {
|
||||
public <T> PagedList<T> findPagedList(DocQueryRequest<T> request) {
|
||||
throw implementationNotInClassPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> List<T> findList(Query<T> query) {
|
||||
public <T> List<T> findList(DocQueryRequest<T> request) {
|
||||
throw implementationNotInClassPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void findEach(Query<T> query, QueryEachConsumer<T> consumer) {
|
||||
public <T> void findEach(DocQueryRequest<T> query, QueryEachConsumer<T> consumer) {
|
||||
throw implementationNotInClassPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void findEachWhile(Query<T> query, QueryEachWhileConsumer<T> consumer) {
|
||||
public <T> void findEachWhile(DocQueryRequest<T> query, QueryEachWhileConsumer<T> consumer) {
|
||||
throw implementationNotInClassPath();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user