mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Compare commits
10
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5c447511c1 | ||
|
|
f91789886c | ||
|
|
7d14ede1b9 | ||
|
|
1ba8bc4557 | ||
|
|
a234bd1201 | ||
|
|
1c0c0893b6 | ||
|
|
ebbc560ae8 | ||
|
|
fcb9df05ad | ||
|
|
3de79b211a | ||
|
|
d93952a920 |
@@ -9,7 +9,7 @@
|
||||
|
||||
<groupId>org.avaje.ebeanorm</groupId>
|
||||
<artifactId>avaje-ebeanorm</artifactId>
|
||||
<version>3.3.2</version>
|
||||
<version>3.4.1</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>avaje-ebeanorm</name>
|
||||
@@ -167,6 +167,15 @@
|
||||
<!-- Enhance the meta beans -->
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.1</version>
|
||||
<configuration>
|
||||
<source>1.6</source>
|
||||
<target>1.6</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.avaje.ebeanorm</groupId>
|
||||
<artifactId>avaje-ebeanorm-mavenenhancer</artifactId>
|
||||
|
||||
@@ -244,14 +244,6 @@ public interface ExpressionList<T> extends Serializable {
|
||||
*/
|
||||
public Query<T> setMaxRows(int maxRows);
|
||||
|
||||
/**
|
||||
* Set the number of rows after which the fetching should continue in a
|
||||
* background thread.
|
||||
*
|
||||
* @see Query#setBackgroundFetchAfter(int)
|
||||
*/
|
||||
public Query<T> setBackgroundFetchAfter(int backgroundFetchAfter);
|
||||
|
||||
/**
|
||||
* Set the name of the property which values become the key of a map.
|
||||
*
|
||||
@@ -259,15 +251,6 @@ public interface ExpressionList<T> extends Serializable {
|
||||
*/
|
||||
public Query<T> setMapKey(String mapKey);
|
||||
|
||||
/**
|
||||
* Please migrate to using {@link #findIterate()} or {@link #findVisit(QueryResultVisitor)}.
|
||||
* Set a QueryListener for bean by bean processing.
|
||||
*
|
||||
* @see Query#setListener(QueryListener)
|
||||
* @deprecated Migrate to {@link #findIterate()} or {@link #findVisit(QueryResultVisitor)}
|
||||
*/
|
||||
public Query<T> setListener(QueryListener<T> queryListener);
|
||||
|
||||
/**
|
||||
* Set to true to use the query for executing this query.
|
||||
*
|
||||
|
||||
@@ -663,36 +663,6 @@ public interface Query<T> extends Serializable {
|
||||
*/
|
||||
public Query<T> setParameter(int position, Object value);
|
||||
|
||||
/**
|
||||
* Please migrate to using {@link #findIterate()} or {@link #findVisit(QueryResultVisitor)}
|
||||
* <p>
|
||||
* Set a listener to process the query on a row by row basis.
|
||||
* </p>
|
||||
* <p>
|
||||
* Use this when you want to process a large query and do not want to hold the
|
||||
* entire query result in memory.
|
||||
* </p>
|
||||
* <p>
|
||||
* It this case the rows are not loaded into the persistence context and
|
||||
* instead are processed by the query listener.
|
||||
* </p>
|
||||
*
|
||||
* <pre class="code">
|
||||
* QueryListener<Order> listener = ...;
|
||||
*
|
||||
* Query<Order> query = Ebean.createQuery(Order.class);
|
||||
*
|
||||
* // set the listener that will process each order one at a time
|
||||
* query.setListener(listener);
|
||||
*
|
||||
* // execute the query. Note that the returned
|
||||
* // list (emptyList) will be empty ...
|
||||
* List<Order> emtyList = query.findList();
|
||||
* </pre>
|
||||
* @deprecated Deprecated in favor of {@link #findIterate()} and {@link #findVisit(QueryResultVisitor)}
|
||||
*/
|
||||
public Query<T> setListener(QueryListener<T> queryListener);
|
||||
|
||||
/**
|
||||
* Set the Id value to query. This is used with findUnique().
|
||||
* <p>
|
||||
@@ -966,13 +936,6 @@ public interface Query<T> extends Serializable {
|
||||
*/
|
||||
public Query<T> setMaxRows(int maxRows);
|
||||
|
||||
/**
|
||||
* Set the rows after which fetching should continue in a background thread.
|
||||
*
|
||||
* @param backgroundFetchAfter
|
||||
*/
|
||||
public Query<T> setBackgroundFetchAfter(int backgroundFetchAfter);
|
||||
|
||||
/**
|
||||
* Set the property to use as keys for a map.
|
||||
* <p>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.avaje.ebean.bean;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Identifies a unique node of an object graph.
|
||||
@@ -70,7 +69,7 @@ public final class ObjectGraphNode implements Serializable {
|
||||
|
||||
public int hashCode() {
|
||||
int hc = 31 * originQueryPoint.hashCode();
|
||||
hc = 31 * hc + Objects.hashCode(path);
|
||||
hc = 31 * hc + (path == null ? 0 : path.hashCode());
|
||||
return hc;
|
||||
}
|
||||
|
||||
@@ -83,7 +82,7 @@ public final class ObjectGraphNode implements Serializable {
|
||||
}
|
||||
|
||||
ObjectGraphNode e = (ObjectGraphNode) obj;
|
||||
return Objects.equals(e.path, path)
|
||||
return ((e.path == path) || (e.path != null && e.path.equals(path)))
|
||||
&& e.originQueryPoint.equals(originQueryPoint);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package com.avaje.ebeaninternal.api;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* A hash for a query plan.
|
||||
*/
|
||||
@@ -26,7 +24,7 @@ public class HashQueryPlan {
|
||||
public int hashCode() {
|
||||
int hc = planHash;
|
||||
hc = hc * 31 + bindCount;
|
||||
hc = hc * 31 + Objects.hashCode(rawSql);
|
||||
hc = hc * 31 + (rawSql == null ? 0 : rawSql.hashCode());
|
||||
return hc;
|
||||
}
|
||||
|
||||
@@ -41,6 +39,6 @@ public class HashQueryPlan {
|
||||
HashQueryPlan e = (HashQueryPlan) obj;
|
||||
return e.planHash == planHash
|
||||
&& e.bindCount == bindCount
|
||||
&& Objects.equals(e.rawSql, rawSql);
|
||||
&& ((e.rawSql == rawSql) || (e.rawSql != null && e.rawSql.equals(rawSql)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package com.avaje.ebeaninternal.api;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Used to build HashQueryPlan instances.
|
||||
*/
|
||||
@@ -33,7 +31,7 @@ public class HashQueryPlanBuilder {
|
||||
* Add an object to the hash calculation.
|
||||
*/
|
||||
public HashQueryPlanBuilder add(Object object) {
|
||||
planHash = planHash * 31 + Objects.hashCode(object);
|
||||
planHash = planHash * 31 + (object == null ? 0 : object.hashCode());
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ import java.util.List;
|
||||
import com.avaje.ebean.ExpressionList;
|
||||
import com.avaje.ebean.OrderBy;
|
||||
import com.avaje.ebean.Query;
|
||||
import com.avaje.ebean.QueryListener;
|
||||
import com.avaje.ebean.bean.BeanCollectionTouched;
|
||||
import com.avaje.ebean.bean.CallStack;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
@@ -509,12 +508,6 @@ public interface SpiQuery<T> extends Query<T> {
|
||||
*/
|
||||
public String getMapKey();
|
||||
|
||||
/**
|
||||
* Return the number of rows after which fetching should occur in a
|
||||
* background thread.
|
||||
*/
|
||||
public int getBackgroundFetchAfter();
|
||||
|
||||
/**
|
||||
* Return the maximum number of rows to return in the query.
|
||||
*/
|
||||
@@ -545,19 +538,6 @@ public interface SpiQuery<T> extends Query<T> {
|
||||
*/
|
||||
public Object getId();
|
||||
|
||||
/**
|
||||
* Return the queryListener.
|
||||
*/
|
||||
public QueryListener<T> getListener();
|
||||
|
||||
/**
|
||||
* Return true if this query should use its own transaction.
|
||||
* <p>
|
||||
* This is true for background fetching and when using QueryListener.
|
||||
* </p>
|
||||
*/
|
||||
public boolean createOwnTransaction();
|
||||
|
||||
/**
|
||||
* Set the generated sql for debug purposes.
|
||||
*
|
||||
|
||||
@@ -90,7 +90,6 @@ import com.avaje.ebeaninternal.server.deploy.InheritInfo;
|
||||
import com.avaje.ebeaninternal.server.el.ElFilter;
|
||||
import com.avaje.ebeaninternal.server.jmx.MAdminAutofetch;
|
||||
import com.avaje.ebeaninternal.server.lib.ShutdownManager;
|
||||
import com.avaje.ebeaninternal.server.loadcontext.DLoadContext;
|
||||
import com.avaje.ebeaninternal.server.query.CQuery;
|
||||
import com.avaje.ebeaninternal.server.query.CQueryEngine;
|
||||
import com.avaje.ebeaninternal.server.query.CallableQueryIds;
|
||||
@@ -1133,7 +1132,7 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
if (Mode.LAZYLOAD_MANY.equals(query.getMode())) {
|
||||
allowOneManyFetch = false;
|
||||
|
||||
} else if (query.hasMaxRowsOrFirstRow() && !query.isRawSql() && !query.isSqlSelect() && query.getBackgroundFetchAfter() == 0) {
|
||||
} else if (query.hasMaxRowsOrFirstRow() && !query.isRawSql() && !query.isSqlSelect()) {
|
||||
// convert ALL fetch joins to Many's to be query joins
|
||||
// so that limit offset type SQL clauses work
|
||||
allowOneManyFetch = false;
|
||||
@@ -1194,16 +1193,15 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
if (cachedBean != null) {
|
||||
if (context == null) {
|
||||
context = new DefaultPersistenceContext();
|
||||
|
||||
}
|
||||
context.put(query.getId(), cachedBean);
|
||||
|
||||
DLoadContext loadContext = new DLoadContext(this, beanDescriptor, query.isReadOnly(), query);
|
||||
loadContext.setPersistenceContext(context);
|
||||
|
||||
EntityBeanIntercept ebi = ((EntityBean) cachedBean)._ebean_getIntercept();
|
||||
|
||||
// Not using a loadContext for beans coming out of L2 cache
|
||||
// so that means no batch lazy loading for these beans
|
||||
EntityBean entityBean = (EntityBean) cachedBean;
|
||||
EntityBeanIntercept ebi = entityBean._ebean_getIntercept();
|
||||
ebi.setPersistenceContext(context);
|
||||
loadContext.register(null, ebi);
|
||||
Object id = beanDescriptor.getId(entityBean);
|
||||
context.put(id, entityBean);
|
||||
}
|
||||
|
||||
return (T) cachedBean;
|
||||
|
||||
@@ -29,6 +29,7 @@ import com.avaje.ebeaninternal.server.deploy.DeployPropertyParserMap;
|
||||
import com.avaje.ebeaninternal.server.loadcontext.DLoadContext;
|
||||
import com.avaje.ebeaninternal.server.query.CQueryPlan;
|
||||
import com.avaje.ebeaninternal.server.query.CancelableQuery;
|
||||
import com.avaje.ebeaninternal.server.transaction.DefaultPersistenceContext;
|
||||
|
||||
/**
|
||||
* Wraps the objects involved in executing a Query.
|
||||
@@ -43,7 +44,7 @@ public final class OrmQueryRequest<T> extends BeanRequest implements BeanQueryRe
|
||||
|
||||
private final BeanFinder<T> finder;
|
||||
|
||||
private final LoadContext graphContext;
|
||||
private LoadContext graphContext;
|
||||
|
||||
private final Boolean readOnly;
|
||||
|
||||
@@ -75,9 +76,6 @@ public final class OrmQueryRequest<T> extends BeanRequest implements BeanQueryRe
|
||||
this.queryEngine = queryEngine;
|
||||
this.query = query;
|
||||
this.readOnly = query.isReadOnly();
|
||||
|
||||
this.graphContext = new DLoadContext(ebeanServer, beanDescriptor, readOnly, query);
|
||||
graphContext.registerSecondaryQueries(query);
|
||||
}
|
||||
|
||||
public void executeSecondaryQueries(int defaultQueryBatch) {
|
||||
@@ -163,12 +161,7 @@ public final class OrmQueryRequest<T> extends BeanRequest implements BeanQueryRe
|
||||
@Override
|
||||
public void initTransIfRequired() {
|
||||
// first check if the query requires its own transaction
|
||||
if (query.createOwnTransaction()) {
|
||||
// using background fetch or query listener etc
|
||||
transaction = ebeanServer.createQueryTransaction();
|
||||
createdTransaction = true;
|
||||
|
||||
} else if (transaction == null) {
|
||||
if (transaction == null) {
|
||||
// maybe a current one
|
||||
transaction = ebeanServer.getCurrentServerTransaction();
|
||||
if (transaction == null) {
|
||||
@@ -177,8 +170,11 @@ public final class OrmQueryRequest<T> extends BeanRequest implements BeanQueryRe
|
||||
createdTransaction = true;
|
||||
}
|
||||
}
|
||||
|
||||
this.persistenceContext = getPersistenceContext(query, transaction);
|
||||
this.graphContext.setPersistenceContext(persistenceContext);
|
||||
|
||||
this.graphContext = new DLoadContext(this);
|
||||
this.graphContext.registerSecondaryQueries(query);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -381,7 +377,8 @@ public final class OrmQueryRequest<T> extends BeanRequest implements BeanQueryRe
|
||||
}
|
||||
|
||||
public void flushPersistenceContextOnIterate() {
|
||||
beanDescriptor.flushPersistenceContextOnIterate(persistenceContext);
|
||||
persistenceContext = new DefaultPersistenceContext();
|
||||
graphContext.setPersistenceContext(persistenceContext);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2444,13 +2444,5 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void flushPersistenceContextOnIterate(PersistenceContext persistenceContext) {
|
||||
persistenceContext.clear(beanType);
|
||||
for (int i = 0; i < propertiesMany.length; i++) {
|
||||
persistenceContext.clear(propertiesMany[i].getBeanDescriptor().getBeanType());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package com.avaje.ebeaninternal.server.expression;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import com.avaje.ebean.event.BeanQueryRequest;
|
||||
@@ -115,7 +114,7 @@ class AllEqualsExpression implements SpiExpression {
|
||||
|
||||
int hc = 31;
|
||||
for (Object value : propMap.values()) {
|
||||
hc = hc * 31 + Objects.hashCode(value);
|
||||
hc = hc * 31 + (value == null ? 0 : value.hashCode());
|
||||
}
|
||||
|
||||
return hc;
|
||||
|
||||
@@ -14,7 +14,6 @@ import com.avaje.ebean.Junction;
|
||||
import com.avaje.ebean.OrderBy;
|
||||
import com.avaje.ebean.PagingList;
|
||||
import com.avaje.ebean.QueryIterator;
|
||||
import com.avaje.ebean.QueryListener;
|
||||
import com.avaje.ebean.QueryResultVisitor;
|
||||
import com.avaje.ebean.event.BeanQueryRequest;
|
||||
import com.avaje.ebeaninternal.api.HashQueryPlanBuilder;
|
||||
@@ -375,19 +374,10 @@ abstract class JunctionExpression<T> implements Junction<T>, SpiExpression, Expr
|
||||
return exprList.select(properties);
|
||||
}
|
||||
|
||||
public com.avaje.ebean.Query<T> setBackgroundFetchAfter(int backgroundFetchAfter) {
|
||||
return exprList.setBackgroundFetchAfter(backgroundFetchAfter);
|
||||
}
|
||||
|
||||
public com.avaje.ebean.Query<T> setFirstRow(int firstRow) {
|
||||
return exprList.setFirstRow(firstRow);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public com.avaje.ebean.Query<T> setListener(QueryListener<T> queryListener) {
|
||||
return exprList.setListener(queryListener);
|
||||
}
|
||||
|
||||
public com.avaje.ebean.Query<T> setMapKey(String mapKey) {
|
||||
return exprList.setMapKey(mapKey);
|
||||
}
|
||||
|
||||
@@ -28,8 +28,9 @@ public class DLoadBeanContext extends DLoadBaseContext implements LoadBeanContex
|
||||
|
||||
super(parent, desc, path, defaultBatchSize, queryProps);
|
||||
|
||||
this.currentBuffer = createBuffer(firstBatchSize);
|
||||
this.bufferList = queryFetch ? new ArrayList<DLoadBeanContext.LoadBuffer>() : null;
|
||||
// bufferList only required when using query joins (queryFetch)
|
||||
this.bufferList = (!queryFetch) ? null : new ArrayList<DLoadBeanContext.LoadBuffer>();
|
||||
this.currentBuffer = createBuffer(firstBatchSize);
|
||||
}
|
||||
|
||||
protected void configureQuery(SpiQuery<?> query, String lazyLoadProperty) {
|
||||
@@ -51,11 +52,11 @@ public class DLoadBeanContext extends DLoadBaseContext implements LoadBeanContex
|
||||
|
||||
protected void register(EntityBeanIntercept ebi){
|
||||
|
||||
ebi.setBeanLoader(0, currentBuffer, getPersistenceContext());
|
||||
if (currentBuffer.add(ebi)) {
|
||||
// the currentBuffer is full so create another one
|
||||
if (currentBuffer.isFull()) {
|
||||
currentBuffer = createBuffer(secondaryBatchSize);
|
||||
}
|
||||
currentBuffer.add(ebi);
|
||||
ebi.setBeanLoader(0, currentBuffer, getPersistenceContext());
|
||||
}
|
||||
|
||||
private LoadBuffer createBuffer(int size) {
|
||||
@@ -98,22 +99,29 @@ public class DLoadBeanContext extends DLoadBaseContext implements LoadBeanContex
|
||||
*/
|
||||
public static class LoadBuffer implements BeanLoader, LoadBeanBuffer {
|
||||
|
||||
private final PersistenceContext persistenceContext;
|
||||
private final DLoadBeanContext context;
|
||||
private final int batchSize;
|
||||
private final List<EntityBeanIntercept> list;
|
||||
|
||||
public LoadBuffer(DLoadBeanContext context, int batchSize) {
|
||||
this.context = context;
|
||||
// set the persistence context as at this moment in
|
||||
// case it changes as part of a findIterate etc
|
||||
this.persistenceContext = context.getPersistenceContext();
|
||||
this.batchSize = batchSize;
|
||||
this.list = new ArrayList<EntityBeanIntercept>(batchSize);
|
||||
}
|
||||
|
||||
public boolean isFull() {
|
||||
return batchSize == list.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the buffer is full.
|
||||
*/
|
||||
public boolean add(EntityBeanIntercept ebi) {
|
||||
public void add(EntityBeanIntercept ebi) {
|
||||
list.add(ebi);
|
||||
return batchSize == list.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -138,7 +146,7 @@ public class DLoadBeanContext extends DLoadBaseContext implements LoadBeanContex
|
||||
|
||||
@Override
|
||||
public PersistenceContext getPersistenceContext() {
|
||||
return context.getPersistenceContext();
|
||||
return persistenceContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -52,12 +52,14 @@ public class DLoadContext implements LoadContext {
|
||||
private List<OrmQueryProperties> secQuery;
|
||||
|
||||
|
||||
public DLoadContext(SpiEbeanServer ebeanServer, BeanDescriptor<?> rootDescriptor, Boolean readOnly, SpiQuery<?> query) {
|
||||
public DLoadContext(OrmQueryRequest<?> request) {
|
||||
|
||||
this.ebeanServer = ebeanServer;
|
||||
this.persistenceContext = request.getPersistenceContext();
|
||||
this.ebeanServer = request.getServer();
|
||||
this.defaultBatchSize = ebeanServer.getLazyLoadBatchSize();
|
||||
this.rootDescriptor = rootDescriptor;
|
||||
this.readOnly = readOnly;
|
||||
this.rootDescriptor = request.getBeanDescriptor();
|
||||
SpiQuery<?> query = request.getQuery();
|
||||
this.readOnly = query.isReadOnly();
|
||||
this.excludeBeanCache = Boolean.FALSE.equals(query.isUseBeanCache());
|
||||
this.useAutofetchManager = query.getAutoFetchManager() != null;
|
||||
|
||||
|
||||
@@ -17,70 +17,71 @@ import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocMany;
|
||||
import com.avaje.ebeaninternal.server.querydefn.OrmQueryProperties;
|
||||
|
||||
public class DLoadManyContext extends DLoadBaseContext implements LoadManyContext {
|
||||
|
||||
|
||||
protected final BeanPropertyAssocMany<?> property;
|
||||
|
||||
|
||||
private List<LoadBuffer> bufferList;
|
||||
|
||||
|
||||
private LoadBuffer currentBuffer;
|
||||
|
||||
public DLoadManyContext(DLoadContext parent, BeanPropertyAssocMany<?> property,
|
||||
String path, int defaultBatchSize, OrmQueryProperties queryProps) {
|
||||
|
||||
super(parent, property.getBeanDescriptor(), path, defaultBatchSize, queryProps);
|
||||
public DLoadManyContext(DLoadContext parent, BeanPropertyAssocMany<?> property, String path, int defaultBatchSize,
|
||||
OrmQueryProperties queryProps) {
|
||||
|
||||
this.property = property;
|
||||
this.bufferList = new ArrayList<DLoadManyContext.LoadBuffer>();
|
||||
super(parent, property.getBeanDescriptor(), path, defaultBatchSize, queryProps);
|
||||
|
||||
this.property = property;
|
||||
// bufferList only required when using query joins (queryFetch)
|
||||
this.bufferList = (!queryFetch) ? null : new ArrayList<DLoadManyContext.LoadBuffer>();
|
||||
this.currentBuffer = createBuffer(firstBatchSize);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private LoadBuffer createBuffer(int size) {
|
||||
LoadBuffer buffer = new LoadBuffer(this, size);
|
||||
bufferList.add(buffer);
|
||||
if (bufferList != null) {
|
||||
bufferList.add(buffer);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public void configureQuery(SpiQuery<?> query){
|
||||
|
||||
// propagate the readOnly state
|
||||
if (parent.isReadOnly() != null){
|
||||
query.setReadOnly(parent.isReadOnly());
|
||||
}
|
||||
query.setParentNode(objectGraphNode);
|
||||
|
||||
if (queryProps != null){
|
||||
queryProps.configureBeanQuery(query);
|
||||
}
|
||||
|
||||
if (parent.isUseAutofetchManager()){
|
||||
query.setAutofetch(true);
|
||||
}
|
||||
}
|
||||
|
||||
public BeanPropertyAssocMany<?> getBeanProperty() {
|
||||
return property;
|
||||
}
|
||||
public void configureQuery(SpiQuery<?> query) {
|
||||
|
||||
public BeanDescriptor<?> getBeanDescriptor() {
|
||||
return desc;
|
||||
}
|
||||
// propagate the readOnly state
|
||||
if (parent.isReadOnly() != null) {
|
||||
query.setReadOnly(parent.isReadOnly());
|
||||
}
|
||||
query.setParentNode(objectGraphNode);
|
||||
|
||||
|
||||
public String getName() {
|
||||
return parent.getEbeanServer().getName();
|
||||
}
|
||||
if (queryProps != null) {
|
||||
queryProps.configureBeanQuery(query);
|
||||
}
|
||||
|
||||
public void register(BeanCollection<?> bc){
|
||||
|
||||
bc.setLoader(0, currentBuffer);
|
||||
if (currentBuffer.add(bc)) {
|
||||
// the currentBuffer is full so create another one
|
||||
if (parent.isUseAutofetchManager()) {
|
||||
query.setAutofetch(true);
|
||||
}
|
||||
}
|
||||
|
||||
public BeanPropertyAssocMany<?> getBeanProperty() {
|
||||
return property;
|
||||
}
|
||||
|
||||
public BeanDescriptor<?> getBeanDescriptor() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return parent.getEbeanServer().getName();
|
||||
}
|
||||
|
||||
public void register(BeanCollection<?> bc) {
|
||||
|
||||
if (currentBuffer.isFull()) {
|
||||
currentBuffer = createBuffer(secondaryBatchSize);
|
||||
}
|
||||
}
|
||||
currentBuffer.add(bc);
|
||||
bc.setLoader(0, currentBuffer);
|
||||
}
|
||||
|
||||
|
||||
public void loadSecondaryQuery(OrmQueryRequest<?> parentRequest, int requestedBatchSize, boolean all){
|
||||
public void loadSecondaryQuery(OrmQueryRequest<?> parentRequest, int requestedBatchSize, boolean all) {
|
||||
|
||||
if (!queryFetch) {
|
||||
throw new IllegalStateException("Not expecting loadSecondaryQuery() to be called?");
|
||||
@@ -89,33 +90,38 @@ public class DLoadManyContext extends DLoadBaseContext implements LoadManyContex
|
||||
if (bufferList != null) {
|
||||
for (LoadBuffer loadBuffer : bufferList) {
|
||||
if (!loadBuffer.list.isEmpty()) {
|
||||
LoadManyRequest req = new LoadManyRequest(loadBuffer, parentRequest.getTransaction(), requestedBatchSize, false, false, false);
|
||||
parent.getEbeanServer().loadMany(req);
|
||||
LoadManyRequest req = new LoadManyRequest(loadBuffer, parentRequest.getTransaction(), requestedBatchSize,
|
||||
false, false, false);
|
||||
parent.getEbeanServer().loadMany(req);
|
||||
if (!queryProps.isQueryFetchAll()) {
|
||||
// Stop - only fetch the first batch ... the rest will be lazy loaded
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// this is only run once - secondary query is a one shot deal
|
||||
this.bufferList = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A buffer for batch loading bean collections on a given path.
|
||||
* Supports batch lazy loading and secondary query loading.
|
||||
* A buffer for batch loading bean collections on a given path. Supports batch lazy loading and
|
||||
* secondary query loading.
|
||||
*/
|
||||
public static class LoadBuffer implements BeanCollectionLoader, LoadManyBuffer {
|
||||
|
||||
|
||||
private final PersistenceContext persistenceContext;
|
||||
private final DLoadManyContext context;
|
||||
private final int batchSize;
|
||||
private final List<BeanCollection<?>> list;
|
||||
|
||||
|
||||
public LoadBuffer(DLoadManyContext context, int batchSize) {
|
||||
this.context = context;
|
||||
// set the persistence context as at this moment in
|
||||
// case it changes as part of a findIterate etc
|
||||
this.persistenceContext = context.getPersistenceContext();
|
||||
this.batchSize = batchSize;
|
||||
this.list = new ArrayList<BeanCollection<?>>(batchSize);
|
||||
}
|
||||
@@ -123,11 +129,17 @@ public class DLoadManyContext extends DLoadBaseContext implements LoadManyContex
|
||||
/**
|
||||
* Return true if the buffer is full.
|
||||
*/
|
||||
public boolean add(BeanCollection<?> bc) {
|
||||
list.add(bc);
|
||||
public boolean isFull() {
|
||||
return batchSize == list.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the buffer is full.
|
||||
*/
|
||||
public void add(BeanCollection<?> bc) {
|
||||
list.add(bc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BeanCollection<?>> getBatch() {
|
||||
return list;
|
||||
@@ -137,22 +149,22 @@ public class DLoadManyContext extends DLoadBaseContext implements LoadManyContex
|
||||
public BeanPropertyAssocMany<?> getBeanProperty() {
|
||||
return context.property;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ObjectGraphNode getObjectGraphNode() {
|
||||
return context.objectGraphNode;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void configureQuery(SpiQuery<?> query){
|
||||
public void configureQuery(SpiQuery<?> query) {
|
||||
context.configureQuery(query);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return context.serverName;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public BeanDescriptor<?> getBeanDescriptor() {
|
||||
return context.desc;
|
||||
@@ -160,9 +172,9 @@ public class DLoadManyContext extends DLoadBaseContext implements LoadManyContex
|
||||
|
||||
@Override
|
||||
public PersistenceContext getPersistenceContext() {
|
||||
return context.getPersistenceContext();
|
||||
return persistenceContext;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getFullPath() {
|
||||
return context.fullPath;
|
||||
@@ -182,9 +194,10 @@ public class DLoadManyContext extends DLoadBaseContext implements LoadManyContex
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Should reduce the list by checking each beanCollection in the L2 first before executing the query
|
||||
|
||||
|
||||
// Should reduce the list by checking each beanCollection in the L2 first before executing
|
||||
// the query
|
||||
|
||||
LoadManyRequest req = new LoadManyRequest(this, null, batchSize, true, onlyIds, useCache);
|
||||
context.parent.getEbeanServer().loadMany(req);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.avaje.ebean.QueryIterator;
|
||||
import com.avaje.ebean.QueryListener;
|
||||
import com.avaje.ebean.bean.BeanCollection;
|
||||
import com.avaje.ebean.bean.BeanCollectionAdd;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
@@ -24,7 +23,6 @@ import com.avaje.ebean.bean.NodeUsageListener;
|
||||
import com.avaje.ebean.bean.ObjectGraphNode;
|
||||
import com.avaje.ebean.bean.PersistenceContext;
|
||||
import com.avaje.ebeaninternal.api.LoadContext;
|
||||
import com.avaje.ebeaninternal.api.SpiEbeanServer;
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionList;
|
||||
import com.avaje.ebeaninternal.api.SpiQuery;
|
||||
import com.avaje.ebeaninternal.api.SpiQuery.Mode;
|
||||
@@ -41,7 +39,6 @@ import com.avaje.ebeaninternal.server.deploy.DbReadContext;
|
||||
import com.avaje.ebeaninternal.server.el.ElPropertyValue;
|
||||
import com.avaje.ebeaninternal.server.lib.util.StringHelper;
|
||||
import com.avaje.ebeaninternal.server.querydefn.OrmQueryProperties;
|
||||
import com.avaje.ebeaninternal.server.transaction.DefaultPersistenceContext;
|
||||
import com.avaje.ebeaninternal.server.type.DataBind;
|
||||
import com.avaje.ebeaninternal.server.type.DataReader;
|
||||
|
||||
@@ -135,8 +132,6 @@ public class CQuery<T> implements DbReadContext, CancelableQuery {
|
||||
|
||||
private final SpiQuery<T> query;
|
||||
|
||||
private final QueryListener<T> queryListener;
|
||||
|
||||
private Map<String, String> currentPathMap;
|
||||
|
||||
private String currentPrefix;
|
||||
@@ -189,8 +184,6 @@ public class CQuery<T> implements DbReadContext, CancelableQuery {
|
||||
*/
|
||||
private final ElPropertyValue manyPropertyEl;
|
||||
|
||||
private final int backgroundFetchAfter;
|
||||
|
||||
private final int maxRowsLimit;
|
||||
|
||||
/**
|
||||
@@ -198,8 +191,6 @@ public class CQuery<T> implements DbReadContext, CancelableQuery {
|
||||
*/
|
||||
private boolean hasHitBackgroundFetchAfter;
|
||||
|
||||
private final PersistenceContext persistenceContext;
|
||||
|
||||
private DataReader dataReader;
|
||||
|
||||
/**
|
||||
@@ -276,20 +267,7 @@ public class CQuery<T> implements DbReadContext, CancelableQuery {
|
||||
this.desc = request.getBeanDescriptor();
|
||||
this.predicates = predicates;
|
||||
|
||||
this.queryListener = query.getListener();
|
||||
if (queryListener == null) {
|
||||
// normal, use the one from the transaction
|
||||
this.persistenceContext = request.getPersistenceContext();
|
||||
} else {
|
||||
// 'Row Level Transaction Context'...
|
||||
// local transaction context that will be reset
|
||||
// after each 'master' bean is sent to the listener
|
||||
this.persistenceContext = new DefaultPersistenceContext();
|
||||
}
|
||||
|
||||
this.maxRowsLimit = query.getMaxRows() > 0 ? query.getMaxRows() : GLOBAL_ROW_LIMIT;
|
||||
this.backgroundFetchAfter = query.getBackgroundFetchAfter() > 0 ? query
|
||||
.getBackgroundFetchAfter() : Integer.MAX_VALUE;
|
||||
|
||||
this.help = createHelp(request);
|
||||
this.collection = (BeanCollection<T>) (help != null ? help.createEmpty(false) : null);
|
||||
@@ -386,6 +364,7 @@ public class CQuery<T> implements DbReadContext, CancelableQuery {
|
||||
if (forwardOnlyHint) {
|
||||
// Use forward only hints for large resultset processing (Issue 56, MySql specific)
|
||||
pstmt = conn.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
|
||||
pstmt.setFetchSize(Integer.MIN_VALUE);
|
||||
} else {
|
||||
pstmt = conn.prepareStatement(sql);
|
||||
}
|
||||
@@ -442,7 +421,7 @@ public class CQuery<T> implements DbReadContext, CancelableQuery {
|
||||
* Return the persistence context.
|
||||
*/
|
||||
public PersistenceContext getPersistenceContext() {
|
||||
return persistenceContext;
|
||||
return request.getPersistenceContext();
|
||||
}
|
||||
|
||||
public void setLoadedBean(Object bean, Object id, Object lazyLoadParentId) {
|
||||
@@ -465,7 +444,7 @@ public class CQuery<T> implements DbReadContext, CancelableQuery {
|
||||
if (lazyLoadParentId != null) {
|
||||
if (!lazyLoadParentId.equals(this.lazyLoadParentId)) {
|
||||
// get the appropriate parent bean from the persistence context
|
||||
this.lazyLoadParentBean = persistenceContext.get(lazyLoadManyProperty.getBeanDescriptor().getBeanType(), lazyLoadParentId);
|
||||
this.lazyLoadParentBean = getPersistenceContext().get(lazyLoadManyProperty.getBeanDescriptor().getBeanType(), lazyLoadParentId);
|
||||
this.lazyLoadParentId = lazyLoadParentId;
|
||||
}
|
||||
|
||||
@@ -563,12 +542,6 @@ public class CQuery<T> implements DbReadContext, CancelableQuery {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (inForeground && loadedBeanCount >= backgroundFetchAfter) {
|
||||
hasHitBackgroundFetchAfter = true;
|
||||
collection.setFinishedFetch(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!manyIncluded) {
|
||||
// simple query... no details...
|
||||
return readRow();
|
||||
@@ -686,13 +659,8 @@ public class CQuery<T> implements DbReadContext, CancelableQuery {
|
||||
|
||||
private void readTheRows(boolean inForeground) throws SQLException {
|
||||
while (hasNextBean(inForeground)) {
|
||||
if (queryListener != null) {
|
||||
queryListener.process(getLoadedBean());
|
||||
|
||||
} else {
|
||||
// add to the list/set/map
|
||||
help.add(collection, getLoadedBean());
|
||||
}
|
||||
// add to the list/set/map
|
||||
help.add(collection, getLoadedBean());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -73,7 +73,6 @@ public class CQueryFetchIds {
|
||||
private int rowCount;
|
||||
|
||||
private final int maxRows;
|
||||
private final int bgFetchAfter;
|
||||
|
||||
/**
|
||||
* Create the Sql select based on the request.
|
||||
@@ -86,7 +85,6 @@ public class CQueryFetchIds {
|
||||
this.query = request.getQuery();
|
||||
this.sql = sql;
|
||||
this.maxRows = query.getMaxRows();
|
||||
this.bgFetchAfter = query.getBackgroundFetchAfter();
|
||||
|
||||
query.setGeneratedSql(sql);
|
||||
|
||||
@@ -184,9 +182,6 @@ public class CQueryFetchIds {
|
||||
hasMoreRows = rset.next();
|
||||
break;
|
||||
|
||||
} else if (bgFetchAfter > 0 && rowCount >= bgFetchAfter) {
|
||||
useBackgroundToContinueFetch = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@ import com.avaje.ebean.OrderBy.Property;
|
||||
import com.avaje.ebean.PagingList;
|
||||
import com.avaje.ebean.Query;
|
||||
import com.avaje.ebean.QueryIterator;
|
||||
import com.avaje.ebean.QueryListener;
|
||||
import com.avaje.ebean.QueryResultVisitor;
|
||||
import com.avaje.ebean.RawSql;
|
||||
import com.avaje.ebean.bean.BeanCollectionTouched;
|
||||
@@ -68,8 +67,6 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
* Used to add beans to the PersistanceContext prior to query.
|
||||
*/
|
||||
private transient ArrayList<EntityBean> contextAdditions;
|
||||
|
||||
private transient QueryListener<T> queryListener;
|
||||
|
||||
/**
|
||||
* For lazy loading of ManyToMany we need to add a join to the intersection
|
||||
@@ -142,11 +139,6 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
private boolean futureFetch;
|
||||
|
||||
private List<Object> partialIds;
|
||||
|
||||
/**
|
||||
* The rows after which the fetch continues in a bg thread.
|
||||
*/
|
||||
private int backgroundFetchAfter;
|
||||
|
||||
private int timeout = -1;
|
||||
|
||||
@@ -437,7 +429,6 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
copy.additionalWhere = additionalWhere;
|
||||
copy.additionalHaving = additionalHaving;
|
||||
copy.distinct = distinct;
|
||||
copy.backgroundFetchAfter = backgroundFetchAfter;
|
||||
copy.timeout = timeout;
|
||||
copy.mapKey = mapKey;
|
||||
copy.id = id;
|
||||
@@ -1016,26 +1007,6 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the findListener is one has been set.
|
||||
*/
|
||||
public QueryListener<T> getListener() {
|
||||
return queryListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a FindListener. This is designed for large fetches where lots are
|
||||
* rows are to be processed and instead of returning all the rows they are
|
||||
* processed one at a time.
|
||||
* <p>
|
||||
* Note that the returning List Set or Map will be empty.
|
||||
* </p>
|
||||
*/
|
||||
public DefaultOrmQuery<T> setListener(QueryListener<T> queryListener) {
|
||||
this.queryListener = queryListener;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Class<T> getBeanType() {
|
||||
return beanType;
|
||||
}
|
||||
@@ -1112,15 +1083,6 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getBackgroundFetchAfter() {
|
||||
return backgroundFetchAfter;
|
||||
}
|
||||
|
||||
public DefaultOrmQuery<T> setBackgroundFetchAfter(int backgroundFetchAfter) {
|
||||
this.backgroundFetchAfter = backgroundFetchAfter;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Object getId() {
|
||||
return id;
|
||||
}
|
||||
@@ -1235,23 +1197,6 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
return whereExpressions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if using background fetching or a queryListener.
|
||||
*/
|
||||
public boolean createOwnTransaction() {
|
||||
if (futureFetch){
|
||||
// the future fetches have already created
|
||||
// their own transaction
|
||||
return false;
|
||||
}
|
||||
if (backgroundFetchAfter > 0 || queryListener != null) {
|
||||
// run in own transaction as we can't know how long
|
||||
// the background fetching will continue etc
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getGeneratedSql() {
|
||||
return generatedSql;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ import com.avaje.ebean.OrderBy;
|
||||
import com.avaje.ebean.PagingList;
|
||||
import com.avaje.ebean.Query;
|
||||
import com.avaje.ebean.QueryIterator;
|
||||
import com.avaje.ebean.QueryListener;
|
||||
import com.avaje.ebean.QueryResultVisitor;
|
||||
import com.avaje.ebean.event.BeanQueryRequest;
|
||||
import com.avaje.ebeaninternal.api.HashQueryPlanBuilder;
|
||||
@@ -213,19 +212,10 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
return query.setMaxRows(maxRows);
|
||||
}
|
||||
|
||||
public Query<T> setBackgroundFetchAfter(int backgroundFetchAfter) {
|
||||
return query.setBackgroundFetchAfter(backgroundFetchAfter);
|
||||
}
|
||||
|
||||
public Query<T> setMapKey(String mapKey) {
|
||||
return query.setMapKey(mapKey);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public Query<T> setListener(QueryListener<T> queryListener) {
|
||||
return query.setListener(queryListener);
|
||||
}
|
||||
|
||||
public Query<T> setUseCache(boolean useCache) {
|
||||
return query.setUseCache(useCache);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ import com.avaje.ebean.FutureRowCount;
|
||||
import com.avaje.ebean.OrderBy;
|
||||
import com.avaje.ebean.PagingList;
|
||||
import com.avaje.ebean.Query;
|
||||
import com.avaje.ebean.QueryListener;
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionList;
|
||||
import com.avaje.ebeaninternal.server.expression.FilterExprPath;
|
||||
|
||||
@@ -128,19 +127,10 @@ public class FilterExpressionList<T> extends DefaultExpressionList<T> {
|
||||
throw new PersistenceException(notAllowedMessage);
|
||||
}
|
||||
|
||||
public Query<T> setBackgroundFetchAfter(int backgroundFetchAfter) {
|
||||
return rootQuery.setBackgroundFetchAfter(backgroundFetchAfter);
|
||||
}
|
||||
|
||||
public Query<T> setFirstRow(int firstRow) {
|
||||
return rootQuery.setFirstRow(firstRow);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public Query<T> setListener(QueryListener<T> queryListener) {
|
||||
return rootQuery.setListener(queryListener);
|
||||
}
|
||||
|
||||
|
||||
public Query<T> setMapKey(String mapKey) {
|
||||
return rootQuery.setMapKey(mapKey);
|
||||
}
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
package com.avaje.tests.basic;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.avaje.ebean.BaseTestCase;
|
||||
import com.avaje.ebean.Ebean;
|
||||
import com.avaje.ebean.Query;
|
||||
import com.avaje.ebeaninternal.api.SpiEbeanServer;
|
||||
import com.avaje.tests.model.basic.Order;
|
||||
import com.avaje.tests.model.basic.ResetBasicData;
|
||||
|
||||
public class TestBackgroundFetchAfter extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void testWrtJoin() {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
SpiEbeanServer server = (SpiEbeanServer)Ebean.getServer(null);
|
||||
boolean h2Db = "h2".equals(server.getDatabasePlatform().getName());
|
||||
|
||||
// limit not in sql as join to many
|
||||
Query<Order> q = Ebean.find(Order.class)
|
||||
.fetch("details")
|
||||
.setBackgroundFetchAfter(3)
|
||||
.setMaxRows(10);
|
||||
|
||||
q.findList();
|
||||
String sql = q.getGeneratedSql();
|
||||
|
||||
if (h2Db){
|
||||
Assert.assertTrue(sql.indexOf("limit") == -1);
|
||||
}
|
||||
|
||||
// allows limit use as no join to many
|
||||
q = Ebean.find(Order.class)
|
||||
.setBackgroundFetchAfter(3)
|
||||
.setMaxRows(10);
|
||||
|
||||
q.findList();
|
||||
sql = q.getGeneratedSql();
|
||||
|
||||
if (h2Db){
|
||||
Assert.assertTrue(sql.indexOf("limit") > -1);
|
||||
}
|
||||
|
||||
// allows limit use as join to one (not many)
|
||||
q = Ebean.find(Order.class)
|
||||
.fetch("customer")
|
||||
.setBackgroundFetchAfter(3)
|
||||
.setMaxRows(10);
|
||||
|
||||
q.findList();
|
||||
sql = q.getGeneratedSql();
|
||||
|
||||
if (h2Db){
|
||||
Assert.assertTrue(sql.indexOf("limit") > -1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user