#360 ENH: Add query setDisableLazyLoading(true) ... for use when graph serialised via external library (and you don't want lazy loading to fire)

This commit is contained in:
Robin Bygrave
2015-07-29 20:31:25 +12:00
parent 59d009bc94
commit 3d4bd15dac
14 changed files with 239 additions and 39 deletions
+7
View File
@@ -1257,4 +1257,11 @@ public interface Query<T> extends Serializable {
*/
Class<T> getBeanType();
/**
* Set true if you want to disable lazy loading.
* <p>
* That is, once the object graph is returned further lazy loading is disabled.
* </p>
*/
Query<T> setDisableLazyLoading(boolean disableLazyLoading);
}
@@ -576,9 +576,14 @@ public interface SpiQuery<T> extends Query<T> {
*/
int getFirstRow();
/**
* Return true if lazy loading has been disabled on the query.
*/
boolean isDisableLazyLoading();
/**
* Internally set by Ebean when this query must use the DISTINCT keyword.
* <p/>
* <p>
* This does not exclude/remove the use of the id property.
*/
Query<T> setSqlDistinct(boolean sqlDistinct);
@@ -152,7 +152,7 @@ public class DRawSqlSelect {
}
}
SqlTreeNode sqlRoot = new SqlTreeNodeRoot(desc, selectProps, null, withId);
SqlTreeNode sqlRoot = new SqlTreeNodeRoot(desc, selectProps, withId, false);
return new SqlTree(desc.getName(), sqlRoot);
}
@@ -49,6 +49,8 @@ public class DLoadBeanContext extends DLoadBaseContext implements LoadBeanContex
if (parent.isReadOnly() != null) {
query.setReadOnly(parent.isReadOnly());
}
// propagate the asOf and lazy loading mode
query.setDisableLazyLoading(parent.isDisableLazyLoading());
query.asOf(parent.getAsOf());
query.setParentNode(objectGraphNode);
query.setLazyLoadProperty(lazyLoadProperty);
@@ -36,8 +36,9 @@ public class DLoadContext implements LoadContext {
private final Boolean readOnly;
private final boolean excludeBeanCache;
private final int defaultBatchSize;
/**
private final boolean disableLazyLoading;
/**
* The path relative to the root of the object graph.
*/
private final String relativePath;
@@ -59,7 +60,8 @@ public class DLoadContext implements LoadContext {
SpiQuery<?> query = request.getQuery();
this.asOf = query.getAsOf();
this.readOnly = query.isReadOnly();
this.readOnly = query.isReadOnly();
this.disableLazyLoading = query.isDisableLazyLoading();
this.excludeBeanCache = Boolean.FALSE.equals(query.isUseBeanCache());
this.useAutofetchManager = query.getAutoFetchManager() != null;
@@ -219,6 +221,10 @@ public class DLoadContext implements LoadContext {
return asOf;
}
protected boolean isDisableLazyLoading() {
return disableLazyLoading;
}
public PersistenceContext getPersistenceContext() {
return persistenceContext;
}
@@ -61,6 +61,8 @@ public class DLoadManyContext extends DLoadBaseContext implements LoadManyContex
query.setReadOnly(parent.isReadOnly());
}
// propagate the asOf and lazy loading mode
query.setDisableLazyLoading(parent.isDisableLazyLoading());
query.asOf(parent.getAsOf());
query.setParentNode(objectGraphNode);
@@ -71,6 +71,8 @@ public class SqlTreeBuilder {
*/
private final boolean rawNoId;
private final boolean disableLazyLoad;
private SqlTreeNode rootNode;
/**
@@ -81,6 +83,7 @@ public class SqlTreeBuilder {
this.rawSql = true;
this.desc = request.getBeanDescriptor();
this.rawNoId = rawNoId;
this.disableLazyLoad = request.getQuery().isDisableLazyLoading();
this.query = null;
this.subQuery = false;
this.queryDetail = queryDetail;
@@ -104,6 +107,7 @@ public class SqlTreeBuilder {
this.rawNoId = false;
this.desc = request.getBeanDescriptor();
this.query = request.getQuery();
this.disableLazyLoad = (query == null) ? false : query.isDisableLazyLoading();
this.subQuery = Type.SUBQUERY.equals(query.getType()) || Type.ID_LIST.equals(query.getType());
this.includeJoin = query.getIncludeTableJoin();
@@ -252,8 +256,7 @@ public class SqlTreeBuilder {
}
}
private SqlTreeNode buildNode(String prefix, BeanPropertyAssoc<?> prop, BeanDescriptor<?> desc,
List<SqlTreeNode> myList) {
private SqlTreeNode buildNode(String prefix, BeanPropertyAssoc<?> prop, BeanDescriptor<?> desc, List<SqlTreeNode> myList) {
OrmQueryProperties queryProps = queryDetail.getChunk(prefix, false);
@@ -265,14 +268,13 @@ public class SqlTreeBuilder {
// Optional many property for lazy loading query
BeanPropertyAssocMany<?> lazyLoadMany = (query == null) ? null : query.getLazyLoadForParentsProperty();
boolean withId = !rawNoId && !subQuery && (query == null || !query.isDistinct());
return new SqlTreeNodeRoot(desc, props, myList, withId, includeJoin, lazyLoadMany, SpiQuery.TemporalMode.of(query));
return new SqlTreeNodeRoot(desc, props, myList, withId, includeJoin, lazyLoadMany, SpiQuery.TemporalMode.of(query), disableLazyLoad);
} else if (prop instanceof BeanPropertyAssocMany<?>) {
return new SqlTreeNodeManyRoot(prefix, (BeanPropertyAssocMany<?>) prop, props, myList);
return new SqlTreeNodeManyRoot(prefix, (BeanPropertyAssocMany<?>) prop, props, myList, disableLazyLoad);
} else {
return new SqlTreeNodeBean(prefix, prop, props, myList, true);
return new SqlTreeNodeBean(prefix, prop, props, myList, true, disableLazyLoad);
}
}
@@ -87,49 +87,58 @@ public class SqlTreeNodeBean implements SqlTreeNode {
*/
protected String intersectionAsOfTableAlias;
public SqlTreeNodeBean(String prefix, BeanPropertyAssoc<?> beanProp, SqlTreeProperties props,
List<SqlTreeNode> myChildren, boolean withId) {
/**
* Construct for Raw SQL.
*/
public SqlTreeNodeBean(BeanDescriptor<?> desc, SqlTreeProperties props, boolean withId, boolean disableLazyLoad) {
this(null, null, desc, props, null, withId, null, null, disableLazyLoad);
}
this(prefix, beanProp, beanProp.getTargetDescriptor(), props, myChildren, withId, null, SpiQuery.TemporalMode.CURRENT);
/**
* Construct for leaf node.
*/
public SqlTreeNodeBean(String prefix, BeanPropertyAssoc<?> beanProp, SqlTreeProperties props,
List<SqlTreeNode> myChildren, boolean withId, boolean disableLazyLoad) {
this(prefix, beanProp, beanProp.getTargetDescriptor(), props, myChildren, withId, null, SpiQuery.TemporalMode.CURRENT, disableLazyLoad);
}
/**
* Construct for root node.
*/
public SqlTreeNodeBean(BeanDescriptor<?> desc, SqlTreeProperties props, List<SqlTreeNode> myList, boolean withId,
BeanPropertyAssocMany<?> many, SpiQuery.TemporalMode temporalMode, boolean disableLazyLoad) {
this(null, null, desc, props, myList, withId, many, temporalMode, disableLazyLoad);
}
/**
* Create with the appropriate node.
*/
public SqlTreeNodeBean(String prefix, BeanPropertyAssoc<?> beanProp, BeanDescriptor<?> desc,
SqlTreeProperties props, List<SqlTreeNode> myChildren, boolean withId, BeanPropertyAssocMany<?> lazyLoadParent, SpiQuery.TemporalMode temporalMode) {
private SqlTreeNodeBean(String prefix, BeanPropertyAssoc<?> beanProp, BeanDescriptor<?> desc, SqlTreeProperties props,
List<SqlTreeNode> myChildren, boolean withId, BeanPropertyAssocMany<?> lazyLoadParent,
SpiQuery.TemporalMode temporalMode, boolean disableLazyLoad) {
this.lazyLoadParent = lazyLoadParent;
this.lazyLoadParentIdBinder = (lazyLoadParent == null) ? null : lazyLoadParent.getBeanDescriptor().getIdBinder();
this.prefix = prefix;
this.nodeBeanProp = beanProp;
this.desc = desc;
this.inheritInfo = desc.getInheritInfo();
this.idBinder = desc.getIdBinder();
this.temporalMode = temporalMode;
this.temporalVersions = temporalMode == SpiQuery.TemporalMode.VERSIONS;
this.inheritInfo = desc.getInheritInfo();
this.nodeBeanProp = beanProp;
this.extraWhere = (beanProp == null) ? null : beanProp.getExtraWhere();
this.idBinder = desc.getIdBinder();
// the bean has an Id property and we want to use it
this.readId = withId && (desc.getIdProperty() != null);
this.disableLazyLoad = !readId || desc.isSqlSelectBased() || temporalVersions;
this.disableLazyLoad = disableLazyLoad || !readId || desc.isSqlSelectBased() || temporalVersions;
this.tableJoins = props.getTableJoins();
this.partialObject = props.isPartialObject();
this.readOnlyLeaf = props.isReadOnly();
this.properties = props.getProps();
if (myChildren == null) {
children = NO_CHILDREN;
} else {
children = myChildren.toArray(new SqlTreeNode[myChildren.size()]);
}
this.children = myChildren == null ? NO_CHILDREN : myChildren.toArray(new SqlTreeNode[myChildren.size()]);
pathMap = createPathMap(prefix, desc);
}
@@ -10,10 +10,10 @@ import com.avaje.ebeaninternal.server.deploy.DbSqlContext;
public final class SqlTreeNodeManyRoot extends SqlTreeNodeBean {
final BeanPropertyAssocMany<?> manyProp;
private final BeanPropertyAssocMany<?> manyProp;
public SqlTreeNodeManyRoot(String prefix, BeanPropertyAssocMany<?> prop, SqlTreeProperties props, List<SqlTreeNode> myList) {
super(prefix, prop, prop.getTargetDescriptor(), props, myList, true, null, null);
public SqlTreeNodeManyRoot(String prefix, BeanPropertyAssocMany<?> prop, SqlTreeProperties props, List<SqlTreeNode> myList, boolean disableLazyLoad) {
super(prefix, prop, props, myList, true, disableLazyLoad);
this.manyProp = prop;
}
@@ -19,13 +19,17 @@ public final class SqlTreeNodeRoot extends SqlTreeNodeBean {
* Specify for SqlSelect to include an Id property or not.
*/
public SqlTreeNodeRoot(BeanDescriptor<?> desc, SqlTreeProperties props, List<SqlTreeNode> myList, boolean withId,
TableJoin includeJoin, BeanPropertyAssocMany<?> many, SpiQuery.TemporalMode temporalMode) {
super(null, null, desc, props, myList, withId, many, temporalMode);
TableJoin includeJoin, BeanPropertyAssocMany<?> many, SpiQuery.TemporalMode temporalMode, boolean disableLazyLoad) {
super(desc, props, myList, withId, many, temporalMode, disableLazyLoad);
this.includeJoin = includeJoin;
}
public SqlTreeNodeRoot(BeanDescriptor<?> desc, SqlTreeProperties props, List<SqlTreeNode> myList, boolean withId) {
super(null, null, desc, props, myList, withId, null, null);
/**
* Construct for raw sql.
*/
public SqlTreeNodeRoot(BeanDescriptor<?> desc, SqlTreeProperties props, boolean withId, boolean disableLazyLoad) {
super(desc, props, withId, disableLazyLoad);
this.includeJoin = null;
}
@@ -83,6 +83,11 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
private int firstRow;
/**
* Set to true to disable lazy loading on the object graph returned.
*/
private boolean disableLazyLoading;
/**
* Lazy loading batch size (can override server wide default).
*/
@@ -710,6 +715,7 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
builder.add(firstRow).add(maxRows).add(orderBy).add(forUpdate);
builder.add(rawWhereClause).add(additionalWhere).add(additionalHaving);
builder.add(mapKey);
builder.add(disableLazyLoading);
builder.add(id != null);
builder.add(asOf != null);
builder.add(rawSql == null ? 0 : rawSql.queryHash());
@@ -1138,6 +1144,16 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
this.includeTableJoin = includeTableJoin;
}
@Override
public Query<T> setDisableLazyLoading(boolean disableLazyLoading) {
this.disableLazyLoading = disableLazyLoading;
return this;
}
public boolean isDisableLazyLoading() {
return disableLazyLoading;
}
public int getFirstRow() {
return firstRow;
}
@@ -341,6 +341,9 @@ public class OrmQueryProperties implements Serializable {
if (filterMany != null) {
filterMany.queryPlanHash(request, builder);
}
builder.add(lazyFetchBatch);
builder.add(queryFetchBatch);
builder.add(queryFetchAll);
}
public String getProperties() {