mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Fix for #207: Add support for PeristenceContextScope QUERY and NONE (in addition to the existing TRANSACTION scope)
This commit is contained in:
@@ -2,10 +2,7 @@ package com.avaje.ebeaninternal.api;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.avaje.ebean.EbeanServer;
|
||||
import com.avaje.ebean.Query;
|
||||
import com.avaje.ebean.Transaction;
|
||||
import com.avaje.ebean.TxScope;
|
||||
import com.avaje.ebean.*;
|
||||
import com.avaje.ebean.bean.BeanCollectionLoader;
|
||||
import com.avaje.ebean.bean.BeanLoader;
|
||||
import com.avaje.ebean.bean.CallStack;
|
||||
@@ -63,6 +60,11 @@ public interface SpiEbeanServer extends EbeanServer, BeanLoader, BeanCollectionL
|
||||
*/
|
||||
public CallStack createCallStack();
|
||||
|
||||
/**
|
||||
* Return the PersistenceContextScope to use defined at query or server level.
|
||||
*/
|
||||
public PersistenceContextScope getPersistenceContextScope(SpiQuery<?> query);
|
||||
|
||||
/**
|
||||
* Return the DDL generator.
|
||||
*/
|
||||
|
||||
@@ -5,6 +5,7 @@ import java.util.List;
|
||||
|
||||
import com.avaje.ebean.ExpressionList;
|
||||
import com.avaje.ebean.OrderBy;
|
||||
import com.avaje.ebean.PersistenceContextScope;
|
||||
import com.avaje.ebean.Query;
|
||||
import com.avaje.ebean.bean.BeanCollectionTouched;
|
||||
import com.avaje.ebean.bean.CallStack;
|
||||
@@ -79,7 +80,15 @@ public interface SpiQuery<T> extends Query<T> {
|
||||
*/
|
||||
SUBQUERY
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the PersistenceContextScope that this query should use.
|
||||
* <p>
|
||||
* This can be null and in that case use the default scope.
|
||||
* </p>
|
||||
*/
|
||||
public PersistenceContextScope getPersistenceContextScope();
|
||||
|
||||
/**
|
||||
* Return true if select all properties was used to ensure the property
|
||||
* invoking a lazy load was included in the query.
|
||||
|
||||
+7
-4
@@ -40,10 +40,13 @@ public class DefaultServerCacheManager implements ServerCacheManager {
|
||||
cacheFactory.init(server);
|
||||
this.ebeanServer = (SpiEbeanServer)server;
|
||||
}
|
||||
|
||||
public void setCaching(Class<?> beanType, boolean useCache) {
|
||||
ebeanServer.getBeanDescriptor(beanType).getCacheOptions().setUseCache(useCache);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set bean caching on or off for a given bean type.
|
||||
*/
|
||||
public void setCaching(Class<?> beanType, boolean useCache) {
|
||||
ebeanServer.getBeanDescriptor(beanType).setUseCache(useCache);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear both the bean cache and the query cache for a
|
||||
|
||||
@@ -137,7 +137,6 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
|
||||
private final CQueryEngine cqueryEngine;
|
||||
|
||||
//@Deprecated
|
||||
private DdlGenerator ddlGenerator;
|
||||
|
||||
private final ExpressionFactory expressionFactory;
|
||||
@@ -157,6 +156,11 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
*/
|
||||
private String mbeanName;
|
||||
|
||||
/**
|
||||
* The default PersistenceContextScope used if it is not explicitly set on a query.
|
||||
*/
|
||||
private final PersistenceContextScope defaultPersistenceContextScope;
|
||||
|
||||
/**
|
||||
* The MBeanServer Ebean is registered with.
|
||||
*/
|
||||
@@ -215,6 +219,7 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
this.cqueryEngine = config.getCQueryEngine();
|
||||
this.expressionFactory = config.getExpressionFactory();
|
||||
this.encryptKeyManager = serverConfig.getEncryptKeyManager();
|
||||
this.defaultPersistenceContextScope = serverConfig.getPersistenceContextScope();
|
||||
|
||||
this.beanDescriptorManager = config.getBeanDescriptorManager();
|
||||
beanDescriptorManager.setEbeanServer(this);
|
||||
@@ -1131,8 +1136,8 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
t = getCurrentServerTransaction();
|
||||
}
|
||||
PersistenceContext context = null;
|
||||
if (t != null) {
|
||||
// first look in the persistence context
|
||||
if (t != null && useTransactionPersistenceContext(query)) {
|
||||
// first look in the transaction scoped persistence context
|
||||
context = t.getPersistenceContext();
|
||||
if (context != null) {
|
||||
WithOption o = context.getWithOption(beanDescriptor.getBeanType(), query.getId());
|
||||
@@ -1155,7 +1160,22 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
// Hit the L2 bean cache
|
||||
return beanDescriptor.cacheBeanGet(query, context);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return true if transactions PersistenceContext should be used.
|
||||
*/
|
||||
private <T> boolean useTransactionPersistenceContext(SpiQuery<T> query) {
|
||||
return PersistenceContextScope.TRANSACTION.equals(getPersistenceContextScope(query));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the PersistenceContextScope to use defined at query or server level.
|
||||
*/
|
||||
public PersistenceContextScope getPersistenceContextScope(SpiQuery<?> query) {
|
||||
PersistenceContextScope scope = query.getPersistenceContextScope();
|
||||
return (scope != null) ? scope : defaultPersistenceContextScope;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> T findId(Query<T> query, Transaction t) {
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ 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;
|
||||
import com.avaje.ebeaninternal.server.transaction.NoopPersistenceContext;
|
||||
|
||||
/**
|
||||
* Wraps the objects involved in executing a Query.
|
||||
@@ -53,7 +54,7 @@ public final class OrmQueryRequest<T> extends BeanRequest implements BeanQueryRe
|
||||
private HashQuery cacheKey;
|
||||
|
||||
private HashQueryPlan queryPlanHash;
|
||||
|
||||
|
||||
/**
|
||||
* Create the InternalQueryRequest.
|
||||
*/
|
||||
@@ -69,7 +70,7 @@ public final class OrmQueryRequest<T> extends BeanRequest implements BeanQueryRe
|
||||
this.readOnly = query.isReadOnly();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Return the database platform like clause.
|
||||
*/
|
||||
@@ -183,18 +184,32 @@ public final class OrmQueryRequest<T> extends BeanRequest implements BeanQueryRe
|
||||
persistenceContext = new DefaultPersistenceContext();
|
||||
loadContext.setPersistenceContext(persistenceContext);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the TransactionContext either explicitly set on the query or
|
||||
* transaction scoped.
|
||||
*/
|
||||
private PersistenceContext getPersistenceContext(SpiQuery<?> query, SpiTransaction t) {
|
||||
|
||||
// check if there is already a persistence context set which is the case
|
||||
// when lazy loading or query joins are executed
|
||||
PersistenceContext ctx = query.getPersistenceContext();
|
||||
if (ctx == null) {
|
||||
ctx = t.getPersistenceContext();
|
||||
if (ctx != null) return ctx;
|
||||
|
||||
// determine the scope (from the query and then server)
|
||||
PersistenceContextScope scope = ebeanServer.getPersistenceContextScope(query);
|
||||
switch (scope) {
|
||||
case QUERY:
|
||||
// Create a new PersistenceContext for this query
|
||||
return new DefaultPersistenceContext();
|
||||
case NONE:
|
||||
// Effectively don't use a PersistenceContext
|
||||
return new NoopPersistenceContext();
|
||||
default: {
|
||||
// Use the transaction scoped PersistenceContext
|
||||
return t.getPersistenceContext();
|
||||
}
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -725,6 +725,13 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
|
||||
return inheritInfo == null || inheritInfo.isRoot();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the bean caching on or off.
|
||||
*/
|
||||
public void setUseCache(boolean useCache) {
|
||||
cacheHelp.setUseCache(useCache);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if there is currently query caching for this type of bean.
|
||||
*/
|
||||
|
||||
@@ -105,7 +105,16 @@ public final class BeanDescriptorCacheHelp<T> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void setUseCache(boolean useCache) {
|
||||
if (useCache) {
|
||||
getBeanCache();
|
||||
} else {
|
||||
beanCacheClear();
|
||||
beanCache = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if there is currently query caching for this type of bean.
|
||||
*/
|
||||
|
||||
@@ -167,6 +167,8 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
|
||||
private Boolean readOnly;
|
||||
|
||||
private PersistenceContextScope persistenceContextScope;
|
||||
|
||||
private boolean sqlSelect;
|
||||
|
||||
/**
|
||||
@@ -459,6 +461,7 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
if (havingExpressions != null) {
|
||||
copy.havingExpressions = havingExpressions.copy(copy);
|
||||
}
|
||||
copy.persistenceContextScope = persistenceContextScope;
|
||||
copy.usageProfiling = usageProfiling;
|
||||
copy.autoFetch = autoFetch;
|
||||
copy.parentNode = parentNode;
|
||||
@@ -468,6 +471,16 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
return copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query<T> setPersistenceContextScope(PersistenceContextScope scope) {
|
||||
this.persistenceContextScope = scope;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PersistenceContextScope getPersistenceContextScope() {
|
||||
return persistenceContextScope;
|
||||
}
|
||||
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
package com.avaje.ebeaninternal.server.transaction;
|
||||
|
||||
import com.avaje.ebean.bean.PersistenceContext;
|
||||
|
||||
/**
|
||||
* PersistenceContext used with scope of NONE.
|
||||
* <p/>
|
||||
* When used effectively means no PersistenceContext is used at all. This is not expected to be used much and
|
||||
* actually is not recommended.
|
||||
*/
|
||||
public class NoopPersistenceContext implements PersistenceContext {
|
||||
|
||||
@Override
|
||||
public void put(Object id, Object bean) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object putIfAbsent(Object id, Object bean) {
|
||||
// do nothing
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object get(Class<?> beanType, Object uid) {
|
||||
// do nothing, return null
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WithOption getWithOption(Class<?> beanType, Object uid) {
|
||||
// do nothing, return null
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear(Class<?> beanType) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear(Class<?> beanType, Object uid) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleted(Class<?> beanType, Object id) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size(Class<?> beanType) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user