mirror of
https://github.com/apache/openjpa.git
synced 2025-02-08 11:06:01 +00:00
OPENJPA-1856: Make DataCache eviction due to bulk updates configurable.
git-svn-id: https://svn.apache.org/repos/asf/openjpa/branches/2.1.x@1057319 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
92aba0ead7
commit
f12970baf2
@ -80,7 +80,8 @@ public abstract class AbstractDataCache extends AbstractConcurrentEventManager
|
|||||||
private String _schedule = null;
|
private String _schedule = null;
|
||||||
protected Set<String> _includedTypes = new HashSet<String>();
|
protected Set<String> _includedTypes = new HashSet<String>();
|
||||||
protected Set<String> _excludedTypes = new HashSet<String>();
|
protected Set<String> _excludedTypes = new HashSet<String>();
|
||||||
|
protected boolean _evictOnBulkUpdate = true;
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return _name;
|
return _name;
|
||||||
}
|
}
|
||||||
@ -541,4 +542,12 @@ public abstract class AbstractDataCache extends AbstractConcurrentEventManager
|
|||||||
public DataCache selectCache(OpenJPAStateManager sm) {
|
public DataCache selectCache(OpenJPAStateManager sm) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean getEvictOnBulkUpdate(){
|
||||||
|
return _evictOnBulkUpdate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEvictOnBulkUpdate(boolean b){
|
||||||
|
_evictOnBulkUpdate = b;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -304,4 +304,9 @@ public interface DataCache
|
|||||||
* Returns number of read/write request and cache hit ratio data.
|
* Returns number of read/write request and cache hit ratio data.
|
||||||
*/
|
*/
|
||||||
public CacheStatistics getStatistics();
|
public CacheStatistics getStatistics();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the the cache needs to be updated when bulk updates as executed. Defaults to true.
|
||||||
|
*/
|
||||||
|
public boolean getEvictOnBulkUpdate();
|
||||||
}
|
}
|
||||||
|
@ -117,7 +117,7 @@ public class DataCacheStoreManager
|
|||||||
DataCache cache;
|
DataCache cache;
|
||||||
for (Class<?> cls : classes) {
|
for (Class<?> cls : classes) {
|
||||||
cache = mdr.getMetaData(cls, loader, false).getDataCache();
|
cache = mdr.getMetaData(cls, loader, false).getDataCache();
|
||||||
if (cache != null)
|
if (cache != null && cache.getEvictOnBulkUpdate())
|
||||||
cache.removeAll(cls, false);
|
cache.removeAll(cls, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -381,4 +381,14 @@ public class DelegatingDataCache
|
|||||||
throw translate(re);
|
throw translate(re);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean getEvictOnBulkUpdate() {
|
||||||
|
if (_cache == null)
|
||||||
|
return false;
|
||||||
|
try {
|
||||||
|
return _cache.getEvictOnBulkUpdate();
|
||||||
|
} catch (RuntimeException re) {
|
||||||
|
throw translate(re);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -380,7 +380,7 @@ public class QueryCacheStoreQuery
|
|||||||
|
|
||||||
// evict from the data cache
|
// evict from the data cache
|
||||||
for (int i = 0; i < cmd.length; i++) {
|
for (int i = 0; i < cmd.length; i++) {
|
||||||
if (cmd[i].getDataCache() != null)
|
if (cmd[i].getDataCache() != null && cmd[i].getDataCache().getEvictOnBulkUpdate())
|
||||||
cmd[i].getDataCache().removeAll(
|
cmd[i].getDataCache().removeAll(
|
||||||
cmd[i].getDescribedType(), true);
|
cmd[i].getDescribedType(), true);
|
||||||
}
|
}
|
||||||
|
@ -131,7 +131,7 @@ public abstract class AbstractStoreQuery
|
|||||||
} finally {
|
} finally {
|
||||||
for (ClassMetaData cmd : getAccessPathMetaDatas(q)) {
|
for (ClassMetaData cmd : getAccessPathMetaDatas(q)) {
|
||||||
DataCache cache = cmd.getDataCache();
|
DataCache cache = cmd.getDataCache();
|
||||||
if (cache != null) {
|
if (cache != null && cache.getEvictOnBulkUpdate()) {
|
||||||
cache.removeAll(cmd.getDescribedType(), true);
|
cache.removeAll(cmd.getDescribedType(), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -144,7 +144,7 @@ public abstract class AbstractStoreQuery
|
|||||||
} finally {
|
} finally {
|
||||||
for (ClassMetaData cmd : getAccessPathMetaDatas(q)) {
|
for (ClassMetaData cmd : getAccessPathMetaDatas(q)) {
|
||||||
DataCache cache = cmd.getDataCache();
|
DataCache cache = cmd.getDataCache();
|
||||||
if (cache != null) {
|
if (cache != null && cache.getEvictOnBulkUpdate()) {
|
||||||
cache.removeAll(cmd.getDescribedType(), true);
|
cache.removeAll(cmd.getDescribedType(), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -793,7 +793,7 @@ public class ExpressionStoreQuery
|
|||||||
} finally {
|
} finally {
|
||||||
for (ClassMetaData cmd : getAccessPathMetaDatas(q)) {
|
for (ClassMetaData cmd : getAccessPathMetaDatas(q)) {
|
||||||
DataCache cache = cmd.getDataCache();
|
DataCache cache = cmd.getDataCache();
|
||||||
if (cache != null) {
|
if (cache != null && cache.getEvictOnBulkUpdate()) {
|
||||||
cache.removeAll(cmd.getDescribedType(), true);
|
cache.removeAll(cmd.getDescribedType(), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -810,7 +810,7 @@ public class ExpressionStoreQuery
|
|||||||
} finally {
|
} finally {
|
||||||
for (ClassMetaData cmd : getAccessPathMetaDatas(q)) {
|
for (ClassMetaData cmd : getAccessPathMetaDatas(q)) {
|
||||||
DataCache cache = cmd.getDataCache();
|
DataCache cache = cmd.getDataCache();
|
||||||
if (cache != null) {
|
if (cache != null && cache.getEvictOnBulkUpdate()) {
|
||||||
cache.removeAll(cmd.getDescribedType(), true);
|
cache.removeAll(cmd.getDescribedType(), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,10 +21,14 @@ package org.apache.openjpa.persistence.datacache;
|
|||||||
import javax.persistence.Cache;
|
import javax.persistence.Cache;
|
||||||
import javax.persistence.EntityManager;
|
import javax.persistence.EntityManager;
|
||||||
|
|
||||||
|
import org.apache.openjpa.persistence.OpenJPAEntityManagerFactorySPI;
|
||||||
|
import org.apache.openjpa.persistence.OpenJPAEntityManagerSPI;
|
||||||
import org.apache.openjpa.persistence.test.SingleEMFTestCase;
|
import org.apache.openjpa.persistence.test.SingleEMFTestCase;
|
||||||
|
|
||||||
public class TestBulkUpdatesDataCacheEviction extends SingleEMFTestCase {
|
public class TestBulkUpdatesDataCacheEviction extends SingleEMFTestCase {
|
||||||
Object[] props = new Object[] { CLEAR_TABLES, CachedEntityStatistics.class, "openjpa.DataCache", "true" };
|
Object[] props = new Object[] { CLEAR_TABLES, CachedEntityStatistics.class, "openjpa.DataCache", "true" };
|
||||||
|
Object[] noEvictProps = new Object[] { CLEAR_TABLES, CachedEntityStatistics.class
|
||||||
|
, "openjpa.DataCache", "true(EvictOnBulkUpdate=false)" };
|
||||||
|
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
super.setUp(props);
|
super.setUp(props);
|
||||||
@ -85,7 +89,58 @@ public class TestBulkUpdatesDataCacheEviction extends SingleEMFTestCase {
|
|||||||
em.close();
|
em.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testUpdateNoEvict(){
|
||||||
|
OpenJPAEntityManagerFactorySPI emf = createNamedEMF(getPersistenceUnitName(), noEvictProps);
|
||||||
|
Cache cache = emf.getCache();
|
||||||
|
OpenJPAEntityManagerSPI em = emf.createEntityManager();
|
||||||
|
try {
|
||||||
|
CachedEntityStatistics e = createEntity(em);
|
||||||
|
assertTrue(cache.contains(CachedEntityStatistics.class, e.getId()));
|
||||||
|
em.clear();
|
||||||
|
|
||||||
|
String update = "UPDATE CachedEntityStatistics s SET s.firstName = :name WHERE s.id = :id";
|
||||||
|
String name = "name_" + System.currentTimeMillis();
|
||||||
|
// execute update, this should result in a cache eviction
|
||||||
|
em.getTransaction().begin();
|
||||||
|
assertEquals(1, em.createQuery(update).setParameter("name", name).setParameter("id", e.getId())
|
||||||
|
.executeUpdate());
|
||||||
|
em.getTransaction().commit();
|
||||||
|
assertTrue(cache.contains(CachedEntityStatistics.class, e.getId()));
|
||||||
|
|
||||||
|
CachedEntityStatistics postUpdate = em.find(CachedEntityStatistics.class, e.getId());
|
||||||
|
assertNotEquals(name, postUpdate.getFirstName());
|
||||||
|
}finally{
|
||||||
|
emf.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testDeleteNoEvict() throws Exception {
|
||||||
|
OpenJPAEntityManagerFactorySPI emf = createNamedEMF(getPersistenceUnitName(), noEvictProps);
|
||||||
|
Cache cache = emf.getCache();
|
||||||
|
OpenJPAEntityManagerSPI em = emf.createEntityManager();
|
||||||
|
try {
|
||||||
|
CachedEntityStatistics e = createEntity(em);
|
||||||
|
assertTrue(cache.contains(CachedEntityStatistics.class, e.getId()));
|
||||||
|
em.clear();
|
||||||
|
|
||||||
|
String delete = "DELETE FROM CachedEntityStatistics s WHERE s.id = :id";
|
||||||
|
// execute update, this should NOT result in a cache eviction
|
||||||
|
em.getTransaction().begin();
|
||||||
|
assertEquals(1, em.createQuery(delete).setParameter("id", e.getId()).executeUpdate());
|
||||||
|
em.getTransaction().commit();
|
||||||
|
assertTrue(cache.contains(CachedEntityStatistics.class, e.getId()));
|
||||||
|
|
||||||
|
em.clear();
|
||||||
|
|
||||||
|
CachedEntityStatistics postUpdate = em.find(CachedEntityStatistics.class, e.getId());
|
||||||
|
assertNotNull(postUpdate);
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
em.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private CachedEntityStatistics createEntity(EntityManager em) {
|
private CachedEntityStatistics createEntity(EntityManager em) {
|
||||||
em.getTransaction().begin();
|
em.getTransaction().begin();
|
||||||
CachedEntityStatistics e = new CachedEntityStatistics();
|
CachedEntityStatistics e = new CachedEntityStatistics();
|
||||||
|
@ -345,6 +345,18 @@ to evict values from the cache every 120 minutes.
|
|||||||
true(EvictionSchedule='+120')
|
true(EvictionSchedule='+120')
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</para>
|
</para>
|
||||||
|
<example id="bulk_update_evict_cache">
|
||||||
|
<title>
|
||||||
|
Bulk updates and cache eviction
|
||||||
|
</title>
|
||||||
|
<para>
|
||||||
|
For the example, setting EvictOnBulkUpdate to false will tell OpenJPA to not evict from the DataCache when executing
|
||||||
|
and UPDATE or DELETE statement. The default for the value is true.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
<programlisting><property name="openjpa.DataCache" value="true(EvictOnBulkUpdate=false)"/></programlisting>
|
||||||
|
</para>
|
||||||
|
</example>
|
||||||
<section id="ref_guide_cache_distribution">
|
<section id="ref_guide_cache_distribution">
|
||||||
<title>Distributing instances across cache partitions</title>
|
<title>Distributing instances across cache partitions</title>
|
||||||
<para>
|
<para>
|
||||||
@ -371,7 +383,7 @@ as follows:
|
|||||||
<property name="openjpa.DataCache" value="partitioned(PartitionType=concurrent,partitions=
|
<property name="openjpa.DataCache" value="partitioned(PartitionType=concurrent,partitions=
|
||||||
'(name=a,cacheSize=100),(name=b,cacheSize=200)')"/>
|
'(name=a,cacheSize=100),(name=b,cacheSize=200)')"/>
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</example>
|
</example>
|
||||||
</section>
|
</section>
|
||||||
<para>
|
<para>
|
||||||
The distribution policy is configured by a full-qualified class name that implements
|
The distribution policy is configured by a full-qualified class name that implements
|
||||||
|
Loading…
x
Reference in New Issue
Block a user