mirror of
https://github.com/apache/openjpa.git
synced 2025-02-21 01:15:30 +00:00
OPENJPA-1271:
Enable CacheStoreMode and CacheRetrieveMode properties to be set for an EntityManager. git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@808981 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
78e93abb51
commit
991cdcae7d
@ -30,6 +30,8 @@ import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.apache.openjpa.enhance.PCDataGenerator;
|
||||
import org.apache.openjpa.kernel.DataCacheRetrieveMode;
|
||||
import org.apache.openjpa.kernel.DataCacheStoreMode;
|
||||
import org.apache.openjpa.kernel.DelegatingStoreManager;
|
||||
import org.apache.openjpa.kernel.FetchConfiguration;
|
||||
import org.apache.openjpa.kernel.LockLevels;
|
||||
@ -54,9 +56,9 @@ public class DataCacheStoreManager
|
||||
extends DelegatingStoreManager {
|
||||
|
||||
// all the state managers changed in this transaction
|
||||
private Collection _inserts = null; // statemanagers
|
||||
private Map _updates = null; // statemanager -> fmd set
|
||||
private Collection _deletes = null; // statemanagers
|
||||
private Collection<OpenJPAStateManager> _inserts = null;
|
||||
private Map<OpenJPAStateManager, BitSet> _updates = null;
|
||||
private Collection<OpenJPAStateManager> _deletes = null;
|
||||
|
||||
// the owning context
|
||||
private StoreContext _ctx = null;
|
||||
@ -130,127 +132,125 @@ public class DataCacheStoreManager
|
||||
* Update all caches with the committed inserts, updates, and deletes.
|
||||
*/
|
||||
private void updateCaches() {
|
||||
// map each data cache to the modifications we need to perform
|
||||
Map modMap = null;
|
||||
Modifications mods;
|
||||
OpenJPAStateManager sm;
|
||||
DataCachePCData data;
|
||||
DataCache cache;
|
||||
if(_ctx.getCacheStoreMode() != DataCacheStoreMode.BYPASS ) {
|
||||
// map each data cache to the modifications we need to perform
|
||||
Map modMap = null;
|
||||
Modifications mods;
|
||||
DataCachePCData data;
|
||||
DataCache cache;
|
||||
|
||||
// create pc datas for inserts
|
||||
if (_ctx.getPopulateDataCache() && _inserts != null) {
|
||||
for (Iterator itr = _inserts.iterator(); itr.hasNext();) {
|
||||
sm = (OpenJPAStateManager) itr.next();
|
||||
cache = sm.getMetaData().getDataCache();
|
||||
if (cache == null)
|
||||
continue;
|
||||
// create pc datas for inserts
|
||||
if (_ctx.getPopulateDataCache() && _inserts != null) {
|
||||
for(OpenJPAStateManager sm : _inserts) {
|
||||
cache = sm.getMetaData().getDataCache();
|
||||
if (cache == null)
|
||||
continue;
|
||||
|
||||
if (modMap == null)
|
||||
modMap = new HashMap();
|
||||
mods = getModifications(modMap, cache);
|
||||
data = newPCData(sm);
|
||||
data.store(sm);
|
||||
mods.additions.add(new PCDataHolder(data, sm));
|
||||
}
|
||||
}
|
||||
|
||||
// update pcdatas for updates
|
||||
Map.Entry entry;
|
||||
if (_updates != null) {
|
||||
BitSet fields;
|
||||
for (Iterator itr = _updates.entrySet().iterator();
|
||||
itr.hasNext();) {
|
||||
entry = (Map.Entry) itr.next();
|
||||
sm = (OpenJPAStateManager) entry.getKey();
|
||||
fields = (BitSet) entry.getValue();
|
||||
|
||||
cache = sm.getMetaData().getDataCache();
|
||||
if (cache == null)
|
||||
continue;
|
||||
|
||||
// it's ok not to clone the object that we get from the cache,
|
||||
// since we're inside the commit() method, so any modifications
|
||||
// to the underlying cache are valid. If the commit had not
|
||||
// already succeeded, then we'd want to clone the retrieved
|
||||
// object.
|
||||
if (modMap == null)
|
||||
modMap = new HashMap();
|
||||
data = cache.get(sm.getObjectId());
|
||||
mods = getModifications(modMap, cache);
|
||||
|
||||
// data should always be non-null, since the object is
|
||||
// dirty, but maybe it got dropped from the cache in the
|
||||
// interim
|
||||
if (data == null) {
|
||||
if (modMap == null)
|
||||
modMap = new HashMap();
|
||||
mods = getModifications(modMap, cache);
|
||||
data = newPCData(sm);
|
||||
data.store(sm);
|
||||
mods.newUpdates.add(new PCDataHolder(data, sm));
|
||||
} else {
|
||||
data.store(sm, fields);
|
||||
mods.existingUpdates.add(new PCDataHolder(data, sm));
|
||||
mods.additions.add(new PCDataHolder(data, sm));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// remove pcdatas for deletes
|
||||
if (_deletes != null) {
|
||||
for (Iterator itr = _deletes.iterator(); itr.hasNext();) {
|
||||
sm = (OpenJPAStateManager) itr.next();
|
||||
cache = sm.getMetaData().getDataCache();
|
||||
if (cache == null)
|
||||
continue;
|
||||
// update pcdatas for updates
|
||||
if (_updates != null) {
|
||||
BitSet fields;
|
||||
OpenJPAStateManager sm;
|
||||
for(Map.Entry<OpenJPAStateManager, BitSet> entry : _updates.entrySet()) {
|
||||
sm = entry.getKey();
|
||||
fields = entry.getValue();
|
||||
|
||||
if (modMap == null)
|
||||
modMap = new HashMap();
|
||||
mods = getModifications(modMap, cache);
|
||||
mods.deletes.add(sm.getObjectId());
|
||||
}
|
||||
}
|
||||
cache = sm.getMetaData().getDataCache();
|
||||
if (cache == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// notify the caches of the changes
|
||||
if (modMap != null) {
|
||||
for (Iterator itr = modMap.entrySet().iterator(); itr.hasNext();) {
|
||||
entry = (Map.Entry) itr.next();
|
||||
cache = (DataCache) entry.getKey();
|
||||
mods = (Modifications) entry.getValue();
|
||||
// it's ok not to clone the object that we get from the cache,
|
||||
// since we're inside the commit() method, so any modifications
|
||||
// to the underlying cache are valid. If the commit had not
|
||||
// already succeeded, then we'd want to clone the retrieved
|
||||
// object.
|
||||
if (modMap == null)
|
||||
modMap = new HashMap();
|
||||
data = cache.get(sm.getObjectId());
|
||||
mods = getModifications(modMap, cache);
|
||||
|
||||
// make sure we're not caching old versions
|
||||
cache.writeLock();
|
||||
try {
|
||||
transformToVersionSafePCDatas(cache, mods.additions);
|
||||
transformToVersionSafePCDatas(cache, mods.newUpdates);
|
||||
transformToVersionSafePCDatas(cache, mods.existingUpdates);
|
||||
cache.commit(mods.additions, mods.newUpdates,
|
||||
mods.existingUpdates, mods.deletes);
|
||||
} finally {
|
||||
cache.writeUnlock();
|
||||
// data should always be non-null, since the object is
|
||||
// dirty, but maybe it got dropped from the cache in the
|
||||
// interim
|
||||
if (data == null) {
|
||||
data = newPCData(sm);
|
||||
data.store(sm);
|
||||
mods.newUpdates.add(new PCDataHolder(data, sm));
|
||||
} else {
|
||||
data.store(sm, fields);
|
||||
mods.existingUpdates.add(new PCDataHolder(data, sm));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if we were in largeTransaction mode, then we have recorded
|
||||
// the classes of updated/deleted objects and these now need to be
|
||||
// evicted
|
||||
if (_ctx.isTrackChangesByType()) {
|
||||
evictTypes(_ctx.getDeletedTypes());
|
||||
evictTypes(_ctx.getUpdatedTypes());
|
||||
}
|
||||
// remove pcdatas for deletes
|
||||
if (_deletes != null) {
|
||||
for(OpenJPAStateManager sm : _deletes) {
|
||||
cache = sm.getMetaData().getDataCache();
|
||||
if (cache == null)
|
||||
continue;
|
||||
|
||||
// and notify the query cache. notify in one batch to reduce synch
|
||||
QueryCache queryCache = _ctx.getConfiguration().
|
||||
if (modMap == null)
|
||||
modMap = new HashMap();
|
||||
mods = getModifications(modMap, cache);
|
||||
mods.deletes.add(sm.getObjectId());
|
||||
}
|
||||
}
|
||||
|
||||
// notify the caches of the changes
|
||||
if (modMap != null) {
|
||||
for (Iterator itr = modMap.entrySet().iterator(); itr.hasNext();) {
|
||||
Map.Entry entry = (Map.Entry) itr.next();
|
||||
cache = (DataCache) entry.getKey();
|
||||
mods = (Modifications) entry.getValue();
|
||||
|
||||
// make sure we're not caching old versions
|
||||
cache.writeLock();
|
||||
try {
|
||||
transformToVersionSafePCDatas(cache, mods.additions);
|
||||
transformToVersionSafePCDatas(cache, mods.newUpdates);
|
||||
transformToVersionSafePCDatas(cache, mods.existingUpdates);
|
||||
cache.commit(mods.additions, mods.newUpdates,
|
||||
mods.existingUpdates, mods.deletes);
|
||||
} finally {
|
||||
cache.writeUnlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if we were in largeTransaction mode, then we have recorded
|
||||
// the classes of updated/deleted objects and these now need to be
|
||||
// evicted
|
||||
if (_ctx.isTrackChangesByType()) {
|
||||
evictTypes(_ctx.getDeletedTypes());
|
||||
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 pers = _ctx.getPersistedTypes();
|
||||
Collection del = _ctx.getDeletedTypes();
|
||||
Collection up = _ctx.getUpdatedTypes();
|
||||
int size = pers.size() + del.size() + up.size();
|
||||
if (size > 0) {
|
||||
Collection types = new ArrayList(size);
|
||||
types.addAll(pers);
|
||||
types.addAll(del);
|
||||
types.addAll(up);
|
||||
queryCache.onTypesChanged(new TypesChangedEvent(this, types));
|
||||
}
|
||||
if (queryCache != null) {
|
||||
Collection pers = _ctx.getPersistedTypes();
|
||||
Collection del = _ctx.getDeletedTypes();
|
||||
Collection up = _ctx.getUpdatedTypes();
|
||||
int size = pers.size() + del.size() + up.size();
|
||||
if (size > 0) {
|
||||
Collection types = new ArrayList(size);
|
||||
types.addAll(pers);
|
||||
types.addAll(del);
|
||||
types.addAll(up);
|
||||
queryCache.onTypesChanged(new TypesChangedEvent(this, types));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -333,52 +333,74 @@ public class DataCacheStoreManager
|
||||
return super.syncVersion(sm, edata);
|
||||
}
|
||||
|
||||
public boolean initialize(OpenJPAStateManager sm, PCState state,
|
||||
FetchConfiguration fetch, Object edata) {
|
||||
public boolean initialize(OpenJPAStateManager sm, PCState state, FetchConfiguration fetch, Object edata) {
|
||||
boolean rval;
|
||||
DataCache cache = sm.getMetaData().getDataCache();
|
||||
if (cache == null || sm.isEmbedded())
|
||||
return super.initialize(sm, state, fetch, edata);
|
||||
|
||||
DataCachePCData data = cache.get(sm.getObjectId());
|
||||
if (data != null && !isLocking(fetch)) {
|
||||
//### the 'data.type' access here probably needs to be
|
||||
//### addressed for bug 511
|
||||
sm.initialize(data.getType(), state);
|
||||
data.load(sm, fetch, edata);
|
||||
return true;
|
||||
if (cache == null || sm.isEmbedded() || _ctx.getCacheRetrieveMode() == DataCacheRetrieveMode.BYPASS
|
||||
|| _ctx.getCacheStoreMode() == DataCacheStoreMode.REFRESH) {
|
||||
// save the return value and return later in case we need to update the cache)
|
||||
rval = super.initialize(sm, state, fetch, edata);
|
||||
}
|
||||
|
||||
// initialize from store manager
|
||||
if (!super.initialize(sm, state, fetch, edata))
|
||||
return false;
|
||||
if (!_ctx.getPopulateDataCache())
|
||||
return true;
|
||||
else {
|
||||
DataCachePCData data = cache.get(sm.getObjectId());
|
||||
if (data != null && !isLocking(fetch)) {
|
||||
//### the 'data.type' access here probably needs to be
|
||||
//### addressed for bug 511
|
||||
sm.initialize(data.getType(), state);
|
||||
data.load(sm, fetch, edata);
|
||||
return true;
|
||||
}
|
||||
|
||||
// initialize from store manager
|
||||
if (!super.initialize(sm, state, fetch, edata)) {
|
||||
return false;
|
||||
}
|
||||
rval = true; // same as rval = super.initialize(...)
|
||||
}
|
||||
|
||||
// update the cache if configured appropriately.
|
||||
if (_ctx.getCacheStoreMode() == DataCacheStoreMode.REFRESH && _ctx.getPopulateDataCache()) {
|
||||
cacheStateManager(cache, sm);
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
private void cacheStateManager(DataCache cache, OpenJPAStateManager sm) {
|
||||
if(sm.isFlushed()) {
|
||||
return;
|
||||
}
|
||||
// make sure that we're not trying to cache an old version
|
||||
cache.writeLock();
|
||||
try {
|
||||
data = cache.get(sm.getObjectId());
|
||||
if (data != null && compareVersion(sm, sm.getVersion(),
|
||||
data.getVersion()) == VERSION_EARLIER)
|
||||
return true;
|
||||
DataCachePCData data = cache.get(sm.getObjectId());
|
||||
if (data != null && compareVersion(sm, sm.getVersion(), data.getVersion()) == VERSION_EARLIER) {
|
||||
return;
|
||||
}
|
||||
|
||||
// cache newly loaded info. It is safe to cache data frorm
|
||||
// initialize() because this method is only called upon
|
||||
// initial load of the data.
|
||||
if (data == null)
|
||||
boolean isNew = data == null;
|
||||
if (isNew) {
|
||||
data = newPCData(sm);
|
||||
}
|
||||
data.store(sm);
|
||||
cache.put(data);
|
||||
if(isNew) {
|
||||
cache.put(data);
|
||||
}
|
||||
else {
|
||||
cache.update(data);
|
||||
}
|
||||
} finally {
|
||||
cache.writeUnlock();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean load(OpenJPAStateManager sm, BitSet fields,
|
||||
FetchConfiguration fetch, int lockLevel, Object edata) {
|
||||
DataCache cache = sm.getMetaData().getDataCache();
|
||||
if (cache == null || sm.isEmbedded())
|
||||
if (cache == null || sm.isEmbedded() || _ctx.getCacheRetrieveMode() == DataCacheRetrieveMode.BYPASS)
|
||||
return super.load(sm, fields, fetch, lockLevel, edata);
|
||||
|
||||
DataCachePCData data = cache.get(sm.getObjectId());
|
||||
@ -392,33 +414,11 @@ public class DataCacheStoreManager
|
||||
// so that if the store manager decides to modify it it won't affect us
|
||||
if (!super.load(sm, (BitSet) fields.clone(), fetch, lockLevel, edata))
|
||||
return false;
|
||||
if (!_ctx.getPopulateDataCache())
|
||||
return true;
|
||||
// Do not load changes into cache if the instance has been flushed
|
||||
if (sm.isFlushed())
|
||||
return true;
|
||||
|
||||
// make sure that we're not trying to cache an old version
|
||||
cache.writeLock();
|
||||
try {
|
||||
data = cache.get(sm.getObjectId());
|
||||
if (data != null && compareVersion(sm, sm.getVersion(),
|
||||
data.getVersion()) == VERSION_EARLIER)
|
||||
return true;
|
||||
|
||||
// cache newly loaded info
|
||||
boolean isNew = data == null;
|
||||
if (isNew)
|
||||
data = newPCData(sm);
|
||||
data.store(sm, fields);
|
||||
if (isNew)
|
||||
cache.put(data);
|
||||
else
|
||||
cache.update(data);
|
||||
} finally {
|
||||
cache.writeUnlock();
|
||||
if (_ctx.getPopulateDataCache()) {
|
||||
cacheStateManager(cache, sm);
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
public Collection loadAll(Collection sms, PCState state, int load,
|
||||
@ -430,7 +430,7 @@ public class DataCacheStoreManager
|
||||
return super.loadAll(sms, state, load, fetch, edata);
|
||||
}
|
||||
|
||||
Map unloaded = null;
|
||||
Map<OpenJPAStateManager, BitSet> unloaded = null;
|
||||
List smList = null;
|
||||
Map caches = new HashMap();
|
||||
OpenJPAStateManager sm;
|
||||
@ -509,12 +509,12 @@ public class DataCacheStoreManager
|
||||
return failed;
|
||||
|
||||
// for each loaded instance, merge loaded state into cached data
|
||||
Map.Entry entry;
|
||||
|
||||
boolean isNew;
|
||||
for (Iterator itr = unloaded.entrySet().iterator(); itr.hasNext();) {
|
||||
entry = (Map.Entry) itr.next();
|
||||
sm = (OpenJPAStateManager) entry.getKey();
|
||||
fields = (BitSet) entry.getValue();
|
||||
|
||||
for(Map.Entry<OpenJPAStateManager, BitSet> entry : unloaded.entrySet()) {
|
||||
sm = entry.getKey();
|
||||
fields = entry.getValue();
|
||||
|
||||
cache = sm.getMetaData().getDataCache();
|
||||
if (cache == null || sm.isEmbedded() || (failed != null
|
||||
@ -550,10 +550,10 @@ public class DataCacheStoreManager
|
||||
/**
|
||||
* Helper method to add an unloaded instance to the given map.
|
||||
*/
|
||||
private static Map addUnloaded(OpenJPAStateManager sm, BitSet fields,
|
||||
Map unloaded) {
|
||||
private static Map<OpenJPAStateManager, BitSet> addUnloaded(OpenJPAStateManager sm, BitSet fields,
|
||||
Map<OpenJPAStateManager, BitSet> unloaded) {
|
||||
if (unloaded == null)
|
||||
unloaded = new HashMap();
|
||||
unloaded = new HashMap<OpenJPAStateManager, BitSet>();
|
||||
unloaded.put(sm, fields);
|
||||
return unloaded;
|
||||
}
|
||||
@ -580,24 +580,29 @@ public class DataCacheStoreManager
|
||||
sm = (OpenJPAStateManager) itr.next();
|
||||
|
||||
if (sm.getPCState() == PCState.PNEW && !sm.isFlushed()) {
|
||||
if (_inserts == null)
|
||||
_inserts = new ArrayList();
|
||||
if (_inserts == null) {
|
||||
_inserts = new ArrayList<OpenJPAStateManager>();
|
||||
}
|
||||
_inserts.add(sm);
|
||||
|
||||
// may have been re-persisted
|
||||
if (_deletes != null)
|
||||
_deletes.remove(sm);
|
||||
if (_deletes != null) {
|
||||
_deletes.remove(sm);
|
||||
}
|
||||
} else if (_inserts != null
|
||||
&& (sm.getPCState() == PCState.PNEWDELETED
|
||||
|| sm.getPCState() == PCState.PNEWFLUSHEDDELETED))
|
||||
|| sm.getPCState() == PCState.PNEWFLUSHEDDELETED)) {
|
||||
_inserts.remove(sm);
|
||||
}
|
||||
else if (sm.getPCState() == PCState.PDIRTY) {
|
||||
if (_updates == null)
|
||||
_updates = new HashMap();
|
||||
if (_updates == null) {
|
||||
_updates = new HashMap<OpenJPAStateManager, BitSet>();
|
||||
}
|
||||
_updates.put(sm, sm.getDirty());
|
||||
} else if (sm.getPCState() == PCState.PDELETED) {
|
||||
if (_deletes == null)
|
||||
_deletes = new HashSet();
|
||||
if (_deletes == null) {
|
||||
_deletes = new HashSet<OpenJPAStateManager>();
|
||||
}
|
||||
_deletes.add(sm);
|
||||
}
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
@ -229,6 +230,12 @@ public class BrokerImpl
|
||||
private boolean _cachePreparedQuery = true;
|
||||
private boolean _cacheFinderQuery = true;
|
||||
|
||||
private DataCacheStoreMode _cacheStoreMode;
|
||||
private DataCacheRetrieveMode _cacheRetrieveMode;
|
||||
|
||||
// Store and Retrieve mode may be suspended for a given operation. Stack may be overkill here.
|
||||
private Stack<DataCacheStoreMode> _cacheStoreModeStack = new Stack<DataCacheStoreMode>();
|
||||
private Stack<DataCacheRetrieveMode> _cacheRetrieveModeStack = new Stack<DataCacheRetrieveMode>();
|
||||
|
||||
// Map of properties whose values have been changed
|
||||
// private Map<String, String> _changedProperties =
|
||||
@ -4894,4 +4901,40 @@ public class BrokerImpl
|
||||
unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataCacheRetrieveMode getCacheRetrieveMode() {
|
||||
return _cacheRetrieveMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataCacheStoreMode getCacheStoreMode() {
|
||||
return _cacheStoreMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCacheRetrieveMode(DataCacheRetrieveMode mode) {
|
||||
_cacheRetrieveMode = mode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCacheStoreMode(DataCacheStoreMode mode) {
|
||||
_cacheStoreMode = mode;
|
||||
}
|
||||
|
||||
public void popCacheRetrieveMode() {
|
||||
_cacheRetrieveMode = _cacheRetrieveModeStack.pop();
|
||||
}
|
||||
|
||||
public void popCacheStoreMode() {
|
||||
_cacheStoreMode = _cacheStoreModeStack.pop();
|
||||
}
|
||||
|
||||
public void pushCacheRetrieveMode() {
|
||||
_cacheRetrieveModeStack.push(_cacheRetrieveMode);
|
||||
}
|
||||
|
||||
public void pushCacheStoreMode() {
|
||||
_cacheStoreModeStack.push(_cacheStoreMode);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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.kernel;
|
||||
|
||||
/**
|
||||
* DataCache Retrieve Modes.
|
||||
*/
|
||||
public enum DataCacheRetrieveMode {
|
||||
/**
|
||||
* Retrieve objects from the DataCache if a DataCache is enabled.
|
||||
*/
|
||||
USE,
|
||||
/**
|
||||
* Ignore the DataCache and fetch data directly from the database.
|
||||
*/
|
||||
BYPASS,
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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.kernel;
|
||||
|
||||
/**
|
||||
* DataCache Store modes
|
||||
*/
|
||||
public enum DataCacheStoreMode {
|
||||
|
||||
/**
|
||||
* Store updates, inserts and deletes in the DataCache. The DataCache will
|
||||
* not be refreshed when data is read from the database.
|
||||
*/
|
||||
USE,
|
||||
/**
|
||||
* Write updates, inserts and deletes directly to the database. The
|
||||
* DataCache will not be aware of these changes and may need to be
|
||||
* refreshed.
|
||||
*/
|
||||
BYPASS,
|
||||
/**
|
||||
* Store updates, inserts and deletes in the DataCache. Entities which are
|
||||
* read from the database will be refreshed in the DataCache.
|
||||
*/
|
||||
REFRESH
|
||||
}
|
@ -1411,4 +1411,39 @@ public class DelegatingBroker
|
||||
_broker.setCachePreparedQuery(flag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataCacheRetrieveMode getCacheRetrieveMode() {
|
||||
return _broker.getCacheRetrieveMode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataCacheStoreMode getCacheStoreMode() {
|
||||
return _broker.getCacheStoreMode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCacheRetrieveMode(DataCacheRetrieveMode mode) {
|
||||
_broker.setCacheRetrieveMode(mode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCacheStoreMode(DataCacheStoreMode mode) {
|
||||
_broker.setCacheStoreMode(mode);
|
||||
}
|
||||
|
||||
public void popCacheRetrieveMode() {
|
||||
_broker.popCacheRetrieveMode();
|
||||
}
|
||||
|
||||
public void popCacheStoreMode() {
|
||||
_broker.popCacheStoreMode();
|
||||
}
|
||||
|
||||
public void pushCacheRetrieveMode() {
|
||||
_broker.pushCacheRetrieveMode();
|
||||
}
|
||||
|
||||
public void pushCacheStoreMode() {
|
||||
_broker.pushCacheStoreMode();
|
||||
}
|
||||
}
|
||||
|
@ -458,4 +458,61 @@ public interface StoreContext {
|
||||
* Releases the internal lock.
|
||||
*/
|
||||
public void unlock ();
|
||||
|
||||
/**
|
||||
* Return the current DataCacheStoreMode for this context. The
|
||||
* DataCacheStoreMode controls when entities are added / updated in the
|
||||
* DataCache.
|
||||
*
|
||||
* @return DataCacheStore mode in use
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public DataCacheStoreMode getCacheStoreMode();
|
||||
|
||||
/**
|
||||
* Set DataCacheStoreMode
|
||||
* @param mode The new DataCacheStoreMode
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public void setCacheStoreMode(DataCacheStoreMode mode);
|
||||
|
||||
/**
|
||||
* Return the current DataCacheRetrieveMode (controls whether objects will
|
||||
* be loaded from the DataCache or direct from the database).
|
||||
*
|
||||
* @return DataCacheRetrieveMode in use.
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public DataCacheRetrieveMode getCacheRetrieveMode();
|
||||
|
||||
/**
|
||||
* Set DataCacheRetrieveMode
|
||||
* @param mode new mode for obtaining data from the cache
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public void setCacheRetrieveMode(DataCacheRetrieveMode mode);
|
||||
|
||||
/**
|
||||
* Pop the DataCacheRetrieveMode stack
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public void popCacheRetrieveMode();
|
||||
|
||||
/**
|
||||
* Pop the DataCacheStoreMode stack.
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public void popCacheStoreMode() ;
|
||||
|
||||
/**
|
||||
* Push the current DataCacheRetrieveMode onto a saved stack.
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public void pushCacheRetrieveMode() ;
|
||||
|
||||
/**
|
||||
* Push the current DataCacheStoreMode onto a saved stack.
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public void pushCacheStoreMode();
|
||||
}
|
||||
|
@ -0,0 +1,396 @@
|
||||
/*
|
||||
* 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.cache.jpa;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.Cache;
|
||||
import javax.persistence.CacheRetrieveMode;
|
||||
import javax.persistence.CacheStoreMode;
|
||||
import javax.persistence.EntityManager;
|
||||
|
||||
import org.apache.openjpa.lib.jdbc.AbstractJDBCListener;
|
||||
import org.apache.openjpa.lib.jdbc.JDBCEvent;
|
||||
import org.apache.openjpa.persistence.OpenJPAEntityManagerFactorySPI;
|
||||
import org.apache.openjpa.persistence.cache.jpa.model.CacheEntity;
|
||||
import org.apache.openjpa.persistence.cache.jpa.model.CacheableEntity;
|
||||
import org.apache.openjpa.persistence.cache.jpa.model.NegatedCachableEntity;
|
||||
import org.apache.openjpa.persistence.cache.jpa.model.NegatedUncacheableEntity;
|
||||
import org.apache.openjpa.persistence.cache.jpa.model.UncacheableEntity;
|
||||
import org.apache.openjpa.persistence.cache.jpa.model.UnspecifiedEntity;
|
||||
import org.apache.openjpa.persistence.cache.jpa.model.XmlCacheableEntity;
|
||||
import org.apache.openjpa.persistence.cache.jpa.model.XmlUncacheableEntity;
|
||||
|
||||
public abstract class AbstractCacheModeTestCase extends AbstractCacheTestCase {
|
||||
public abstract OpenJPAEntityManagerFactorySPI getEntityManagerFactory();
|
||||
|
||||
public abstract List<String> getSql();
|
||||
|
||||
protected abstract Class<?>[] getExpectedNotInCache();
|
||||
|
||||
protected abstract Class<?>[] getExpectedInCache();
|
||||
|
||||
// =======================================================================
|
||||
// Asserts
|
||||
// =======================================================================
|
||||
/**
|
||||
* Assert whether the cache contains the expected results.
|
||||
*
|
||||
* @param cache
|
||||
* The JPA Cache to verify
|
||||
* @param expectCacheables
|
||||
* Whether entities with @Cacheable(true) should be in the cache
|
||||
* (almost always true)
|
||||
* @param expectUncacheables
|
||||
* Whether entities with @Cacheable(false) should be in the cache
|
||||
* (almost always false)
|
||||
* @param expectUnspecified
|
||||
* Whether entities with no @Cacheable annotation should be in
|
||||
* the cache (varies per config).
|
||||
*/
|
||||
protected void assertCacheContents(Cache cache, boolean expectCacheables, boolean expectUncacheables,
|
||||
boolean expectUnspecified) {
|
||||
assertCacheables(cache, expectCacheables);
|
||||
assertUncacheables(cache, expectUncacheables);
|
||||
assertUnspecified(cache, expectUnspecified);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert whether the cacheable types are in the cache. This method exits on
|
||||
* the first cache 'miss'.
|
||||
*
|
||||
* @param cache
|
||||
* JPA Cache to verify
|
||||
* @param expected
|
||||
* If true the cacheable types should be in the cache, if false
|
||||
* they should not be.
|
||||
*/
|
||||
protected void assertCacheables(Cache cache, boolean expected) {
|
||||
assertCached(cache, CacheableEntity.class, 1, expected);
|
||||
assertCached(cache, NegatedUncacheableEntity.class, 1, expected);
|
||||
assertCached(cache, XmlCacheableEntity.class, 1, expected);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert whether the uncacheable types are in the cache. This method exits
|
||||
* on the first cache 'miss'.
|
||||
*
|
||||
* @param cache
|
||||
* JPA Cache to verify
|
||||
* @param expected
|
||||
* If true the uncacheable types should be in the cache, if false
|
||||
* they should not be.
|
||||
*/
|
||||
protected void assertUncacheables(Cache cache, boolean expected) {
|
||||
assertCached(cache, UncacheableEntity.class, 1, expected);
|
||||
assertCached(cache, XmlUncacheableEntity.class, 1, expected);
|
||||
assertCached(cache, NegatedCachableEntity.class, 1, expected);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert whether the unspecified types are in the cache. This method exits
|
||||
* on the first cache 'miss'.
|
||||
*
|
||||
* @param cache
|
||||
* JPA Cache to verify
|
||||
* @param expected
|
||||
* If true the unspecified types should be in the cache, if false
|
||||
* they should not be.
|
||||
*/
|
||||
protected void assertUnspecified(Cache cache, boolean expected) {
|
||||
assertCached(cache, UnspecifiedEntity.class, 1, expected);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that no sql is executed when running the supplied Action.
|
||||
*
|
||||
* @param act
|
||||
* Action to execute.
|
||||
*/
|
||||
public void assertNoSql(Action act) {
|
||||
assertSqlInc(act, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that <literal>expectedSqls</literal> SQL statements are executed
|
||||
* when running <literal>act</literal>
|
||||
*
|
||||
* @param act
|
||||
* Action to run.
|
||||
* @param expectedSqls
|
||||
* Number of SQL statements that should be executed.
|
||||
*/
|
||||
public void assertSqlInc(Action act, int expectedSqls) {
|
||||
int before = getSql().size();
|
||||
act.run();
|
||||
assertEquals(before + expectedSqls, getSql().size());
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// Utility classes
|
||||
// =======================================================================
|
||||
/**
|
||||
* Basic 'runnable' interface used to run a set of commands, then analyze
|
||||
* the number of SQL statements that result.
|
||||
*/
|
||||
public interface Action {
|
||||
public void run();
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple JDBCListener which stores the executed sql in a List. The List is
|
||||
* provided by the getSql() method so that subclasses may use separate
|
||||
* lists.
|
||||
*
|
||||
* @author mikedd
|
||||
*
|
||||
*/
|
||||
public class Listener extends AbstractJDBCListener {
|
||||
@Override
|
||||
public void beforeExecuteStatement(JDBCEvent event) {
|
||||
if (event.getSQL() != null && getSql() != null) {
|
||||
getSql().add(event.getSQL());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// Test utilities
|
||||
// =======================================================================
|
||||
public boolean getCacheEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// Common test methods.
|
||||
// =======================================================================
|
||||
/**
|
||||
* Ensure that each call the em.find generates an SQL statement when
|
||||
* CacheRetrieveMode.BYPASS is used.
|
||||
*/
|
||||
public void testReadModeByass() {
|
||||
assertSqlInc(new Action() {
|
||||
public void run() {
|
||||
EntityManager em = getEntityManagerFactory().createEntityManager();
|
||||
em.setProperty(RETRIEVE_MODE_PROP, CacheRetrieveMode.BYPASS);
|
||||
for (Class<?> cls : persistentTypes) {
|
||||
em.find(cls, 1);
|
||||
}
|
||||
em.close();
|
||||
}
|
||||
}, persistentTypes.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Ensure that each entity in getExpectedInCache():
|
||||
* <ul>
|
||||
* <li>is in the cache</li>
|
||||
* <li>does not go to the database for a find operation</li>
|
||||
* <li>is not null</li>
|
||||
* </ul>
|
||||
* </p>
|
||||
* <p>
|
||||
* and
|
||||
* </p>
|
||||
* <p>
|
||||
* Ensure that each entity in getExpectedNotInCache() :
|
||||
* <ul>
|
||||
* <li>is not in the cache</li>
|
||||
* <li>results in a single SQL statement when em.find() is called</li>
|
||||
* <li>is not null</li>
|
||||
* </ul>
|
||||
* </p>
|
||||
*
|
||||
*/
|
||||
public void testRetrieveModeUse() {
|
||||
assertNoSql(new Action() {
|
||||
public void run() {
|
||||
EntityManager em = getEntityManagerFactory().createEntityManager();
|
||||
em.setProperty(RETRIEVE_MODE_PROP, CacheRetrieveMode.USE);
|
||||
for (Class<?> cls : getExpectedInCache()) {
|
||||
assertCached(getEntityManagerFactory().getCache(), cls, 1, true);
|
||||
assertNotNull(em.find(cls, 1));
|
||||
}
|
||||
em.close();
|
||||
}
|
||||
});
|
||||
assertSqlInc(new Action() {
|
||||
public void run() {
|
||||
EntityManager em = getEntityManagerFactory().createEntityManager();
|
||||
em.setProperty(RETRIEVE_MODE_PROP, CacheRetrieveMode.USE);
|
||||
for (Class<?> cls : getExpectedNotInCache()) {
|
||||
assertCached(getEntityManagerFactory().getCache(), cls, 1, false);
|
||||
assertNotNull(em.find(cls, 1));
|
||||
}
|
||||
em.close();
|
||||
}
|
||||
}, getExpectedNotInCache().length);
|
||||
}
|
||||
|
||||
public void updateAndFind(Class<? extends CacheEntity> classToUpdate, int idToUpdate,
|
||||
Class<? extends CacheEntity> classToFind, int idToFind,
|
||||
CacheStoreMode storeMode, CacheRetrieveMode retrieveMode) {
|
||||
EntityManager em = getEntityManagerFactory().createEntityManager();
|
||||
|
||||
if (storeMode != null) {
|
||||
em.setProperty(STORE_MODE_PROP, storeMode);
|
||||
}
|
||||
if (retrieveMode != null) {
|
||||
em.setProperty(RETRIEVE_MODE_PROP, retrieveMode);
|
||||
}
|
||||
|
||||
em.getTransaction().begin();
|
||||
CacheEntity ce1 = em.find(classToUpdate, idToUpdate);
|
||||
CacheEntity ce2 = em.find(classToFind, idToFind);
|
||||
assertNotNull(ce1);
|
||||
assertNotNull(ce2);
|
||||
ce1.setName(ce1.getName() + "UPD");
|
||||
em.getTransaction().commit();
|
||||
em.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Test logic to validate different CacheStoreModes. It should behave
|
||||
* identically for all shared-cache-modes except NONE which never caches
|
||||
* anything.
|
||||
* </p>
|
||||
* <p>
|
||||
* This method only tests setting the store mode on the EntityManager
|
||||
* itself.
|
||||
* </p>
|
||||
* <p>
|
||||
* The first transaction updates CacheableEntity::1 with CacheStoreMode
|
||||
* tran1StoreMode, calls find for CacheableEntity::1 and
|
||||
* XmlCacheableEntity::1. This will never trigger a cache refresh since the
|
||||
* data is up to date - but it could trigger additional SQL
|
||||
* </p>
|
||||
* <p>
|
||||
* The second transaction updates XmlCacheableEntity::1 with CacheStoreMode
|
||||
* tran2StoreMode, calls find for CacheableEntity::1 and
|
||||
* XmlCacheableEntity::1. In this case if tran2StoreMode ==
|
||||
* CacheStoreMode.REFRESH we may update the cache with the state of
|
||||
* CacheableEntity::1.
|
||||
* </p>
|
||||
*
|
||||
* @param tran1StoreMode
|
||||
* CacheStoreMode to use in transaction 1.
|
||||
* @param tran2StoreMode
|
||||
* cacheStoreMode to use in transaction 2.
|
||||
* @param cacheUpdatedForTran1
|
||||
* Whether the cache will contain an updated version of
|
||||
* CacheableEntity::1
|
||||
* @param cacheUpdatedForTran2
|
||||
* Whether the cache will contain an updated version of
|
||||
* XmlCacheableEntity::1
|
||||
* @param version
|
||||
* Expected starting version of for both entities
|
||||
*/
|
||||
public void entityManagerStoreModeTest(CacheStoreMode tran1StoreMode, CacheStoreMode tran2StoreMode,
|
||||
boolean cacheUpdatedForTran1, boolean cacheUpdatedForTran2, int version) {
|
||||
updateAndFind(CacheableEntity.class, 1, XmlCacheableEntity.class, 1, tran1StoreMode, null);
|
||||
updateAndFind(XmlCacheableEntity.class, 1, CacheableEntity.class, 1, tran2StoreMode, null);
|
||||
|
||||
// get entities from the cache and ensure their versions are as
|
||||
// expected.
|
||||
EntityManager em = getEntityManagerFactory().createEntityManager();
|
||||
em = getEntityManagerFactory().createEntityManager();
|
||||
CacheableEntity ceFromEM = em.find(CacheableEntity.class, 1);
|
||||
XmlCacheableEntity xceFromEM = em.find(XmlCacheableEntity.class, 1);
|
||||
em.close();
|
||||
assertEquals(cacheUpdatedForTran1 ? version + 1 : version, ceFromEM.getVersion());
|
||||
assertEquals(cacheUpdatedForTran2 ? version + 1 : version, xceFromEM.getVersion());
|
||||
|
||||
// get the data from the database. Version should always have been
|
||||
// updated in this case.
|
||||
em = getEntityManagerFactory().createEntityManager();
|
||||
em.setProperty(RETRIEVE_MODE_PROP, CacheRetrieveMode.BYPASS);
|
||||
CacheableEntity ceFromDB =
|
||||
(CacheableEntity) em.createNativeQuery("Select * from CacheableEntity where id = 1", CacheableEntity.class)
|
||||
.getSingleResult();
|
||||
|
||||
XmlCacheableEntity xceFromDB =
|
||||
(XmlCacheableEntity) em.createNativeQuery("Select * from XmlCacheableEntity where id = 1",
|
||||
XmlCacheableEntity.class).getSingleResult();
|
||||
|
||||
assertEquals(version + 1, ceFromDB.getVersion());
|
||||
assertEquals(version + 1, xceFromDB.getVersion());
|
||||
em.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the defaultStoreModeTest with
|
||||
*/
|
||||
public void testStoreModeUseBypass() throws Exception {
|
||||
if (getCacheEnabled()) {
|
||||
entityManagerStoreModeTest(CacheStoreMode.USE, CacheStoreMode.BYPASS, true, false, 1);
|
||||
}
|
||||
}
|
||||
|
||||
public void testStoreModeUseUse() {
|
||||
if (getCacheEnabled()) {
|
||||
entityManagerStoreModeTest(CacheStoreMode.USE, CacheStoreMode.USE, true, true, 1);
|
||||
}
|
||||
}
|
||||
|
||||
public void testStoreModeUseRefresh() {
|
||||
if (getCacheEnabled()) {
|
||||
entityManagerStoreModeTest(CacheStoreMode.USE, CacheStoreMode.REFRESH, true, true, 1);
|
||||
}
|
||||
}
|
||||
|
||||
public void entityManagerStoreModeTest() {
|
||||
if (getCacheEnabled()) {
|
||||
entityManagerStoreModeTest(CacheStoreMode.BYPASS, CacheStoreMode.BYPASS, false, false, 1);
|
||||
}
|
||||
}
|
||||
|
||||
public void testStoreModeBypassUse() {
|
||||
if (getCacheEnabled()) {
|
||||
entityManagerStoreModeTest(CacheStoreMode.BYPASS, CacheStoreMode.USE, false, true, 1);
|
||||
}
|
||||
}
|
||||
|
||||
public void testStoreModeBypassRefresh() {
|
||||
if (getCacheEnabled()) {
|
||||
// REFRESH picks up the changes from the database, even though the
|
||||
// first update was done with BYPASS
|
||||
entityManagerStoreModeTest(CacheStoreMode.BYPASS, CacheStoreMode.REFRESH, true, true, 1);
|
||||
}
|
||||
}
|
||||
|
||||
public void testStoreModeRefreshUse() {
|
||||
if (getCacheEnabled()) {
|
||||
entityManagerStoreModeTest(CacheStoreMode.REFRESH, CacheStoreMode.USE, true, true, 1);
|
||||
}
|
||||
}
|
||||
|
||||
public void testStoreModeRefreshBypass() {
|
||||
if (getCacheEnabled()) {
|
||||
entityManagerStoreModeTest(CacheStoreMode.REFRESH, CacheStoreMode.BYPASS, true, false, 1);
|
||||
}
|
||||
}
|
||||
|
||||
public void testStoreModeRefreshRefresh() {
|
||||
if (getCacheEnabled()) {
|
||||
entityManagerStoreModeTest(CacheStoreMode.REFRESH, CacheStoreMode.REFRESH, true, true, 1);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,155 +0,0 @@
|
||||
/*
|
||||
* 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.cache.jpa;
|
||||
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
import javax.persistence.Cache;
|
||||
import javax.persistence.EntityManager;
|
||||
|
||||
import org.apache.openjpa.persistence.OpenJPAEntityManagerFactorySPI;
|
||||
import org.apache.openjpa.persistence.OpenJPAPersistence;
|
||||
import org.apache.openjpa.persistence.cache.jpa.model.CacheEntity;
|
||||
import org.apache.openjpa.persistence.cache.jpa.model.CacheableEntity;
|
||||
import org.apache.openjpa.persistence.cache.jpa.model.NegatedCachableEntity;
|
||||
import org.apache.openjpa.persistence.cache.jpa.model.NegatedUncacheableEntity;
|
||||
import org.apache.openjpa.persistence.cache.jpa.model.UncacheableEntity;
|
||||
import org.apache.openjpa.persistence.cache.jpa.model.UnspecifiedEntity;
|
||||
import org.apache.openjpa.persistence.cache.jpa.model.XmlCacheableEntity;
|
||||
import org.apache.openjpa.persistence.cache.jpa.model.XmlUncacheableEntity;
|
||||
import org.apache.openjpa.persistence.test.AbstractPersistenceTestCase;
|
||||
|
||||
public abstract class AbstractJPACacheTestCase extends AbstractPersistenceTestCase {
|
||||
public abstract OpenJPAEntityManagerFactorySPI getEntityManagerFactory();
|
||||
|
||||
private static Class<?>[] persistentTypes =
|
||||
{ CacheableEntity.class, UncacheableEntity.class, UnspecifiedEntity.class,
|
||||
NegatedCachableEntity.class, NegatedUncacheableEntity.class, XmlCacheableEntity.class,
|
||||
XmlUncacheableEntity.class };
|
||||
|
||||
public void populate() throws IllegalAccessException, InstantiationException {
|
||||
EntityManager em = getEntityManagerFactory().createEntityManager();
|
||||
em.getTransaction().begin();
|
||||
for (Class<?> clss : persistentTypes) {
|
||||
if (!Modifier.isAbstract(clss.getModifiers())) {
|
||||
CacheEntity ce = (CacheEntity) clss.newInstance();
|
||||
ce.setId(1);
|
||||
em.persist(ce);
|
||||
}
|
||||
}
|
||||
em.getTransaction().commit();
|
||||
em.close();
|
||||
}
|
||||
|
||||
public OpenJPAEntityManagerFactorySPI createEntityManagerFactory(String puName) {
|
||||
OpenJPAEntityManagerFactorySPI emf =
|
||||
(OpenJPAEntityManagerFactorySPI) OpenJPAPersistence.createEntityManagerFactory(puName,
|
||||
"META-INF/caching-persistence.xml", getPropertiesMap("openjpa.DataCache", "true",
|
||||
"openjpa.RemoteCommitProvider", "sjvm", persistentTypes));
|
||||
return emf;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
// populate once per test method in case we add more methods
|
||||
cleanDatabase();
|
||||
populate();
|
||||
}
|
||||
|
||||
public void cleanDatabase() throws Exception {
|
||||
EntityManager em = getEntityManagerFactory().createEntityManager();
|
||||
em.getTransaction().begin();
|
||||
for (Class<?> clss : persistentTypes) {
|
||||
if (!Modifier.isAbstract(clss.getModifiers())) {
|
||||
em.createQuery("Delete from " + clss.getSimpleName()).executeUpdate();
|
||||
}
|
||||
}
|
||||
em.getTransaction().commit();
|
||||
em.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert whether the cache contains the expected results.
|
||||
*
|
||||
* @param cache
|
||||
* The JPA Cache to verify
|
||||
* @param expectCacheables
|
||||
* Whether entities with @Cacheable(true) should be in the cache
|
||||
* (almost always true)
|
||||
* @param expectUncacheables
|
||||
* Whether entities with @Cacheable(false) should be in the cache
|
||||
* (almost always false)
|
||||
* @param expectUnspecified
|
||||
* Whether entities with no @Cacheable annotation should be in
|
||||
* the cache (varies per config).
|
||||
*/
|
||||
protected void assertCacheContents(Cache cache, boolean expectCacheables, boolean expectUncacheables,
|
||||
boolean expectUnspecified) {
|
||||
assertCacheables(cache, expectCacheables);
|
||||
assertUncacheables(cache, expectUncacheables);
|
||||
assertUnspecified(cache, expectUnspecified);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert whether the cacheable types are in the cache. This method exits on
|
||||
* the first cache 'miss'.
|
||||
*
|
||||
* @param cache
|
||||
* JPA Cache to verify
|
||||
* @param expected
|
||||
* If true the cacheable types should be in the cache, if false
|
||||
* they should not be.
|
||||
*/
|
||||
protected void assertCacheables(Cache cache, boolean expected) {
|
||||
assertCached(cache, CacheableEntity.class, 1, expected);
|
||||
assertCached(cache, NegatedUncacheableEntity.class, 1, expected);
|
||||
assertCached(cache, XmlCacheableEntity.class, 1, expected);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert whether the uncacheable types are in the cache. This method exits
|
||||
* on the first cache 'miss'.
|
||||
*
|
||||
* @param cache
|
||||
* JPA Cache to verify
|
||||
* @param expected
|
||||
* If true the uncacheable types should be in the cache, if false
|
||||
* they should not be.
|
||||
*/
|
||||
protected void assertUncacheables(Cache cache, boolean expected) {
|
||||
assertCached(cache, UncacheableEntity.class, 1, expected);
|
||||
assertCached(cache, XmlUncacheableEntity.class, 1, expected);
|
||||
assertCached(cache, NegatedCachableEntity.class, 1, expected);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert whether the unspecified types are in the cache. This method exits
|
||||
* on the first cache 'miss'.
|
||||
*
|
||||
* @param cache
|
||||
* JPA Cache to verify
|
||||
* @param expected
|
||||
* If true the unspecified types should be in the cache, if false
|
||||
* they should not be.
|
||||
*/
|
||||
protected void assertUnspecified(Cache cache, boolean expected) {
|
||||
assertCached(cache, UnspecifiedEntity.class, 1, expected);
|
||||
}
|
||||
}
|
@ -18,14 +18,24 @@
|
||||
*/
|
||||
package org.apache.openjpa.persistence.cache.jpa;
|
||||
|
||||
import javax.persistence.Cache;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.Cache;
|
||||
import javax.persistence.CacheStoreMode;
|
||||
|
||||
import org.apache.openjpa.lib.jdbc.JDBCListener;
|
||||
import org.apache.openjpa.persistence.OpenJPAEntityManagerFactorySPI;
|
||||
|
||||
public class TestCacheModeAll extends AbstractJPACacheTestCase {
|
||||
public class TestCacheModeAll extends AbstractCacheModeTestCase {
|
||||
|
||||
private static OpenJPAEntityManagerFactorySPI emf = null;
|
||||
private static Cache cache = null;
|
||||
private static List<String> sql = new ArrayList<String>();
|
||||
private static JDBCListener listener;
|
||||
|
||||
private static Class<?>[] expectedInCache = persistentTypes;
|
||||
private static Class<?>[] expectedNotInCache = {};
|
||||
|
||||
@Override
|
||||
public OpenJPAEntityManagerFactorySPI getEntityManagerFactory() {
|
||||
@ -38,6 +48,17 @@ public class TestCacheModeAll extends AbstractJPACacheTestCase {
|
||||
return emf;
|
||||
}
|
||||
|
||||
public JDBCListener getListener() {
|
||||
if (listener == null) {
|
||||
listener = new Listener();
|
||||
}
|
||||
return listener;
|
||||
}
|
||||
|
||||
public List<String> getSql() {
|
||||
return sql;
|
||||
}
|
||||
|
||||
public void testCacheables() {
|
||||
assertCacheables(cache, true);
|
||||
}
|
||||
@ -49,4 +70,14 @@ public class TestCacheModeAll extends AbstractJPACacheTestCase {
|
||||
public void testUnspecified() {
|
||||
assertUnspecified(cache, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getExpectedInCache() {
|
||||
return expectedInCache;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getExpectedNotInCache() {
|
||||
return expectedNotInCache;
|
||||
}
|
||||
}
|
||||
|
@ -18,14 +18,32 @@
|
||||
*/
|
||||
package org.apache.openjpa.persistence.cache.jpa;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.Cache;
|
||||
import javax.persistence.CacheStoreMode;
|
||||
|
||||
import org.apache.openjpa.lib.jdbc.JDBCListener;
|
||||
import org.apache.openjpa.persistence.OpenJPAEntityManagerFactorySPI;
|
||||
import org.apache.openjpa.persistence.cache.jpa.model.CacheableEntity;
|
||||
import org.apache.openjpa.persistence.cache.jpa.model.NegatedUncacheableEntity;
|
||||
import org.apache.openjpa.persistence.cache.jpa.model.UncacheableEntity;
|
||||
import org.apache.openjpa.persistence.cache.jpa.model.UnspecifiedEntity;
|
||||
import org.apache.openjpa.persistence.cache.jpa.model.XmlCacheableEntity;
|
||||
import org.apache.openjpa.persistence.cache.jpa.model.XmlUncacheableEntity;
|
||||
|
||||
public class TestCacheModeDisableSelective extends AbstractJPACacheTestCase {
|
||||
public class TestCacheModeDisableSelective extends AbstractCacheModeTestCase {
|
||||
|
||||
private static OpenJPAEntityManagerFactorySPI emf = null;
|
||||
private static Cache cache = null;
|
||||
private static List<String> sql = new ArrayList<String>();
|
||||
private static JDBCListener listener;
|
||||
|
||||
private static Class<?>[] expectedInCache =
|
||||
{ CacheableEntity.class, XmlCacheableEntity.class, NegatedUncacheableEntity.class, UnspecifiedEntity.class, };
|
||||
private static Class<?>[] expectedNotInCache =
|
||||
{ UncacheableEntity.class, XmlUncacheableEntity.class, };
|
||||
|
||||
@Override
|
||||
public OpenJPAEntityManagerFactorySPI getEntityManagerFactory() {
|
||||
@ -38,6 +56,17 @@ public class TestCacheModeDisableSelective extends AbstractJPACacheTestCase {
|
||||
return emf;
|
||||
}
|
||||
|
||||
public JDBCListener getListener() {
|
||||
if (listener == null) {
|
||||
listener = new Listener();
|
||||
}
|
||||
return listener;
|
||||
}
|
||||
|
||||
public List<String> getSql() {
|
||||
return sql;
|
||||
}
|
||||
|
||||
public void testCacheables() {
|
||||
assertCacheables(cache, true);
|
||||
}
|
||||
@ -49,4 +78,14 @@ public class TestCacheModeDisableSelective extends AbstractJPACacheTestCase {
|
||||
public void testUnspecified() {
|
||||
assertUnspecified(cache, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getExpectedInCache() {
|
||||
return expectedInCache;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getExpectedNotInCache() {
|
||||
return expectedNotInCache;
|
||||
}
|
||||
}
|
||||
|
@ -18,14 +18,31 @@
|
||||
*/
|
||||
package org.apache.openjpa.persistence.cache.jpa;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.Cache;
|
||||
|
||||
import org.apache.openjpa.lib.jdbc.JDBCListener;
|
||||
import org.apache.openjpa.persistence.OpenJPAEntityManagerFactorySPI;
|
||||
import org.apache.openjpa.persistence.cache.jpa.model.CacheableEntity;
|
||||
import org.apache.openjpa.persistence.cache.jpa.model.NegatedUncacheableEntity;
|
||||
import org.apache.openjpa.persistence.cache.jpa.model.UncacheableEntity;
|
||||
import org.apache.openjpa.persistence.cache.jpa.model.UnspecifiedEntity;
|
||||
import org.apache.openjpa.persistence.cache.jpa.model.XmlCacheableEntity;
|
||||
import org.apache.openjpa.persistence.cache.jpa.model.XmlUncacheableEntity;
|
||||
|
||||
public class TestCacheModeEnableSelective extends AbstractJPACacheTestCase {
|
||||
public class TestCacheModeEnableSelective extends AbstractCacheModeTestCase {
|
||||
|
||||
private static OpenJPAEntityManagerFactorySPI emf = null;
|
||||
private static Cache cache = null;
|
||||
private static List<String> sql = new ArrayList<String>();
|
||||
private static JDBCListener listener;
|
||||
|
||||
private static Class<?>[] expectedInCache =
|
||||
{ CacheableEntity.class, XmlCacheableEntity.class, NegatedUncacheableEntity.class, };
|
||||
private static Class<?>[] expectedNotInCache =
|
||||
{ UncacheableEntity.class, XmlUncacheableEntity.class, UnspecifiedEntity.class, };
|
||||
|
||||
@Override
|
||||
public OpenJPAEntityManagerFactorySPI getEntityManagerFactory() {
|
||||
@ -38,6 +55,31 @@ public class TestCacheModeEnableSelective extends AbstractJPACacheTestCase {
|
||||
return emf;
|
||||
}
|
||||
|
||||
public JDBCListener getListener() {
|
||||
if (listener == null) {
|
||||
listener = new Listener();
|
||||
}
|
||||
return listener;
|
||||
}
|
||||
|
||||
public List<String> getSql() {
|
||||
return sql;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getExpectedInCache() {
|
||||
return expectedInCache;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getExpectedNotInCache() {
|
||||
return expectedNotInCache;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// Tests
|
||||
// =======================================================================
|
||||
|
||||
public void testCacheables() {
|
||||
assertCacheables(cache, true);
|
||||
}
|
||||
@ -49,5 +91,5 @@ public class TestCacheModeEnableSelective extends AbstractJPACacheTestCase {
|
||||
public void testUnspecified() {
|
||||
assertUnspecified(cache, false);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -18,14 +18,24 @@
|
||||
*/
|
||||
package org.apache.openjpa.persistence.cache.jpa;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.Cache;
|
||||
|
||||
import org.apache.openjpa.lib.jdbc.JDBCListener;
|
||||
import org.apache.openjpa.persistence.OpenJPAEntityManagerFactorySPI;
|
||||
import org.apache.openjpa.persistence.StoreCache;
|
||||
|
||||
public class TestCacheModeNone extends AbstractJPACacheTestCase {
|
||||
public class TestCacheModeNone extends AbstractCacheModeTestCase {
|
||||
|
||||
private static OpenJPAEntityManagerFactorySPI emf = null;
|
||||
private static Cache cache = null;
|
||||
private static List<String> sql = new ArrayList<String>();
|
||||
private static JDBCListener listener;
|
||||
|
||||
private static Class<?>[] expectedInCache = {};
|
||||
private static Class<?>[] expectedNotInCache = persistentTypes;
|
||||
|
||||
@Override
|
||||
public OpenJPAEntityManagerFactorySPI getEntityManagerFactory() {
|
||||
@ -38,6 +48,22 @@ public class TestCacheModeNone extends AbstractJPACacheTestCase {
|
||||
return emf;
|
||||
}
|
||||
|
||||
public JDBCListener getListener() {
|
||||
if (listener == null) {
|
||||
listener = new Listener();
|
||||
}
|
||||
return listener;
|
||||
}
|
||||
|
||||
public List<String> getSql() {
|
||||
return sql;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getCacheEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void testCacheables() {
|
||||
assertCacheables(cache, false);
|
||||
}
|
||||
@ -49,4 +75,15 @@ public class TestCacheModeNone extends AbstractJPACacheTestCase {
|
||||
public void testUnspecified() {
|
||||
assertUnspecified(cache, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getExpectedInCache() {
|
||||
return expectedInCache;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getExpectedNotInCache() {
|
||||
return expectedNotInCache;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -21,4 +21,6 @@ package org.apache.openjpa.persistence.cache.jpa.model;
|
||||
public interface CacheEntity {
|
||||
|
||||
public void setId(int id);
|
||||
public void setName(String name);
|
||||
public String getName();
|
||||
}
|
||||
|
@ -31,6 +31,8 @@ public class CacheableEntity implements CacheEntity {
|
||||
|
||||
@Version
|
||||
private int version;
|
||||
|
||||
private String name;
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
@ -47,4 +49,12 @@ public class CacheableEntity implements CacheEntity {
|
||||
public void setVersion(int version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
@ -33,6 +33,16 @@ public class NegatedCachableEntity implements CacheEntity {
|
||||
|
||||
@Version
|
||||
private int version;
|
||||
|
||||
private String name;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
|
@ -34,6 +34,16 @@ public class NegatedUncacheableEntity implements CacheEntity {
|
||||
@Version
|
||||
private int version;
|
||||
|
||||
private String name;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
@ -31,6 +31,16 @@ public class UncacheableEntity implements CacheEntity {
|
||||
|
||||
@Version
|
||||
private int version;
|
||||
|
||||
private String name;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
|
@ -29,6 +29,16 @@ public class UnspecifiedEntity implements CacheEntity {
|
||||
|
||||
@Version
|
||||
private int version;
|
||||
|
||||
private String name;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
|
@ -32,6 +32,8 @@ public class XmlCacheableEntity implements CacheEntity {
|
||||
|
||||
@Version
|
||||
private int version;
|
||||
|
||||
private String name;
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
@ -48,4 +50,12 @@ public class XmlCacheableEntity implements CacheEntity {
|
||||
public void setVersion(int version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
@ -33,6 +33,16 @@ public class XmlUncacheableEntity implements CacheEntity {
|
||||
@Version
|
||||
private int version;
|
||||
|
||||
private String name;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
@ -38,6 +38,8 @@ import java.util.IdentityHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.CacheRetrieveMode;
|
||||
import javax.persistence.CacheStoreMode;
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.FlushModeType;
|
||||
import javax.persistence.LockModeType;
|
||||
@ -57,6 +59,8 @@ import org.apache.openjpa.enhance.PCRegistry;
|
||||
import org.apache.openjpa.enhance.Reflection;
|
||||
import org.apache.openjpa.kernel.AbstractBrokerFactory;
|
||||
import org.apache.openjpa.kernel.Broker;
|
||||
import org.apache.openjpa.kernel.DataCacheRetrieveMode;
|
||||
import org.apache.openjpa.kernel.DataCacheStoreMode;
|
||||
import org.apache.openjpa.kernel.DelegatingBroker;
|
||||
import org.apache.openjpa.kernel.FetchConfiguration;
|
||||
import org.apache.openjpa.kernel.FindCallbacks;
|
||||
@ -105,6 +109,9 @@ public class EntityManagerImpl
|
||||
private Map<FetchConfiguration,FetchPlan> _plans = new IdentityHashMap<FetchConfiguration,FetchPlan>(1);
|
||||
|
||||
private RuntimeExceptionTranslator _ret = PersistenceExceptions.getRollbackTranslator(this);
|
||||
|
||||
protected final String RETRIEVE_MODE_PROP = "javax.persistence.cache.retrieveMode";
|
||||
protected final String STORE_MODE_PROP = "javax.persistence.cache.storeMode";
|
||||
|
||||
public EntityManagerImpl() {
|
||||
// for Externalizable
|
||||
@ -482,9 +489,9 @@ public class EntityManagerImpl
|
||||
public <T> T find(Class<T> cls, Object oid, LockModeType mode,
|
||||
Map<String, Object> properties) {
|
||||
assertNotCloseInvoked();
|
||||
if (mode != null && mode != LockModeType.NONE)
|
||||
if (mode != null && mode != LockModeType.NONE) {
|
||||
_broker.assertActiveTransaction();
|
||||
|
||||
}
|
||||
processLockProperties(pushFetchPlan(), mode, properties);
|
||||
try {
|
||||
oid = _broker.newObjectId(cls, oid);
|
||||
@ -1638,4 +1645,38 @@ public class EntityManagerImpl
|
||||
int dot = s.lastIndexOf('.');
|
||||
return dot == -1 ? s : s.substring(dot+1);
|
||||
}
|
||||
|
||||
public void setRetrieveMode(CacheRetrieveMode retrieveMode) {
|
||||
_broker.setCacheRetrieveMode(toDataCacheRetrieveMode(retrieveMode));
|
||||
}
|
||||
|
||||
public CacheRetrieveMode getRetrieveMode() {
|
||||
return fromDataCacheRetrieveMode(_broker.getCacheRetrieveMode());
|
||||
}
|
||||
|
||||
public void setStoreMode(CacheStoreMode storeMode) {
|
||||
_broker.setCacheStoreMode(toDataCacheStoreMode(storeMode));
|
||||
}
|
||||
|
||||
public CacheStoreMode getStoreMode() {
|
||||
return fromDataCacheStoreMode(_broker.getCacheStoreMode());
|
||||
}
|
||||
|
||||
private final DataCacheRetrieveMode toDataCacheRetrieveMode(CacheRetrieveMode mode ) {
|
||||
// relies on the CacheRetrieveMode enums being nearly identical
|
||||
return DataCacheRetrieveMode.valueOf(mode.toString());
|
||||
}
|
||||
|
||||
private final DataCacheStoreMode toDataCacheStoreMode(CacheStoreMode mode ) {
|
||||
// relies on the CacheStoreMode enums being nearly identical
|
||||
return DataCacheStoreMode.valueOf(mode.toString());
|
||||
}
|
||||
|
||||
private final CacheRetrieveMode fromDataCacheRetrieveMode(DataCacheRetrieveMode mode) {
|
||||
return CacheRetrieveMode.valueOf(mode.toString());
|
||||
}
|
||||
|
||||
private final CacheStoreMode fromDataCacheStoreMode(DataCacheStoreMode mode) {
|
||||
return CacheStoreMode.valueOf(mode.toString());
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user