mirror of https://github.com/apache/openjpa.git
OPENJPA-1045. L2 cache included / excluded types may be specified via configuration properties
git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@770729 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
733c1ea7de
commit
2c2e78149d
|
@ -19,13 +19,17 @@
|
|||
package org.apache.openjpa.datacache;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.BitSet;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.openjpa.conf.OpenJPAConfiguration;
|
||||
import org.apache.openjpa.event.RemoteCommitEvent;
|
||||
import org.apache.openjpa.event.RemoteCommitListener;
|
||||
|
@ -35,6 +39,8 @@ import org.apache.openjpa.lib.log.Log;
|
|||
import org.apache.openjpa.lib.util.Localizer;
|
||||
import org.apache.openjpa.lib.util.concurrent.AbstractConcurrentEventManager;
|
||||
|
||||
import serp.util.Strings;
|
||||
|
||||
/**
|
||||
* Abstract {@link DataCache} implementation that provides various
|
||||
* statistics, logging, and timeout functionality common across cache
|
||||
|
@ -69,6 +75,9 @@ public abstract class AbstractDataCache
|
|||
private boolean _closed = false;
|
||||
private String _schedule = null;
|
||||
|
||||
protected Set<String> _includedTypes;
|
||||
protected Set<String> _excludedTypes;
|
||||
|
||||
public String getName() {
|
||||
return _name;
|
||||
}
|
||||
|
@ -461,4 +470,73 @@ public abstract class AbstractDataCache
|
|||
log.warn(s_loc.get("exp-listener-ex"), e);
|
||||
}
|
||||
}
|
||||
|
||||
public Set<String> getTypes() {
|
||||
return _includedTypes;
|
||||
}
|
||||
|
||||
public Set<String> getExcludedTypes() {
|
||||
return _excludedTypes;
|
||||
}
|
||||
|
||||
public void setTypes(Set<String> types) {
|
||||
_includedTypes = types;
|
||||
}
|
||||
|
||||
public void setTypes(String types) {
|
||||
_includedTypes =
|
||||
StringUtils.isEmpty(types) ? null : new HashSet<String>(Arrays
|
||||
.asList(Strings.split(types, ";", 0)));
|
||||
}
|
||||
|
||||
public void setExcludedTypes(Set<String> types) {
|
||||
_excludedTypes = types;
|
||||
}
|
||||
|
||||
public void setExcludedTypes(String types) {
|
||||
_excludedTypes =
|
||||
StringUtils.isEmpty(types) ? null : new HashSet<String>(Arrays
|
||||
.asList(Strings.split(types, ";", 0)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether a provided class can be applied to this cache.
|
||||
*
|
||||
* <P>
|
||||
* The algorithm used to determine which types apply is as follows:
|
||||
* <UL>
|
||||
* <LI>If neither included nor excluded types are found all types will be
|
||||
* used.</LI>
|
||||
* <LI>If included types are specified and excluded types are not specified
|
||||
* <b>only</b> the included types will be used.</LI>
|
||||
* <LI>If included types are not specified and excluded types are specified
|
||||
* all types will be used <b>except</b> those which are explicitly excluded.
|
||||
* </LI>
|
||||
* <LI>If both included types and excluded types are specified then
|
||||
* <b>only</b> the included types will be used. If an included type is also
|
||||
* an excluded type the <b>excluded</b> setting will take precedence (ie
|
||||
* the type will not be used).</LI>
|
||||
* </UL>
|
||||
*
|
||||
* @param className
|
||||
* A class which may be used by this plugin.
|
||||
* @return True if the type should be used, otherwise false.
|
||||
*/
|
||||
public boolean isCacheableType(String classname) {
|
||||
boolean rval = true;
|
||||
if(rval) {
|
||||
System.out.format("ABDC");
|
||||
}
|
||||
if (_includedTypes != null && ! _includedTypes.isEmpty()) {
|
||||
if(!_includedTypes.contains(classname)) {
|
||||
rval = false;
|
||||
}
|
||||
}
|
||||
if (_excludedTypes != null && ! _excludedTypes.isEmpty()) {
|
||||
if(_excludedTypes.contains(classname)) {
|
||||
rval = false;
|
||||
}
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ import java.util.TreeMap;
|
|||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.openjpa.conf.OpenJPAConfiguration;
|
||||
import org.apache.openjpa.datacache.AbstractDataCache;
|
||||
import org.apache.openjpa.datacache.DataCache;
|
||||
import org.apache.openjpa.enhance.PCRegistry;
|
||||
import org.apache.openjpa.enhance.Reflection;
|
||||
|
@ -1395,14 +1396,23 @@ public class ClassMetaData
|
|||
}
|
||||
|
||||
/**
|
||||
* The name of the datacache to use for this class, or null if none.
|
||||
* The name of the datacache to use for this class. If this class is not
|
||||
* eligible for caching based its annotation or the cache configuration
|
||||
* null will be returned.
|
||||
*
|
||||
* @return The cache name, or null if this type should not be cached.
|
||||
*/
|
||||
public String getDataCacheName() {
|
||||
if (DEFAULT_STRING.equals(_cacheName)) {
|
||||
if (_super != null)
|
||||
if (_super != null) {
|
||||
_cacheName = getPCSuperclassMetaData().getDataCacheName();
|
||||
else
|
||||
}
|
||||
else {
|
||||
_cacheName = DataCache.NAME_DEFAULT;
|
||||
}
|
||||
if(!isCacheable(_cacheName)) {
|
||||
_cacheName = null;
|
||||
}
|
||||
}
|
||||
return _cacheName;
|
||||
}
|
||||
|
@ -2553,4 +2563,23 @@ public class ClassMetaData
|
|||
public void setAbstract(boolean flag) {
|
||||
_abstract = flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether this Type should be included in the DataCache (if one
|
||||
* is provided) based on the DataCache's configuration.
|
||||
*
|
||||
* @return true if the DataCache will accept this type, otherwise false.
|
||||
*/
|
||||
private boolean isCacheable(String candidateCacheName) {
|
||||
boolean rval = true;
|
||||
DataCache cache =
|
||||
getRepository().getConfiguration().getDataCacheManagerInstance()
|
||||
.getDataCache(candidateCacheName);
|
||||
if (cache != null && (cache instanceof AbstractDataCache)) {
|
||||
AbstractDataCache adc = (AbstractDataCache) cache;
|
||||
if (!adc.isCacheableType(getDescribedType().getName()))
|
||||
rval = false;
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* 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.datacache;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Version;
|
||||
|
||||
@Entity
|
||||
@Table(name="CACHE_EXC_ITEM")
|
||||
public class Item {
|
||||
|
||||
@Id
|
||||
private int id;
|
||||
|
||||
@Version
|
||||
private int version;
|
||||
|
||||
private String name;
|
||||
|
||||
private String type;
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public int getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(int version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* 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.datacache;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToOne;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Version;
|
||||
|
||||
@Entity
|
||||
@Table(name="CACHE_EXC_ORDR")
|
||||
public class Order {
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private int id;
|
||||
|
||||
@Version
|
||||
private int version;
|
||||
|
||||
private int quantity;
|
||||
|
||||
@OneToOne
|
||||
private Item item;
|
||||
|
||||
@ManyToOne
|
||||
private Purchase purchase;
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public int getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(int version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public int getQuantity() {
|
||||
return quantity;
|
||||
}
|
||||
|
||||
public void setQuantity(int quantity) {
|
||||
this.quantity = quantity;
|
||||
}
|
||||
|
||||
public Item getItem() {
|
||||
return item;
|
||||
}
|
||||
|
||||
public void setItem(Item item) {
|
||||
this.item = item;
|
||||
}
|
||||
|
||||
public Purchase getPurchase() {
|
||||
return purchase;
|
||||
}
|
||||
|
||||
public void setPurchase(Purchase purchase) {
|
||||
this.purchase = purchase;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* 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.datacache;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Version;
|
||||
|
||||
@Entity
|
||||
@Table(name="CACHE_EXC_PURC")
|
||||
public class Purchase {
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private int id;
|
||||
|
||||
@Version
|
||||
private int version;
|
||||
|
||||
@OneToMany(mappedBy = "purchase", cascade = CascadeType.ALL)
|
||||
private Collection<Order> orders;
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public int getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(int version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public Collection<Order> getOrders() {
|
||||
return orders;
|
||||
}
|
||||
|
||||
public void setOrders(Collection<Order> orders) {
|
||||
this.orders = orders;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,233 @@
|
|||
/*
|
||||
* 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.datacache;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.Query;
|
||||
|
||||
import org.apache.openjpa.jdbc.meta.ClassMapping;
|
||||
import org.apache.openjpa.persistence.OpenJPAEntityManagerFactorySPI;
|
||||
import org.apache.openjpa.persistence.StoreCache;
|
||||
import org.apache.openjpa.persistence.test.PersistenceTestCase;
|
||||
|
||||
public class TestCacheExclusions extends PersistenceTestCase {
|
||||
|
||||
private OpenJPAEntityManagerFactorySPI emf = null;
|
||||
|
||||
private static String[] ITEM_NAMES =
|
||||
{ "Cup", "pen", "pencil", "phone", "laptop", "keyboard", "mouse" };
|
||||
|
||||
private static final String _tSep = ";";
|
||||
|
||||
Item[] items = new Item[ITEM_NAMES.length];
|
||||
Order o1, o2;
|
||||
Purchase p;
|
||||
|
||||
public void populate() {
|
||||
EntityManager em = emf.createEntityManager();
|
||||
em.getTransaction().begin();
|
||||
int n = 0;
|
||||
for (String s : ITEM_NAMES) {
|
||||
items[n] = new Item();
|
||||
items[n].setName(s);
|
||||
items[n].setId(n);
|
||||
em.persist(items[n++]);
|
||||
}
|
||||
p = new Purchase();
|
||||
p.setOrders(new ArrayList<Order>());
|
||||
o1 = new Order();
|
||||
o1.setItem(em.find(Item.class, 1));
|
||||
o1.setQuantity(2);
|
||||
o1.setPurchase(p);
|
||||
p.getOrders().add(o1);
|
||||
|
||||
o2 = new Order();
|
||||
o2.setItem(em.find(Item.class, 4));
|
||||
o2.setQuantity(23);
|
||||
o2.setPurchase(p);
|
||||
p.getOrders().add(o2);
|
||||
|
||||
em.persist(p);
|
||||
em.getTransaction().commit();
|
||||
em.close();
|
||||
}
|
||||
|
||||
public void tearDown() throws Exception {
|
||||
if (emf != null) {
|
||||
EntityManager em = emf.createEntityManager();
|
||||
em.getTransaction().begin();
|
||||
|
||||
for (ClassMapping mapping : ((ClassMapping[]) emf
|
||||
.getConfiguration().getMetaDataRepositoryInstance()
|
||||
.getMetaDatas())) {
|
||||
Query q =
|
||||
em.createNativeQuery("DROP TABLE "
|
||||
+ mapping.getTable().getName());
|
||||
q.executeUpdate();
|
||||
}
|
||||
em.getTransaction().commit();
|
||||
em.close();
|
||||
|
||||
emf.close();
|
||||
}
|
||||
emf = null;
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
public void testCacheAll() {
|
||||
getEntityManagerFactoryCacheSettings(null, null);
|
||||
populate();
|
||||
StoreCache cache = emf.getStoreCache();
|
||||
assertCacheContents(cache, true, true, true);
|
||||
}
|
||||
|
||||
public void testCacheItems() {
|
||||
getEntityManagerFactoryCacheSettings(new Class[] { Item.class }, null);
|
||||
populate();
|
||||
StoreCache cache = emf.getStoreCache();
|
||||
assertCacheContents(cache, false, false, true);
|
||||
}
|
||||
|
||||
public void testCacheItemsAndPurchases() {
|
||||
getEntityManagerFactoryCacheSettings(new Class[] { Item.class,
|
||||
Purchase.class }, null);
|
||||
populate();
|
||||
StoreCache cache = emf.getStoreCache();
|
||||
assertCacheContents(cache, true, false, true);
|
||||
}
|
||||
|
||||
public void testCacheItemsAndOrders() {
|
||||
getEntityManagerFactoryCacheSettings(new Class[] { Item.class,
|
||||
Order.class }, null);
|
||||
populate();
|
||||
StoreCache cache = emf.getStoreCache();
|
||||
assertCacheContents(cache, false, true, true);
|
||||
}
|
||||
|
||||
public void testCachePurchasesAndOrders() {
|
||||
getEntityManagerFactoryCacheSettings(new Class[] { Purchase.class,
|
||||
Order.class }, null);
|
||||
populate();
|
||||
StoreCache cache = emf.getStoreCache();
|
||||
assertCacheContents(cache, true, true, false);
|
||||
}
|
||||
|
||||
public void testExcludePurchases() {
|
||||
getEntityManagerFactoryCacheSettings(null,
|
||||
new Class[] { Purchase.class });
|
||||
populate();
|
||||
StoreCache cache = emf.getStoreCache();
|
||||
assertCacheContents(cache, false, true, true);
|
||||
}
|
||||
|
||||
public void testExcludeOrders() {
|
||||
getEntityManagerFactoryCacheSettings(null, new Class[] { Order.class });
|
||||
populate();
|
||||
StoreCache cache = emf.getStoreCache();
|
||||
assertCacheContents(cache, true, false, true);
|
||||
}
|
||||
|
||||
public void testExcludeItems() {
|
||||
getEntityManagerFactoryCacheSettings(null, new Class[] { Item.class });
|
||||
populate();
|
||||
StoreCache cache = emf.getStoreCache();
|
||||
assertCacheContents(cache, true, true, false);
|
||||
}
|
||||
|
||||
public void testExcludeOrdersAndPurchases() {
|
||||
getEntityManagerFactoryCacheSettings(null, new Class[] { Order.class,
|
||||
Purchase.class });
|
||||
populate();
|
||||
StoreCache cache = emf.getStoreCache();
|
||||
assertCacheContents(cache, false, false, true);
|
||||
}
|
||||
|
||||
public void testIncludePurchaseItemExcludePurchase() {
|
||||
getEntityManagerFactoryCacheSettings(new Class[] { Purchase.class,
|
||||
Item.class }, new Class[] { Purchase.class });
|
||||
populate();
|
||||
StoreCache cache = emf.getStoreCache();
|
||||
assertCacheContents(cache, false, false, true);
|
||||
}
|
||||
|
||||
public OpenJPAEntityManagerFactorySPI getEntityManagerFactoryCacheSettings(
|
||||
Class<?>[] includedTypes, Class<?>[] excludedTypes) {
|
||||
StringBuilder includes = new StringBuilder();
|
||||
if (includedTypes != null && includedTypes.length > 0) {
|
||||
includes.append("Types=");
|
||||
for (Class<?> c : includedTypes) {
|
||||
includes.append(c.getName());
|
||||
includes.append(_tSep);
|
||||
}
|
||||
includes.setLength(includes.length() - 1); // remove last semicolon
|
||||
}
|
||||
StringBuilder excludes = new StringBuilder();
|
||||
if (excludedTypes != null && excludedTypes.length > 0) {
|
||||
excludes.append("ExcludedTypes=");
|
||||
for (Class<?> c : excludedTypes) {
|
||||
excludes.append(c.getName());
|
||||
excludes.append(_tSep);
|
||||
}
|
||||
excludes.setLength(excludes.length() - 1); // remove last semicolon
|
||||
}
|
||||
StringBuilder dataCacheSettings = new StringBuilder();
|
||||
dataCacheSettings.append("true");
|
||||
if (includes.length() > 0 || excludes.length() > 0) {
|
||||
dataCacheSettings.append("(");
|
||||
dataCacheSettings.append(includes);
|
||||
if (includes.length() > 0 && excludes.length() > 0) {
|
||||
dataCacheSettings.append(",");
|
||||
}
|
||||
dataCacheSettings.append(excludes);
|
||||
dataCacheSettings.append(")");
|
||||
}
|
||||
Map<String, String> props = new HashMap<String, String>();
|
||||
props.put("openjpa.DataCache", dataCacheSettings.toString());
|
||||
props.put("openjpa.RemoteCommitProvider", "sjvm");
|
||||
props.put("openjpa.MetaDataFactory", "jpa(Types="
|
||||
+ Item.class.getName() + _tSep + Purchase.class.getName() + _tSep
|
||||
+ Order.class.getName() + ")");
|
||||
emf =
|
||||
(OpenJPAEntityManagerFactorySPI) javax.persistence.Persistence
|
||||
.createEntityManagerFactory("test", props);
|
||||
return emf;
|
||||
}
|
||||
|
||||
public void assertCacheContents(StoreCache cache, boolean expectPurchase,
|
||||
boolean expectOrders, boolean expectItems) {
|
||||
assertEquals("Expected purchases to " + (expectPurchase ? "" : "not ")
|
||||
+ "exist in the cache", expectPurchase, cache.contains(
|
||||
Purchase.class, p.getId()));
|
||||
assertEquals("Expected Orders to " + (expectOrders ? "" : "not ")
|
||||
+ "exist in the cache", expectOrders, cache.contains(Order.class,
|
||||
o1.getId()));
|
||||
assertEquals("Expected Orders to " + (expectOrders ? "" : "not ")
|
||||
+ "exist in the cache", expectOrders, cache.contains(Order.class,
|
||||
o2.getId()));
|
||||
for (int i = 0; i < ITEM_NAMES.length; i++) {
|
||||
assertEquals("Expected Items to " + (expectItems ? "" : "not ")
|
||||
+ "exist in the cache", expectItems, cache.contains(Item.class,
|
||||
items[i].getId()));
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue