diff --git a/src/main/java/com/avaje/ebeaninternal/server/core/OrmQueryRequest.java b/src/main/java/com/avaje/ebeaninternal/server/core/OrmQueryRequest.java index c9ed30418..94f045241 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/core/OrmQueryRequest.java +++ b/src/main/java/com/avaje/ebeaninternal/server/core/OrmQueryRequest.java @@ -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,12 +44,12 @@ public final class OrmQueryRequest extends BeanRequest implements BeanQueryRe private final BeanFinder finder; - private final LoadContext graphContext; - private final Boolean readOnly; private final RawSql rawSql; + private LoadContext loadContext; + private PersistenceContext persistenceContext; private HashQuery cacheKey; @@ -68,13 +69,10 @@ public final class OrmQueryRequest 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) { - graphContext.executeSecondaryQueries(this, defaultQueryBatch); + loadContext.executeSecondaryQueries(this, defaultQueryBatch); } /** @@ -86,7 +84,7 @@ public final class OrmQueryRequest extends BeanRequest implements BeanQueryRe *

*/ public int getSecondaryQueriesMinBatchSize(int defaultQueryBatch) { - return graphContext.getSecondaryQueriesMinBatchSize(this, defaultQueryBatch); + return loadContext.getSecondaryQueriesMinBatchSize(this, defaultQueryBatch); } /** @@ -107,7 +105,7 @@ public final class OrmQueryRequest extends BeanRequest implements BeanQueryRe * Return the graph context for this query. */ public LoadContext getGraphContext() { - return graphContext; + return loadContext; } /** @@ -165,10 +163,20 @@ public final class OrmQueryRequest extends BeanRequest implements BeanQueryRe createdTransaction = true; } } + // initialise the persistenceContext and loadContext this.persistenceContext = getPersistenceContext(query, transaction); - this.graphContext.setPersistenceContext(persistenceContext); + this.loadContext = new DLoadContext(this); + this.loadContext.registerSecondaryQueries(query); } + /** + * For iterate queries reset the persistenceContext and loadContext. + */ + public void flushPersistenceContextOnIterate() { + persistenceContext = new DefaultPersistenceContext(); + loadContext.setPersistenceContext(persistenceContext); + } + /** * Get the TransactionContext either explicitly set on the query or * transaction scoped. @@ -359,10 +367,6 @@ public final class OrmQueryRequest extends BeanRequest implements BeanQueryRe } } - public void flushPersistenceContextOnIterate() { - beanDescriptor.flushPersistenceContextOnIterate(persistenceContext); - } - /** * Return true if the request wants to log the secondary queries (test purpose). */ diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptor.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptor.java index 3c95d5f16..a69eff632 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptor.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptor.java @@ -2254,12 +2254,5 @@ public class BeanDescriptor implements MetaBeanInfo { return ctx.popBeanState(); } - - public void flushPersistenceContextOnIterate(PersistenceContext persistenceContext) { - persistenceContext.clear(beanType); - for (int i = 0; i < propertiesMany.length; i++) { - persistenceContext.clear(propertiesMany[i].getBeanDescriptor().getBeanType()); - } - } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptorCacheHelp.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptorCacheHelp.java index 9f56a3e61..fc07a2e9e 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptorCacheHelp.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptorCacheHelp.java @@ -25,7 +25,6 @@ import com.avaje.ebeaninternal.server.cache.CachedBeanDataUpdate; import com.avaje.ebeaninternal.server.cache.CachedManyIds; import com.avaje.ebeaninternal.server.core.CacheOptions; import com.avaje.ebeaninternal.server.core.PersistRequestBean; -import com.avaje.ebeaninternal.server.loadcontext.DLoadContext; import com.avaje.ebeaninternal.server.querydefn.NaturalKeyBindParam; import com.avaje.ebeaninternal.server.transaction.DefaultPersistenceContext; @@ -328,14 +327,15 @@ public final class BeanDescriptorCacheHelp { if (context == null) { context = new DefaultPersistenceContext(); } - context.put(query.getId(), bean); - DLoadContext loadContext = new DLoadContext(desc.getEbeanServer(), desc, query.isReadOnly(), query); - loadContext.setPersistenceContext(context); - - EntityBeanIntercept ebi = ((EntityBean) bean)._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)bean; + EntityBeanIntercept ebi = entityBean._ebean_getIntercept(); ebi.setPersistenceContext(context); - loadContext.register(null, ebi); + Object id = desc.getId(entityBean); + context.put(id, bean); + } /** diff --git a/src/main/java/com/avaje/ebeaninternal/server/loadcontext/DLoadBeanContext.java b/src/main/java/com/avaje/ebeaninternal/server/loadcontext/DLoadBeanContext.java index ba9f12c0e..cc5b0d158 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/loadcontext/DLoadBeanContext.java +++ b/src/main/java/com/avaje/ebeaninternal/server/loadcontext/DLoadBeanContext.java @@ -29,7 +29,8 @@ public class DLoadBeanContext extends DLoadBaseContext implements LoadBeanContex super(parent, desc, path, defaultBatchSize, queryProps); - this.bufferList = new ArrayList(); + // bufferList only required when using query joins (queryFetch) + this.bufferList = (!queryFetch) ? null : new ArrayList(); this.currentBuffer = createBuffer(firstBatchSize); } @@ -52,11 +53,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 - currentBuffer = createBuffer(secondaryBatchSize); + if (currentBuffer.isFull()) { + currentBuffer = createBuffer(secondaryBatchSize); } + currentBuffer.add(ebi); + ebi.setBeanLoader(0, currentBuffer, getPersistenceContext()); } private LoadBuffer createBuffer(int size) { @@ -99,23 +100,33 @@ 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 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(batchSize); } - + /** * Return true if the buffer is full. */ - public boolean add(EntityBeanIntercept ebi) { - list.add(ebi); + public boolean isFull() { return batchSize == list.size(); } + + /** + * Return true if the buffer is full. + */ + public void add(EntityBeanIntercept ebi) { + list.add(ebi); + } @Override public List getBatch() { @@ -139,7 +150,7 @@ public class DLoadBeanContext extends DLoadBaseContext implements LoadBeanContex @Override public PersistenceContext getPersistenceContext() { - return context.getPersistenceContext(); + return persistenceContext; } @Override diff --git a/src/main/java/com/avaje/ebeaninternal/server/loadcontext/DLoadContext.java b/src/main/java/com/avaje/ebeaninternal/server/loadcontext/DLoadContext.java index 31aec954f..7ae85b1c7 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/loadcontext/DLoadContext.java +++ b/src/main/java/com/avaje/ebeaninternal/server/loadcontext/DLoadContext.java @@ -49,15 +49,18 @@ public class DLoadContext implements LoadContext { private final Map nodePathMap = new HashMap(); private PersistenceContext persistenceContext; + private List secQuery; + public DLoadContext(OrmQueryRequest request) { - public DLoadContext(SpiEbeanServer ebeanServer, BeanDescriptor rootDescriptor, Boolean readOnly, SpiQuery query) { - - this.ebeanServer = ebeanServer; - this.defaultBatchSize = ebeanServer.getLazyLoadBatchSize(); - this.rootDescriptor = rootDescriptor; - this.readOnly = readOnly; + this.persistenceContext = request.getPersistenceContext(); + this.ebeanServer = request.getServer(); + this.defaultBatchSize = ebeanServer.getLazyLoadBatchSize(); + this.rootDescriptor = request.getBeanDescriptor(); + + SpiQuery query = request.getQuery(); + this.readOnly = query.isReadOnly(); this.excludeBeanCache = Boolean.FALSE.equals(query.isUseBeanCache()); this.useAutofetchManager = query.getAutoFetchManager() != null; @@ -72,7 +75,7 @@ public class DLoadContext implements LoadContext { // initialise rootBeanContext after origin and relativePath have been set this.rootBeanContext = new DLoadBeanContext(this, rootDescriptor, null, defaultBatchSize, null); - } + } protected boolean isExcludeBeanCache() { return excludeBeanCache; diff --git a/src/main/java/com/avaje/ebeaninternal/server/loadcontext/DLoadManyContext.java b/src/main/java/com/avaje/ebeaninternal/server/loadcontext/DLoadManyContext.java index 9ce7a6000..18f64664a 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/loadcontext/DLoadManyContext.java +++ b/src/main/java/com/avaje/ebeaninternal/server/loadcontext/DLoadManyContext.java @@ -31,14 +31,16 @@ public class DLoadManyContext extends DLoadBaseContext implements LoadManyContex super(parent, property.getBeanDescriptor(), path, defaultBatchSize, queryProps); this.property = property; - this.bufferList = new ArrayList(); + // bufferList only required when using query joins (queryFetch) + this.bufferList = (!queryFetch) ? null : new ArrayList(); 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; } @@ -74,11 +76,11 @@ public class DLoadManyContext extends DLoadBaseContext implements LoadManyContex public void register(BeanCollection bc){ - bc.setLoader(0, currentBuffer); - if (currentBuffer.add(bc)) { - // the currentBuffer is full so create another one + if (currentBuffer.isFull()) { currentBuffer = createBuffer(secondaryBatchSize); - } + } + currentBuffer.add(bc); + bc.setLoader(0, currentBuffer); } @@ -112,22 +114,32 @@ public class DLoadManyContext extends DLoadBaseContext implements LoadManyContex */ public static class LoadBuffer implements BeanCollectionLoader, LoadManyBuffer { + private final PersistenceContext persistenceContext; private final DLoadManyContext context; private final int batchSize; private final List> 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>(batchSize); } - + /** * Return true if the buffer is full. */ - public boolean add(BeanCollection bc) { + public boolean isFull() { + return batchSize == list.size(); + } + + /** + * Return true if the buffer is full. + */ + public void add(BeanCollection bc) { list.add(bc); - return batchSize == list.size(); } @Override @@ -162,7 +174,7 @@ public class DLoadManyContext extends DLoadBaseContext implements LoadManyContex @Override public PersistenceContext getPersistenceContext() { - return context.getPersistenceContext(); + return persistenceContext; } @Override diff --git a/src/main/java/com/avaje/ebeaninternal/server/query/CQuery.java b/src/main/java/com/avaje/ebeaninternal/server/query/CQuery.java index 4053925b9..3666ff6f5 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/query/CQuery.java +++ b/src/main/java/com/avaje/ebeaninternal/server/query/CQuery.java @@ -188,8 +188,6 @@ public class CQuery implements DbReadContext, CancelableQuery { private final int maxRowsLimit; - private final PersistenceContext persistenceContext; - private DataReader dataReader; /** @@ -266,7 +264,6 @@ public class CQuery implements DbReadContext, CancelableQuery { this.logWhereSql = queryPlan.getLogWhereSql(); this.desc = request.getBeanDescriptor(); this.predicates = predicates; - this.persistenceContext = request.getPersistenceContext(); this.maxRowsLimit = query.getMaxRows() > 0 ? query.getMaxRows() : GLOBAL_ROW_LIMIT; this.help = createHelp(request); this.collection = (BeanCollection) (help != null ? help.createEmpty(false) : null); @@ -420,7 +417,7 @@ public class CQuery implements DbReadContext, CancelableQuery { * Return the persistence context. */ public PersistenceContext getPersistenceContext() { - return persistenceContext; + return request.getPersistenceContext(); } public void setLoadedBean(EntityBean bean, Object id, Object lazyLoadParentId) { @@ -443,7 +440,7 @@ public class CQuery implements DbReadContext, CancelableQuery { if (lazyLoadParentId != null) { if (!lazyLoadParentId.equals(this.lazyLoadParentId)) { // get the appropriate parent bean from the persistence context - this.lazyLoadParentBean = (EntityBean)persistenceContext.get(lazyLoadManyProperty.getBeanDescriptor().getBeanType(), lazyLoadParentId); + this.lazyLoadParentBean = (EntityBean)getPersistenceContext().get(lazyLoadManyProperty.getBeanDescriptor().getBeanType(), lazyLoadParentId); this.lazyLoadParentId = lazyLoadParentId; }