mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Feature/cache improvements 2 (#1067)
* New Mode to control queryCache behavior * Collections form the cache have to be read only * findCount not queried in query cache * return modifiable collections from the cache * FIX: Compile errors * No effective code change: reformat code / javadoc
This commit is contained in:
committed by
Rob Bygrave
parent
b8e1dffca2
commit
a6e4e181bf
@@ -1,5 +1,6 @@
|
||||
package io.ebeaninternal.api;
|
||||
|
||||
import io.ebean.CacheMode;
|
||||
import io.ebean.EbeanServer;
|
||||
import io.ebean.ExpressionList;
|
||||
import io.ebean.OrderBy;
|
||||
@@ -583,9 +584,9 @@ public interface SpiQuery<T> extends Query<T> {
|
||||
boolean isUseBeanCache();
|
||||
|
||||
/**
|
||||
* Return true if this query should use/check the query cache.
|
||||
* Return the cache mode if this query should use/check the query cache.
|
||||
*/
|
||||
boolean isUseQueryCache();
|
||||
CacheMode getUseQueryCache();
|
||||
|
||||
/**
|
||||
* Return true if the beans from this query should be loaded into the bean
|
||||
|
||||
@@ -35,6 +35,7 @@ import io.ebean.bean.ObjectGraphNode;
|
||||
import io.ebean.bean.PersistenceContext;
|
||||
import io.ebean.bean.PersistenceContext.WithOption;
|
||||
import io.ebean.cache.ServerCacheManager;
|
||||
import io.ebean.common.CopyOnFirstWriteList;
|
||||
import io.ebean.config.CurrentTenantProvider;
|
||||
import io.ebean.config.EncryptKeyManager;
|
||||
import io.ebean.config.ServerConfig;
|
||||
@@ -99,6 +100,7 @@ import javax.persistence.NonUniqueResultException;
|
||||
import javax.persistence.OptimisticLockException;
|
||||
import javax.persistence.PersistenceException;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
@@ -1332,10 +1334,19 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
return findIdsWithCopy(((SpiQuery<T>) query).copy(), t);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <A, T> List<A> findIdsWithCopy(Query<T> query, Transaction t) {
|
||||
|
||||
SpiOrmQueryRequest<?> request = createQueryRequest(Type.ID_LIST, query, t);
|
||||
Object result = request.getFromQueryCache();
|
||||
if (result != null) {
|
||||
if (Boolean.FALSE.equals(request.getQuery().isReadOnly())) {
|
||||
return new CopyOnFirstWriteList<>((List<A>) result);
|
||||
} else {
|
||||
return (List<A>) result;
|
||||
}
|
||||
}
|
||||
try {
|
||||
request.initTransIfRequired();
|
||||
return request.findIds();
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package io.ebeaninternal.server.core;
|
||||
|
||||
import io.ebean.CacheMode;
|
||||
import io.ebean.PersistenceContextScope;
|
||||
import io.ebean.QueryIterator;
|
||||
import io.ebean.Version;
|
||||
import io.ebean.bean.BeanCollection;
|
||||
import io.ebean.bean.EntityBean;
|
||||
import io.ebean.bean.PersistenceContext;
|
||||
import io.ebean.common.CopyOnFirstWriteList;
|
||||
import io.ebean.event.BeanFindController;
|
||||
import io.ebean.event.BeanQueryAdapter;
|
||||
import io.ebean.event.BeanQueryRequest;
|
||||
@@ -32,6 +34,8 @@ import javax.persistence.PersistenceException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@@ -471,12 +475,16 @@ public final class OrmQueryRequest<T> extends BeanRequest implements BeanQueryRe
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object getFromQueryCache() {
|
||||
|
||||
if (!query.isUseQueryCache()) {
|
||||
if (query.getUseQueryCache() == CacheMode.OFF) {
|
||||
return null;
|
||||
} else {
|
||||
cacheKey = query.queryHash();
|
||||
}
|
||||
|
||||
if (!query.getUseQueryCache().isGet()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
cacheKey = query.queryHash();
|
||||
|
||||
Object cached = beanDescriptor.queryCacheGet(cacheKey);
|
||||
|
||||
if (cached != null && isAuditReads() && readAuditQueryType()) {
|
||||
@@ -491,6 +499,18 @@ public final class OrmQueryRequest<T> extends BeanRequest implements BeanQueryRe
|
||||
}
|
||||
}
|
||||
|
||||
if (Boolean.FALSE.equals(query.isReadOnly())) {
|
||||
// return shallow copies if readonly is explicitly set to false
|
||||
if (cached instanceof BeanCollection) {
|
||||
cached = ((BeanCollection<?>)cached).getShallowCopy();
|
||||
} else if (cached instanceof List) {
|
||||
cached = new CopyOnFirstWriteList<>((List)cached);
|
||||
} else if (cached instanceof Set) {
|
||||
cached = new LinkedHashSet<>((Set)cached);
|
||||
} else if (cached instanceof Map) {
|
||||
cached = new LinkedHashMap<>((Map)cached);
|
||||
}
|
||||
}
|
||||
return cached;
|
||||
}
|
||||
|
||||
|
||||
@@ -463,7 +463,7 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query<T> setUseQueryCache(boolean useCache) {
|
||||
public Query<T> setUseQueryCache(CacheMode useCache) {
|
||||
return query.setUseQueryCache(useCache);
|
||||
}
|
||||
|
||||
|
||||
@@ -742,7 +742,7 @@ class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, Expression
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query<T> setUseQueryCache(boolean useCache) {
|
||||
public Query<T> setUseQueryCache(CacheMode useCache) {
|
||||
return exprList.setUseQueryCache(useCache);
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,9 @@ import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -71,7 +73,7 @@ public class DefaultOrmQueryEngine implements OrmQueryEngine {
|
||||
|
||||
flushJdbcBatchOnQuery(request);
|
||||
int result = queryEngine.findCount(request);
|
||||
if (request.getQuery().isUseQueryCache()) {
|
||||
if (request.getQuery().getUseQueryCache().isPut()) {
|
||||
request.putToQueryCache(result);
|
||||
}
|
||||
return result;
|
||||
@@ -81,16 +83,28 @@ public class DefaultOrmQueryEngine implements OrmQueryEngine {
|
||||
public <A> List<A> findIds(OrmQueryRequest<?> request) {
|
||||
|
||||
flushJdbcBatchOnQuery(request);
|
||||
return queryEngine.findIds(request);
|
||||
List<A> result = queryEngine.findIds(request);
|
||||
if (request.getQuery().getUseQueryCache().isPut()) {
|
||||
result = Collections.unmodifiableList(result);
|
||||
request.putToQueryCache(result);
|
||||
if (Boolean.FALSE.equals(request.getQuery().isReadOnly())) {
|
||||
result = new ArrayList<>(result);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <A> List<A> findSingleAttributeList(OrmQueryRequest<?> request) {
|
||||
flushJdbcBatchOnQuery(request);
|
||||
List<A> result = queryEngine.findSingleAttributeList(request);
|
||||
if (!result.isEmpty() && request.getQuery().isUseQueryCache()) {
|
||||
if (!result.isEmpty() && request.getQuery().getUseQueryCache().isPut()) {
|
||||
// load the query result into the query cache
|
||||
result = Collections.unmodifiableList(result);
|
||||
request.putToQueryCache(result);
|
||||
if (Boolean.FALSE.equals(request.getQuery().isReadOnly())) {
|
||||
result = new ArrayList<>(result);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -137,9 +151,13 @@ public class DefaultOrmQueryEngine implements OrmQueryEngine {
|
||||
}
|
||||
}
|
||||
|
||||
if (!result.isEmpty() && query.isUseQueryCache()) {
|
||||
if (!result.isEmpty() && query.getUseQueryCache().isPut()) {
|
||||
// load the query result into the query cache
|
||||
result.setReadOnly(true);
|
||||
request.putToQueryCache(result);
|
||||
if (Boolean.FALSE.equals(query.isReadOnly())) {
|
||||
result = result.getShallowCopy();
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package io.ebeaninternal.server.querydefn;
|
||||
|
||||
import io.ebean.CacheMode;
|
||||
import io.ebean.EbeanServer;
|
||||
import io.ebean.Expression;
|
||||
import io.ebean.ExpressionFactory;
|
||||
@@ -195,7 +196,7 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
|
||||
private boolean excludeBeanCache;
|
||||
|
||||
private Boolean useQueryCache;
|
||||
private CacheMode useQueryCache = CacheMode.OFF;
|
||||
|
||||
private Boolean readOnly;
|
||||
|
||||
@@ -1094,9 +1095,13 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUseQueryCache() {
|
||||
public CacheMode getUseQueryCache() {
|
||||
// not using L2 cache for asDraft() query
|
||||
return !isAsDraft() && Boolean.TRUE.equals(useQueryCache);
|
||||
if (isAsDraft()) {
|
||||
return CacheMode.OFF;
|
||||
} else {
|
||||
return useQueryCache;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1106,7 +1111,7 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultOrmQuery<T> setUseQueryCache(boolean useQueryCache) {
|
||||
public DefaultOrmQuery<T> setUseQueryCache(CacheMode useQueryCache) {
|
||||
this.useQueryCache = useQueryCache;
|
||||
return this;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user