#1460 - ENH: Add FetchGroup ... as a mechanism to specify select() + fetch() separately from Query

This commit is contained in:
rob bygrave committed 2018-07-30 23:51:52 +12:00
1 parent 02fe956056
commit 471605619a
17 files changed
+569 -7

No files matched your search

@@ -6,6 +6,7 @@ import io.ebean.DtoQuery;
import io.ebean.Expression;
import io.ebean.ExpressionFactory;
import io.ebean.ExpressionList;
import io.ebean.FetchGroup;
import io.ebean.FetchPath;
import io.ebean.FutureIds;
import io.ebean.FutureList;
@@ -460,6 +461,11 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
return query.select(fetchProperties);
}
@Override
public Query<T> select(FetchGroup fetchGroup) {
return query.select(fetchGroup);
}
@Override
public Query<T> setDistinct(boolean distinct) {
return query.setDistinct(distinct);
@@ -5,6 +5,7 @@ import io.ebean.CountDistinctOrder;
import io.ebean.DtoQuery;
import io.ebean.Expression;
import io.ebean.ExpressionList;
import io.ebean.FetchGroup;
import io.ebean.FetchPath;
import io.ebean.FutureIds;
import io.ebean.FutureList;
@@ -759,6 +760,11 @@ class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, Expression
return exprList.select(properties);
}
@Override
public Query<T> select(FetchGroup fetchGroup) {
return exprList.select(fetchGroup);
}
@Override
public Query<T> setDistinct(boolean distinct) {
return exprList.setDistinct(distinct);
@@ -0,0 +1,26 @@
package io.ebeaninternal.server.query;
import io.ebeaninternal.server.querydefn.OrmQueryDetail;
import io.ebeaninternal.server.querydefn.SpiFetchGroup;
/**
* Default FetchGroup implementation.
*/
class DFetchGroup implements SpiFetchGroup {
private final OrmQueryDetail detail;
DFetchGroup(OrmQueryDetail detail) {
this.detail = detail;
}
@Override
public OrmQueryDetail detail() {
return detail.copy();
}
@Override
public OrmQueryDetail underlying() {
return detail;
}
}
@@ -0,0 +1,85 @@
package io.ebeaninternal.server.query;
import io.ebean.FetchConfig;
import io.ebean.FetchGroup;
import io.ebean.FetchGroupBuilder;
import io.ebeaninternal.server.querydefn.OrmQueryDetail;
import io.ebeaninternal.server.querydefn.SpiFetchGroup;
/**
* Default implementation of the FetchGroupBuilder.
*/
class DFetchGroupBuilder implements FetchGroupBuilder {
private static final FetchConfig FETCH_QUERY = new FetchConfig().query();
private static final FetchConfig FETCH_LAZY = new FetchConfig().lazy();
private OrmQueryDetail detail;
DFetchGroupBuilder(OrmQueryDetail detail) {
this.detail = detail;
}
@Override
public FetchGroupBuilder fetch(String path) {
detail.fetch(path, null, null);
return this;
}
@Override
public FetchGroupBuilder fetch(String path, FetchGroup nestedGroup) {
return fetchNested(path, nestedGroup, null);
}
@Override
public FetchGroupBuilder fetchQuery(String path, FetchGroup nestedGroup) {
return fetchNested(path, nestedGroup, FETCH_QUERY);
}
@Override
public FetchGroupBuilder fetchLazy(String path, FetchGroup nestedGroup) {
return fetchNested(path, nestedGroup, FETCH_LAZY);
}
private FetchGroupBuilder fetchNested(String path, FetchGroup nestedGroup, FetchConfig fetchConfig) {
OrmQueryDetail nestedDetail = ((SpiFetchGroup) nestedGroup).underlying();
detail.addNested(path, nestedDetail, fetchConfig);
return this;
}
@Override
public FetchGroupBuilder fetchQuery(String path) {
detail.fetch(path, null, FETCH_QUERY);
return this;
}
@Override
public FetchGroupBuilder fetchLazy(String path) {
detail.fetch(path, null, FETCH_LAZY);
return this;
}
@Override
public FetchGroupBuilder fetch(String path, String properties) {
detail.fetch(path, properties, null);
return this;
}
@Override
public FetchGroupBuilder fetchQuery(String path, String properties) {
detail.fetch(path, properties, FETCH_QUERY);
return this;
}
@Override
public FetchGroupBuilder fetchLazy(String path, String properties) {
detail.fetch(path, properties, FETCH_LAZY);
return this;
}
@Override
public FetchGroup build() {
return new DFetchGroup(detail);
}
}
@@ -0,0 +1,28 @@
package io.ebeaninternal.server.query;
import io.ebean.FetchGroup;
import io.ebean.FetchGroupBuilder;
import io.ebean.service.SpiFetchGroupService;
import io.ebeaninternal.server.querydefn.OrmQueryDetail;
/**
* Default implementation of SpiFetchGroupService.
*/
public final class DFetchGroupService implements SpiFetchGroupService {
@Override
public FetchGroup of(String select) {
return new DFetchGroup(detail(select));
}
@Override
public FetchGroupBuilder select(String select) {
return new DFetchGroupBuilder(detail(select));
}
private OrmQueryDetail detail(String select) {
OrmQueryDetail detail = new OrmQueryDetail();
detail.select(select);
return detail;
}
}
@@ -7,6 +7,7 @@ import io.ebean.Expression;
import io.ebean.ExpressionFactory;
import io.ebean.ExpressionList;
import io.ebean.FetchConfig;
import io.ebean.FetchGroup;
import io.ebean.FetchPath;
import io.ebean.FutureIds;
import io.ebean.FutureList;
@@ -1329,6 +1330,12 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
return this;
}
@Override
public DefaultOrmQuery<T> select(FetchGroup fetchGroup) {
this.detail = ((SpiFetchGroup)fetchGroup).detail();
return this;
}
@Override
public DefaultOrmQuery<T> fetch(String property) {
return fetch(property, null, null);
@@ -55,6 +55,16 @@ public class OrmQueryDetail implements Serializable {
return copy;
}
/**
* Add a nested OrmQueryDetail to this detail.
*/
public void addNested(String path, OrmQueryDetail other, FetchConfig config) {
fetch(path, other.baseProps.getProperties(), config);
for (Map.Entry<String, OrmQueryProperties> entry : other.fetchPaths.entrySet()) {
fetch(path + "." + entry.getKey(), entry.getValue().getProperties(), entry.getValue().getFetchConfig());
}
}
/**
* Calculate the hash for the query plan.
*/
@@ -148,27 +148,30 @@ public class OrmQueryProperties implements Serializable {
/**
* Copy constructor.
*/
private OrmQueryProperties(OrmQueryProperties source) {
private OrmQueryProperties(OrmQueryProperties source, FetchConfig sourceFetchConfig) {
this.fetchConfig = sourceFetchConfig;
this.parentPath = source.parentPath;
this.path = source.path;
this.rawProperties = source.rawProperties;
this.trimmedProperties = source.trimmedProperties;
this.cache = source.cache;
this.readOnly = source.readOnly;
this.fetchConfig = source.fetchConfig;
this.filterMany = source.filterMany;
this.included = (source.included == null) ? null : new LinkedHashSet<>(source.included);
if (includedBeanJoin != null) {
this.includedBeanJoin = new HashSet<>(source.includedBeanJoin);
}
}
/**
* Creates a copy of the OrmQueryProperties.
*/
public OrmQueryProperties copy() {
return new OrmQueryProperties(this);
return new OrmQueryProperties(this, this.fetchConfig);
}
/**
* Create a copy with the given fetch config.
*/
public OrmQueryProperties copy(FetchConfig fetchConfig) {
return new OrmQueryProperties(this, fetchConfig);
}
/**
@@ -0,0 +1,19 @@
package io.ebeaninternal.server.querydefn;
import io.ebean.FetchGroup;
/**
* Service API of FetchGroup.
*/
public interface SpiFetchGroup extends FetchGroup {
/**
* Return the detail to use for query execution.
*/
OrmQueryDetail detail();
/**
* Return the underlying detail for copy purposes.
*/
OrmQueryDetail underlying();
}