Author: mikedd
Date: Tue Mar 30 20:42:29 2010
New Revision: 929266
URL: http://svn.apache.org/viewvc?rev=929266&view=rev
Log:
OPENJPA-1603:
Decouple the QueryCache from the DataCache. Code contributed by Mike Dick and
Rick Curtis.
Added:
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/PPerson.java
(with props)
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/PPhone.java
(with props)
Modified:
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreManager.java
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DataCacheManagerImpl.java
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DataCacheStoreManager.java
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/QueryCacheStoreQuery.java
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/QueryKey.java
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingBroker.java
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingStoreManager.java
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StoreContext.java
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StoreManager.java
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/datacache/CacheTest.java
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/querycache/TestQueryCache.java
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/TestInverseEagerSQL.java
openjpa/trunk/openjpa-xmlstore/src/main/java/org/apache/openjpa/xmlstore/XMLStoreManager.java
Modified:
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreManager.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreManager.java?rev=929266&r1=929265&r2=929266&view=diff
==============================================================================
---
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreManager.java
(original)
+++
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreManager.java
Tue Mar 30 20:42:29 2010
@@ -30,12 +30,15 @@ import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
+import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.sql.DataSource;
import org.apache.commons.lang.StringUtils;
+import org.apache.openjpa.datacache.QueryCache;
+import org.apache.openjpa.datacache.QueryCacheStoreQuery;
import org.apache.openjpa.enhance.PersistenceCapable;
import org.apache.openjpa.event.OrphanedKeyAction;
import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
@@ -295,6 +298,11 @@ public class JDBCStoreManager
return exists(mapping, sm.getObjectId(), context);
}
+ public boolean isCached(List<Object> oids, BitSet edata) {
+ // JDBCStoreManager doesn't store oids in memory.
+ return false;
+ }
+
private boolean exists(ClassMapping mapping, Object oid, Object context) {
// add where conditions on base class to avoid joins if subclass
// doesn't use oid as identifier
@@ -455,8 +463,9 @@ public class JDBCStoreManager
// Check if the owner has eagerly loaded ToMany relations.
for (int i = 0; i < fms.length; i++) {
if (res.getEager(fms[i]) != null) {
- if (!fms[i].getElement().isTypePC())
+ if (!fms[i].getElement().isTypePC()) {
continue;
+ }
Object coll = owner.fetchObject(fms[i].getIndex());
if (coll instanceof Map)
coll = ((Map)coll).values();
@@ -471,24 +480,23 @@ public class JDBCStoreManager
for (Iterator<?> itr = ((Collection<?>) coll).iterator();
itr.hasNext();) {
PersistenceCapable pc = (PersistenceCapable)
itr.next();
-
- if (pc == null)
+ if (pc == null) {
continue;
-
- OpenJPAStateManager sm = (OpenJPAStateManager) pc.
- pcGetStateManager();
- FieldMapping[] fmd = ((ClassMapping) sm.getMetaData()).
- getFieldMappings();
+ }
+ OpenJPAStateManager sm = (OpenJPAStateManager)
pc.pcGetStateManager();
+ ClassMapping cm =
+ (ClassMapping)
_conf.getMetaDataRepositoryInstance().getCachedMetaData(pc.getClass());
+ FieldMapping[] fmd = cm.getFieldMappings();
for (int j = 0; j < fmd.length; j++) {
- Object oid = sm.getIntermediate(fmd[j].getIndex());
- // if oid was setIntermediate() previously
- // and it is the same as the owner,
- // then set the inverse relation
- if (oid != null &&
- oid.equals(owner.getObjectId())) {
- sm.storeObject(fmd[j].getIndex(),
- owner.getPersistenceCapable());
- break;
+ // don't check the oids for basic fields.
+ if (fmd[j].isTypePC()) {
+ Object oid =
sm.getIntermediate(fmd[j].getIndex());
+ // if oid was setIntermediate() previously and
it is the same as the owner,generate
+ // then set the inverse relation
+ if (oid != null &&
oid.equals(owner.getObjectId())) {
+ sm.storeObject(fmd[j].getIndex(),
owner.getPersistenceCapable());
+ break;
+ }
}
}
}
@@ -911,16 +919,33 @@ public class JDBCStoreManager
return paged;
}
- public StoreQuery newQuery(String language) {
+ private StoreQuery newStoreQuery(String language) {
ExpressionParser ep = QueryLanguages.parserForLanguage(language);
- if (ep != null)
+ if (ep != null) {
return new JDBCStoreQuery(this, ep);
- if (QueryLanguages.LANG_SQL.equals(language))
+ }
+ if (QueryLanguages.LANG_SQL.equals(language)) {
return new SQLStoreQuery(this);
- if (QueryLanguages.LANG_PREPARED_SQL.equals(language))
+ }
+ if (QueryLanguages.LANG_PREPARED_SQL.equals(language)) {
return new PreparedSQLStoreQuery(this);
+ }
return null;
}
+
+ public StoreQuery newQuery(String language) {
+ StoreQuery sq = newStoreQuery(language);
+ if (sq == null || QueryLanguages.parserForLanguage(language) == null) {
+ return sq;
+ }
+
+ QueryCache queryCache =
_ctx.getConfiguration().getDataCacheManagerInstance().getSystemQueryCache();
+ if (queryCache == null) {
+ return sq;
+ }
+
+ return new QueryCacheStoreQuery(sq, queryCache);
+ }
public FetchConfiguration newFetchConfiguration() {
return new JDBCFetchConfigurationImpl();
Modified:
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DataCacheManagerImpl.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DataCacheManagerImpl.java?rev=929266&r1=929265&r2=929266&view=diff
==============================================================================
---
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DataCacheManagerImpl.java
(original)
+++
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DataCacheManagerImpl.java
Tue Mar 30 20:42:29 2010
@@ -57,7 +57,11 @@ public class DataCacheManagerImpl
public void initialize(OpenJPAConfiguration conf, ObjectValue dataCache,
ObjectValue queryCache) {
_conf = conf;
+ _queryCache = (QueryCache) queryCache.instantiate(QueryCache.class,
conf);
+ if (_queryCache != null)
+ _queryCache.initialize(this);
_cache = (DataCache) dataCache.instantiate(DataCache.class, conf);
+
if (_cache == null)
return;
@@ -69,9 +73,7 @@ public class DataCacheManagerImpl
_policy = conf.getCacheDistributionPolicyInstance();
_cache.initialize(this);
- _queryCache = (QueryCache) queryCache.instantiate(QueryCache.class,
conf);
- if (_queryCache != null)
- _queryCache.initialize(this);
+
}
public DataCache getSystemDataCache() {
@@ -155,6 +157,7 @@ public class DataCacheManagerImpl
_includedTypes = includedTypes;
_excludedTypes = excludedTypes;
}
+
/**
* Affirms the given class is eligible to be cached according to the cache
mode
* and the cache enable flag on the given metadata.
Modified:
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DataCacheStoreManager.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DataCacheStoreManager.java?rev=929266&r1=929265&r2=929266&view=diff
==============================================================================
---
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DataCacheStoreManager.java
(original)
+++
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DataCacheStoreManager.java
Tue Mar 30 20:42:29 2010
@@ -34,14 +34,11 @@ import org.apache.openjpa.kernel.DataCac
import org.apache.openjpa.kernel.DataCacheStoreMode;
import org.apache.openjpa.kernel.DelegatingStoreManager;
import org.apache.openjpa.kernel.FetchConfiguration;
-import org.apache.openjpa.kernel.FindCallbacks;
import org.apache.openjpa.kernel.LockLevels;
import org.apache.openjpa.kernel.OpenJPAStateManager;
import org.apache.openjpa.kernel.PCState;
-import org.apache.openjpa.kernel.QueryLanguages;
import org.apache.openjpa.kernel.StoreContext;
import org.apache.openjpa.kernel.StoreManager;
-import org.apache.openjpa.kernel.StoreQuery;
import org.apache.openjpa.meta.ClassMetaData;
import org.apache.openjpa.meta.MetaDataRepository;
import org.apache.openjpa.util.OpenJPAId;
@@ -228,22 +225,6 @@ public class DataCacheStoreManager
evictTypes(_ctx.getUpdatedTypes());
}
- // and notify the query cache. notify in one batch to reduce synch
- QueryCache queryCache = _ctx.getConfiguration().
- getDataCacheManagerInstance().getSystemQueryCache();
- if (queryCache != null) {
- Collection<Class<?>> pers = _ctx.getPersistedTypes();
- Collection<Class<?>> del = _ctx.getDeletedTypes();
- Collection<Class<?>> up = _ctx.getUpdatedTypes();
- int size = pers.size() + del.size() + up.size();
- if (size > 0) {
- Collection<Class<?>> types = new ArrayList<Class<?>>(size);
- types.addAll(pers);
- types.addAll(del);
- types.addAll(up);
- queryCache.onTypesChanged(new TypesChangedEvent(this,
types));
- }
- }
}
}
@@ -292,12 +273,31 @@ public class DataCacheStoreManager
public boolean exists(OpenJPAStateManager sm, Object edata) {
DataCache cache = _mgr.selectCache(sm);
- if (cache != null && !isLocking(null)
- && cache.contains(sm.getObjectId()))
+ if (cache != null && !isLocking(null) &&
cache.contains(sm.getObjectId()))
return true;
return super.exists(sm, edata);
}
+ public boolean isCached(List<Object> oids, BitSet edata) {
+ // If using partitioned cache, we were and still are broke.
+ DataCache cache = _mgr.getSystemDataCache();
+ if (cache != null && !isLocking(null)) {
+ // BitSet size is not consistent.
+ for(int i = 0; i < oids.size(); i++) {
+ Object oid = oids.get(i);
+ // Only check the cache if we haven't found the current oid.
+ if (edata.get(i) == false && cache.contains(oid)) {
+ edata.set(i);
+ }
+ }
+ if(edata.cardinality()==oids.size()){
+ return true;
+ }
+ }
+
+ return super.isCached(oids, edata);
+ }
+
public boolean syncVersion(OpenJPAStateManager sm, Object edata) {
DataCache cache = _mgr.selectCache(sm);
if (cache == null || sm.isEmbedded())
@@ -660,22 +660,6 @@ public class DataCacheStoreManager
.fireLocalStaleNotification(oid);
}
- public StoreQuery newQuery(String language) {
- StoreQuery q = super.newQuery(language);
-
- // if the query can't be parsed or it's using a non-parsed language
- // (one for which there is no ExpressionParser), we can't cache it.
- if (q == null || QueryLanguages.parserForLanguage(language) == null)
- return q;
-
- QueryCache queryCache = _ctx.getConfiguration().
- getDataCacheManagerInstance().getSystemQueryCache();
- if (queryCache == null)
- return q;
-
- return new QueryCacheStoreQuery(q, queryCache);
- }
-
/**
* Create a new cacheable instance for the given state manager.
*/
Modified:
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/QueryCacheStoreQuery.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/QueryCacheStoreQuery.java?rev=929266&r1=929265&r2=929266&view=diff
==============================================================================
---
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/QueryCacheStoreQuery.java
(original)
+++
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/QueryCacheStoreQuery.java
Tue Mar 30 20:42:29 2010
@@ -33,6 +33,7 @@ import java.util.TreeMap;
import org.apache.commons.collections.map.LinkedMap;
import org.apache.openjpa.datacache.AbstractQueryCache.EvictPolicy;
+import org.apache.openjpa.kernel.DelegatingStoreManager;
import org.apache.openjpa.kernel.FetchConfiguration;
import org.apache.openjpa.kernel.LockLevels;
import org.apache.openjpa.kernel.OpenJPAStateManager;
@@ -122,6 +123,7 @@ public class QueryCacheStoreQuery
// get the cached data
QueryResult res = _cache.get(qk);
+
if (res == null)
return null;
if (res.isEmpty())
@@ -153,24 +155,11 @@ public class QueryCacheStoreQuery
int projs = getContext().getProjectionAliases().length;
if (projs == 0) {
- // make sure the data cache contains the oids for the query result;
- // if it doesn't, then using the result could be slower than not
- // using it because of the individual by-oid lookups
- ClassMetaData meta = _repos.getMetaData(getContext().
- getCandidateType(), _sctx.getClassLoader(), true);
- if (meta.getDataCache() == null)
+ // We're only going to return the cached results if we have ALL
results cached. This could be improved
+ // in the future to be a little more intelligent.
+ if (getContext().getStoreContext().isCached(res) == false) {
return null;
-
- BitSet idxs = meta.getDataCache().containsAll(res);
-
- // eventually we should optimize this to figure out how many
objects
- // the cache is missing and if only a few do a bulk fetch for them
- int len = idxs.length();
- if (len < res.size())
- return null;
- for (int i = 0; i < len; i++)
- if (!idxs.get(i))
- return null;
+ }
}
return new CachedList(res, projs != 0, _sctx);
}
Modified:
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/QueryKey.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/QueryKey.java?rev=929266&r1=929265&r2=929266&view=diff
==============================================================================
---
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/QueryKey.java
(original)
+++
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/QueryKey.java
Tue Mar 30 20:42:29 2010
@@ -200,14 +200,11 @@ public class QueryKey
// since the class change framework deals with least-derived types,
// record the least-derived access path types
meta = metas[i];
- if (meta.getDataCache() != null)
- accessPathClassNames.add(meta.getDescribedType().getName());
- while (meta.getPCSuperclass() != null)
- meta = meta.getPCSuperclassMetaData();
-
- // ensure that this metadata is cacheable
- if (meta.getDataCache() == null)
- return null;
+ accessPathClassNames.add(meta.getDescribedType().getName());
+ while (meta.getPCSuperclass() != null) {
+ meta = meta.getPCSuperclassMetaData();
+ }
+
accessPathClassNames.add(meta.getDescribedType().getName());
}
Modified:
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java?rev=929266&r1=929265&r2=929266&view=diff
==============================================================================
---
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java
(original)
+++
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java
Tue Mar 30 20:42:29 2010
@@ -51,6 +51,8 @@ import org.apache.commons.lang.StringUti
import org.apache.openjpa.conf.Compatibility;
import org.apache.openjpa.conf.OpenJPAConfiguration;
import org.apache.openjpa.datacache.DataCache;
+import org.apache.openjpa.datacache.QueryCache;
+import org.apache.openjpa.datacache.TypesChangedEvent;
import org.apache.openjpa.ee.ManagedRuntime;
import org.apache.openjpa.enhance.PCRegistry;
import org.apache.openjpa.enhance.PersistenceCapable;
@@ -70,7 +72,6 @@ import org.apache.openjpa.lib.util.Refer
import org.apache.openjpa.lib.util.ReferenceMap;
import org.apache.openjpa.meta.ClassMetaData;
import org.apache.openjpa.meta.FieldMetaData;
-import org.apache.openjpa.meta.JavaTypes;
import org.apache.openjpa.meta.MetaDataRepository;
import org.apache.openjpa.meta.SequenceMetaData;
import org.apache.openjpa.meta.ValueMetaData;
@@ -88,7 +89,6 @@ import org.apache.openjpa.util.ObjectId;
import org.apache.openjpa.util.ObjectNotFoundException;
import org.apache.openjpa.util.OpenJPAException;
import org.apache.openjpa.util.OptimisticException;
-import org.apache.openjpa.util.Proxy;
import org.apache.openjpa.util.RuntimeExceptionTranslator;
import org.apache.openjpa.util.StoreException;
import org.apache.openjpa.util.UnsupportedException;
@@ -1416,8 +1416,25 @@ public class BrokerImpl
releaseConn = _connRetainMode != CONN_RETAIN_ALWAYS;
if (rollback)
_store.rollback();
- else
+ else {
+ // and notify the query cache. notify in one batch to
reduce synch
+ QueryCache queryCache = getConfiguration().
+ getDataCacheManagerInstance().getSystemQueryCache();
+ if (queryCache != null) {
+ Collection<Class<?>> pers = getPersistedTypes();
+ Collection<Class<?>> del = getDeletedTypes();
+ Collection<Class<?>> up = getUpdatedTypes();
+ int size = pers.size() + del.size() + up.size();
+ if (size > 0) {
+ Collection<Class<?>> types = new
ArrayList<Class<?>>(size);
+ types.addAll(pers);
+ types.addAll(del);
+ types.addAll(up);
+ queryCache.onTypesChanged(new
TypesChangedEvent(this, types));
+ }
+ }
_store.commit();
+ }
} else {
releaseConn = _connRetainMode == CONN_RETAIN_TRANS;
_store.rollbackOptimistic();
@@ -5039,4 +5056,19 @@ public class BrokerImpl
return null;
}
}
+
+ public boolean isCached(List<Object> oids) {
+ BitSet loaded = new BitSet(oids.size());
+ //check L1 cache first
+ for (int i = 0; i < oids.size(); i++) {
+ Object oid = oids.get(i);
+ if (_cache.getById(oid, false) != null) {
+ loaded.set(i);
+ }
+ }
+ if(loaded.cardinality()==oids.size()){
+ return true;
+ }
+ return _store.isCached(oids, loaded);
+ };
}
Modified:
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingBroker.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingBroker.java?rev=929266&r1=929265&r2=929266&view=diff
==============================================================================
---
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingBroker.java
(original)
+++
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingBroker.java
Tue Mar 30 20:42:29 2010
@@ -21,6 +21,7 @@ package org.apache.openjpa.kernel;
import java.util.BitSet;
import java.util.Collection;
import java.util.Iterator;
+import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -1463,4 +1464,8 @@ public class DelegatingBroker
public Object getConnectionFactory2() {
return _broker.getConnectionFactory2();
}
+
+ public boolean isCached(List<Object> oid) {
+ return _broker.isCached(oid);
+ }
}
Modified:
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingStoreManager.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingStoreManager.java?rev=929266&r1=929265&r2=929266&view=diff
==============================================================================
---
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingStoreManager.java
(original)
+++
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingStoreManager.java
Tue Mar 30 20:42:29 2010
@@ -20,6 +20,7 @@ package org.apache.openjpa.kernel;
import java.util.BitSet;
import java.util.Collection;
+import java.util.List;
import org.apache.openjpa.lib.rop.ResultObjectProvider;
import org.apache.openjpa.meta.ClassMetaData;
@@ -199,4 +200,9 @@ public abstract class DelegatingStoreMan
public boolean cancelAll() {
return _store.cancelAll();
}
+
+ public boolean isCached(List<Object> oids, BitSet edata) {
+ return _store.isCached(oids, edata);
+ }
+
}
Modified:
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StoreContext.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StoreContext.java?rev=929266&r1=929265&r2=929266&view=diff
==============================================================================
---
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StoreContext.java
(original)
+++
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StoreContext.java
Tue Mar 30 20:42:29 2010
@@ -21,9 +21,11 @@ package org.apache.openjpa.kernel;
import java.util.BitSet;
import java.util.Collection;
import java.util.Iterator;
+import java.util.List;
import org.apache.openjpa.conf.OpenJPAConfiguration;
import org.apache.openjpa.meta.ValueMetaData;
+import org.apache.openjpa.util.UserException;
/**
* Represents a set of managed objects and their environment.
@@ -111,8 +113,8 @@ public interface StoreContext {
public String getConnectionPassword();
/**
- * Return the cached instance for the given oid/object, or null if not
- * cached.
+ * Return the instance for the given oid/object , or null if not
+ * found in the L1 cache.
*
* @param oid the object's id
* @return the cached object, or null if not cached
@@ -490,4 +492,12 @@ public interface StoreContext {
* @return the NonJTA connection factory or null if connectionFactoryName
is blank.
*/
public Object getConnectionFactory2();
+
+ /**
+ * Indicate whether the oid can be found in the StoreContext's L1 cache or
in the StoreManager cache.
+ * @param oid List of ObjectIds for PersistenceCapables which may be found
in memory.
+ * @return true if the oid is available in memory (cached) otherwise false.
+ * @since 2.0.0.
+ */
+ public boolean isCached(List<Object> oid);
}
Modified:
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StoreManager.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StoreManager.java?rev=929266&r1=929265&r2=929266&view=diff
==============================================================================
---
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StoreManager.java
(original)
+++
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StoreManager.java
Tue Mar 30 20:42:29 2010
@@ -20,6 +20,7 @@ package org.apache.openjpa.kernel;
import java.util.BitSet;
import java.util.Collection;
+import java.util.List;
import org.apache.openjpa.lib.rop.ResultObjectProvider;
import org.apache.openjpa.lib.util.Closeable;
@@ -99,6 +100,13 @@ public interface StoreManager
* if it does not.
*/
public boolean exists(OpenJPAStateManager sm, Object edata);
+
+ /**
+ * Verify that the given instance exists in the data store in memory;
return false
+ * if it does not. When an object is found in memory the corresponding
element of
+ * the BitSet is set to 1.
+ */
+ public boolean isCached(List<Object> oids, BitSet edata);
/**
* Update the version information in the given state manager to the
Modified:
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/datacache/CacheTest.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/datacache/CacheTest.java?rev=929266&r1=929265&r2=929266&view=diff
==============================================================================
---
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/datacache/CacheTest.java
(original)
+++
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/datacache/CacheTest.java
Tue Mar 30 20:42:29 2010
@@ -781,7 +781,8 @@ public abstract class CacheTest extends
Collection c = (Collection) q.execute();
iterate(c);
- assertInCache(q, Boolean.FALSE);
+ // Query results are no longer dependent on cacheability of an
entity.
+ assertInCache(q, Boolean.TRUE);
}
finally {
close(broker);
@@ -801,7 +802,8 @@ public abstract class CacheTest extends
Collection c = (Collection) q.execute();
iterate(c);
- assertInCache(q, Boolean.FALSE);
+ // Query results are no longer dependent on cacheability of an entity.
+ assertInCache(q, Boolean.TRUE);
}
finally {
close(broker);
Modified:
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/querycache/TestQueryCache.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/querycache/TestQueryCache.java?rev=929266&r1=929265&r2=929266&view=diff
==============================================================================
---
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/querycache/TestQueryCache.java
(original)
+++
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/querycache/TestQueryCache.java
Tue Mar 30 20:42:29 2010
@@ -23,112 +23,104 @@ import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.NamedQuery;
-import org.apache.openjpa.persistence.common.utils.AbstractTestCase;
import org.apache.openjpa.persistence.querycache.common.apps.Entity1;
import org.apache.openjpa.persistence.querycache.common.apps.Entity2;
+import org.apache.openjpa.persistence.test.SQLListenerTestCase;
@NamedQuery(name = "setParam1",
- query = "SELECT o FROM Entity1 o WHERE o.pk LIKE :pk")
-public class TestQueryCache extends AbstractTestCase {
+ query = "SELECT o FROM Entity1 o WHERE o.pk = :pk")
+public class TestQueryCache extends SQLListenerTestCase {
EntityManager em;
- public TestQueryCache(String name) {
- super(name, "");
- System.setProperty("cactus.contextURL",
- "http://localhost:9000/cachecactus");
- em = currentEntityManager();
- }
-
- /*public static Test suite()
- {
- ServletTestSuite suite = new ServletTestSuite();
- suite.addTestSuite(TestQueryCache.class);
- return suite;
- }*/
public void setUp() {
- System.setProperty("cactus.contextURL",
- "http://localhost:9000/cactuswebapp");
-
- //deleteAll(Entity2.class);
- deleteAll(Entity1.class);
-
- int instNum = 10;
-
- startTx(em);
-
+ super.setUp(
+ DROP_TABLES,
+ "openjpa.QueryCache", "true",
+ "openjpa.RemoteCommitProvider","sjvm",
+ Entity1.class,Entity2.class
+ // ,"openjpa.Log","SQL=trace"
+ );
+ em = emf.createEntityManager();
+
+ em.getTransaction().begin();
//create and persist multiple entity1 instances
- for (int i = 0; i < instNum; i++) {
+ for (int i = 0; i < 10; i++) {
Entity1 ent = new Entity1(i, "string" + i, i + 2);
Entity2 ent2 = new Entity2(i * 2, "ent2" + i, i);
ent.setEntity2Field(ent2);
em.persist(ent);
}
-
- endTx(em);
- endEm(em);
+ em.getTransaction().commit();
}
+ public void testCachedQuery(){
+ em.createQuery("Select object(o) from Entity1
o").getResultList().get(0);
+ resetSQL();
+ em.createQuery("Select object(o) from Entity1
o").getResultList().get(0);
+ em.createQuery("Select object(o) from Entity1
o").getResultList().get(0);
+
+ assertEquals(0, getSQLCount());
+
+ }
public void testResultList() {
- em = currentEntityManager();
List list = em.createQuery("Select object(o) from Entity1 o")
.getResultList();
assertEquals(10, list.size());
- endEm(em);
}
public void testGetSingleList() {
- em = currentEntityManager();
+
String curr = 2 + "";
Entity1 ret = (Entity1) em
- .createQuery("SELECT o FROM Entity1 o WHERE o.pk LIKE :pk")
- .setParameter("pk", curr)
+ .createQuery("SELECT o FROM Entity1 o WHERE o.pk = :pk")
+ .setParameter("pk", Long.valueOf(curr))
.getSingleResult();
assertNotNull(ret);
assertEquals("string2", ret.getStringField());
assertEquals(4, ret.getIntField());
- endEm(em);
+
}
public void testExecuteUpdate() {
String curr = 2 + "";
String curr2 = 22 + "";
- em = currentEntityManager();
+
startTx(em);
Entity1 entity1 = (Entity1) em
- .createQuery("SELECT o FROM Entity1 o WHERE o.pk LIKE :pk")
- .setParameter("pk", curr)
+ .createQuery("SELECT o FROM Entity1 o WHERE o.pk = :pk")
+ .setParameter("pk", Long.valueOf(curr))
.getSingleResult();
- int ret = em.createQuery("Delete FROM Entity1 o WHERE o.pk LIKE :pk")
- .setParameter("pk", curr)
+ int ret = em.createQuery("Delete FROM Entity1 o WHERE o.pk = :pk")
+ .setParameter("pk", Long.valueOf(curr))
.executeUpdate();
assertEquals(ret, 1);
// cascade remove doesn't remove the entity2
- int retTmp = em.createQuery("Delete FROM Entity2 o WHERE o.pk LIKE
:pk")
+ int retTmp = em.createQuery("Delete FROM Entity2 o WHERE o.pk = :pk")
.setParameter("pk", entity1.getEntity2Field().getPk())
.executeUpdate();
- int ret2 = em.createQuery("Delete FROM Entity1 o WHERE o.pk LIKE :pk")
- .setParameter("pk", curr2)
+ int ret2 = em.createQuery("Delete FROM Entity1 o WHERE o.pk = :pk")
+ .setParameter("pk", Long.valueOf(curr2))
.executeUpdate();
assertEquals(ret2, 0);
endTx(em);
- endEm(em);
+
}
public void testSetMaxResults() {
- em = currentEntityManager();
+
List l = em.createQuery("Select object(o) from Entity1 o")
.setMaxResults(5)
@@ -137,11 +129,11 @@ public class TestQueryCache extends Abst
assertNotNull(l);
assertEquals(5, l.size());
- endEm(em);
+
}
public void testSetFirstResults() {
- em = currentEntityManager();
+
List l = em.createQuery("Select object(o) from Entity1 o")
.setFirstResult(3)
@@ -153,37 +145,23 @@ public class TestQueryCache extends Abst
assertEquals("string3", ent.getStringField());
assertEquals(5, ent.getIntField());
- endEm(em);
- }
-
- // Tests Binding an argument to a named parameter.
- // pk, the named parameter --Not working yet--
- public void xxxtestSetParameter1() {
-
- em = currentEntityManager();
- String curr = 2 + "";
-
- List ret = em.createQuery("SELECT o FROM Entity1 o WHERE o.pk LIKE
:pk")
- .setParameter("pk", curr)
- .getResultList();
-
- assertNotNull(ret);
- assertEquals(1, ret.size());
- ret = em.createNamedQuery("setParam1")
- .setParameter("pk", curr)
- .getResultList();
-
- assertNotNull(ret);
- assertEquals(1, ret.size());
+ }
- endTx(em);
+ protected void startTx(EntityManager em) {
+ em.getTransaction().begin();
}
-
- @Override
- public String getPersistenceUnitName() {
- return "QueryCache";
+
+ protected boolean isActiveTx(EntityManager em) {
+ return em.getTransaction().isActive();
}
- //rest of the interface is tested by the CTS
+ protected void endTx(EntityManager em) {
+ if (em.getTransaction().isActive()) {
+ if (em.getTransaction().getRollbackOnly())
+ em.getTransaction().rollback();
+ else
+ em.getTransaction().commit();
+ }
+ }
}
Added:
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/PPerson.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/PPerson.java?rev=929266&view=auto
==============================================================================
---
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/PPerson.java
(added)
+++
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/PPerson.java
Tue Mar 30 20:42:29 2010
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+ package org.apache.openjpa.persistence.relations;
+
+import java.util.Collection;
+
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.ManyToMany;
+
+...@entity
+public class PPerson {
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private int id;
+
+ private String name;
+
+ @ManyToMany(fetch=FetchType.EAGER, mappedBy="people")
+ private Collection<PPhone> phones;
+
+ public int getId() {
+ return id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Collection<PPhone> getPhones() {
+ return phones;
+ }
+
+ public void setPhones(Collection<PPhone> phones) {
+ this.phones = phones;
+ }
+
+ @Override
+ public String toString() {
+ return "Person [id=" + id + ", number=" + name + "]";
+ }
+
+
+}
Propchange:
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/PPerson.java
------------------------------------------------------------------------------
svn:eol-style = native
Added:
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/PPhone.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/PPhone.java?rev=929266&view=auto
==============================================================================
---
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/PPhone.java
(added)
+++
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/PPhone.java
Tue Mar 30 20:42:29 2010
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+ package org.apache.openjpa.persistence.relations;
+
+import java.util.Collection;
+
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.ManyToMany;
+
+...@entity
+public class PPhone {
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private int id;
+
+ private String number;
+
+ @ManyToMany(fetch=FetchType.EAGER)
+ private Collection<PPerson> people;
+
+ public int getId() {
+ return id;
+ }
+
+ public String getNumber() {
+ return number;
+ }
+
+ public void setNumber(String number) {
+ this.number = number;
+ }
+
+ public Collection<PPerson> getPeople() {
+ return people;
+ }
+
+ public void setPeople(Collection<PPerson> people) {
+ this.people = people;
+ }
+
+ @Override
+ public String toString() {
+ return "Phone [id=" + id + ", number=" + number + "]";
+ }
+}
Propchange:
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/PPhone.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified:
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/TestInverseEagerSQL.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/TestInverseEagerSQL.java?rev=929266&r1=929265&r2=929266&view=diff
==============================================================================
---
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/TestInverseEagerSQL.java
(original)
+++
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/TestInverseEagerSQL.java
Tue Mar 30 20:42:29 2010
@@ -18,6 +18,7 @@
*/
package org.apache.openjpa.persistence.relations;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
@@ -41,13 +42,18 @@ public class TestInverseEagerSQL
public int numCustomers = 1;
public int numOrdersPerCustomer = 4;
+
+ public int _nPeople = 3;
+ public int _nPhones = 3;
public void setUp() {
setUp(Customer.class, Customer.CustomerKey.class, Order.class,
EntityAInverseEager.class, EntityA1InverseEager.class,
EntityA2InverseEager.class, EntityBInverseEager.class,
EntityCInverseEager.class, EntityDInverseEager.class,
- Publisher.class, Magazine.class, DROP_TABLES);
+ Publisher.class, Magazine.class,
+ PPerson.class, PPhone.class,
+ DROP_TABLES);
// Not all databases support GenerationType.IDENTITY column(s)
if (!((JDBCConfiguration) emf.getConfiguration()).
@@ -132,6 +138,21 @@ public class TestInverseEagerSQL
magazine.setName("magagine"+i+"_"+p2.getName());
em.persist(magazine);
}
+
+ PPerson person;
+ PPhone phone;
+ for(int i =0; i < _nPeople; i++) {
+ person = new PPerson();
+ person.setPhones(new ArrayList<PPhone>());
+ em.persist(person);
+ for(int j = 0; j < _nPhones; j++) {
+ phone = new PPhone();
+ phone.setPeople(new ArrayList<PPerson>());
+ phone.getPeople().add(person);
+ person.getPhones().add(phone);
+ em.persist(phone);
+ }
+ }
em.flush();
em.getTransaction().commit();
@@ -255,8 +276,8 @@ public class TestInverseEagerSQL
// Not all databases support GenerationType.IDENTITY column(s)
if (!((JDBCConfiguration) emf.getConfiguration()).
getDBDictionaryInstance().supportsAutoAssign) {
- return;
- }
+ return;
+ }
sql.clear();
OpenJPAEntityManager em = emf.createEntityManager();
@@ -282,6 +303,36 @@ public class TestInverseEagerSQL
assertEquals(0, sql.size());
em.close();
}
+
+ public void testManyToManyEagerEagerInverseLazyQuery() {
+ // Not all databases support GenerationType.IDENTITY column(s)
+ if (!((JDBCConfiguration) emf.getConfiguration()).
+ getDBDictionaryInstance().supportsAutoAssign) {
+ return;
+ }
+ sql.clear();
+
+ OpenJPAEntityManager em = emf.createEntityManager();
+ String query = "select p FROM PPerson p";
+ Query q = em.createQuery(query);
+ List list = q.getResultList();
+ assertEquals(_nPeople, list.size());
+ assertEquals(7, sql.size());
+
+ sql.clear();
+ em.clear();
+ for (int i = 0; i < list.size(); i++) {
+ PPerson p = (PPerson) list.get(i);
+ Collection<PPhone> phones = p.getPhones();
+ assertEquals(_nPhones, phones.size());
+ for(PPhone phone : p.getPhones()) {
+ assertNotNull(phone.getPeople());
+ assertTrue(phone.getPeople().contains(p));
+ }
+ }
+ assertEquals(0, sql.size());
+ em.close();
+ }
public void testTargetOrphanRemoval() {
// Not all databases support GenerationType.IDENTITY column(s)
Modified:
openjpa/trunk/openjpa-xmlstore/src/main/java/org/apache/openjpa/xmlstore/XMLStoreManager.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-xmlstore/src/main/java/org/apache/openjpa/xmlstore/XMLStoreManager.java?rev=929266&r1=929265&r2=929266&view=diff
==============================================================================
---
openjpa/trunk/openjpa-xmlstore/src/main/java/org/apache/openjpa/xmlstore/XMLStoreManager.java
(original)
+++
openjpa/trunk/openjpa-xmlstore/src/main/java/org/apache/openjpa/xmlstore/XMLStoreManager.java
Tue Mar 30 20:42:29 2010
@@ -283,4 +283,8 @@ public class XMLStoreManager
}
return new ListResultObjectProvider(pcs);
}
+ public boolean isCached(List<Object> oids, BitSet edata) {
+ // XMLStoreManager does not cache oids.
+ return false;
+ }
}