Index: openjpa-project/src/doc/manual/ref_guide_caching.xml =================================================================== --- openjpa-project/src/doc/manual/ref_guide_caching.xml (revision 1393568) +++ openjpa-project/src/doc/manual/ref_guide_caching.xml (working copy) @@ -134,6 +134,16 @@ Data Cache Configuration +There are two ways to enable the basic single-factory cache. One is using +openjpa.DataCache +property, the other one is using JPA standard shared-cache-mode Element or the +javax.persistence.sharedCache.mode property. + +
+ + openjpa.DataCache Configuration + + To enable the basic single-factory cache set the openjpa.DataCache property to true: @@ -352,7 +362,67 @@ <property name="openjpa.DataCache" value="true(EvictOnBulkUpdate=false)"/> - + +
+
+ + Integration with JPA standard shared cache mode + + + JPA 2.0 specification introduced the standard data cache configuration through the shared-cache-mode element or javax.persistence. +sharedCache.mode property. + + + When only the shared cache mode is configured to turn on the caching, the default data cache setting will be used. For example the + cache size will be set to default 1000. + + + When the shared cache mode and openjpa.DataCache are both configured, the JPA standard shared cache mode + configuration takes the precedence. + + + If the shared cache mode is to turn on the caching, the cache setting configured through openjpa.DataCache + , like cacheSize and SoftReferenceSize, will be used to initialize or manage the cache. The Types and ExcludeTypes + property in openjpa.DataCache will be ingnored since the shared cache mode in conjunction with the javax.persistence.Cacheable + annotation already defines what will be cached. + + + + +<property name="openjpa.DataCache" value="true"/> +<property name="javax.persistence.sharedCache.mode" value="NONE"/> + + + + When the shared cache mode is set to NONE, the data cache will be disabled no matter how openjpa.DataCache is configured. + + + + + + +<property name="openjpa.DataCache" value="true(ExcludedTypes=foo.bar.Person;foo.bar.Employee)"/> +<property name="javax.persistence.sharedCache.mode" value="ALL"/> + + + + When the shared cache mode is set to ALL, all entities will be cached no matter how openjpa.DataCache is configured. + + + + + + +<property name="openjpa.DataCache" value="true(ExcludedTypes=foo.bar.Person;foo.bar.Employee)"/> +<property name="javax.persistence.sharedCache.mode" value="ENABLE_SELECTIVE"/> + + + + When the shared cache mode set to ENABLE_SELECTIVE, the entities with Cacheable(true) anotation will be cached. + ExcludedTypes will be ignored. + + +
Distributing instances across cache partitions Index: openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/TestCacheModeNoneDataCacheCustomized.java =================================================================== --- openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/TestCacheModeNoneDataCacheCustomized.java (revision 0) +++ openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/TestCacheModeNoneDataCacheCustomized.java (working copy) @@ -0,0 +1,47 @@ +/* + * 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.HashMap; +import java.util.Map; + +import org.apache.openjpa.persistence.OpenJPAEntityManagerFactorySPI; + +public class TestCacheModeNoneDataCacheCustomized extends TestCacheModeNone{ + @Override + public OpenJPAEntityManagerFactorySPI getEntityManagerFactory() { + Map props = new HashMap(); + props.put("openjpa.DataCache", + "org.apache.openjpa.persistence.cache.jpa.DataCacheTestExtension(CacheSize=5000, " + + "ExcludedTypes=org.apache.openjpa.persistence.cache.jpa.model.UncacheableEntity)"); + + props.put("openjpa.RemoteCommitProvider", "sjvm"); + if (emf == null) { + emf = createEntityManagerFactory("cache-mode-none",props); + assertNotNull(emf); + assertEquals("org.apache.openjpa.persistence.cache.jpa.DataCacheTestExtension(CacheSize=5000, " + + "ExcludedTypes=org.apache.openjpa.persistence.cache.jpa.model.UncacheableEntity)", + emf.getConfiguration().getDataCache()); + cache = emf.getCache(); + assertNotNull(cache); + } + return emf; + } +} Index: openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/TestCacheModeAllDataCacheTrue.java =================================================================== --- openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/TestCacheModeAllDataCacheTrue.java (revision 0) +++ openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/TestCacheModeAllDataCacheTrue.java (working copy) @@ -0,0 +1,57 @@ +/* + * 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.HashMap; +import java.util.Map; + +import org.apache.openjpa.datacache.ConcurrentDataCache; +import org.apache.openjpa.persistence.OpenJPAEntityManagerFactorySPI; + +/* + * When shared-cache-mode is set to ALL, all entities will be cached no matter + * what is DataCache Types/ExcludedTypes setting. The other DataCache + * config settings like CacheSize will be used to config the data cache. + */ +public class TestCacheModeAllDataCacheTrue extends TestCacheModeAll{ + + @Override + public OpenJPAEntityManagerFactorySPI getEntityManagerFactory() { + Map props = new HashMap(); + props.put("openjpa.DataCache", "true(CacheSize=5000, " + + "ExcludedTypes=org.apache.openjpa.persistence.cache.jpa.model.UncacheableEntity)"); + props.put("openjpa.RemoteCommitProvider", "sjvm"); + if (emf == null) { + emf = createEntityManagerFactory("cache-mode-all",props); + assertNotNull(emf); + ConcurrentDataCache dataCache = (ConcurrentDataCache) emf.getConfiguration() + .getDataCacheManagerInstance().getDataCache("default"); + assertNotNull(dataCache); + assertEquals(5000, dataCache.getCacheSize()); + assertEquals("true(CacheSize=5000, ExcludedTypes=" + + "org.apache.openjpa.persistence.cache.jpa.model.UncacheableEntity)", + emf.getConfiguration().getDataCache()); + cache = emf.getCache(); + assertNotNull(cache); + } + return emf; + } + +} Index: openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/TestCacheModeInvalid.java =================================================================== --- openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/TestCacheModeInvalid.java (revision 1384400) +++ openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/TestCacheModeInvalid.java (working copy) @@ -32,9 +32,7 @@ public void testInvalidElement() { boolean exceptionCaught = false; try { - Map propertiesMap = getPropertiesMap("openjpa.DataCache", "true", - "openjpa.QueryCache", "true", - "openjpa.RemoteCommitProvider", "sjvm", persistentTypes, + Map propertiesMap = getPropertiesMap(persistentTypes, "openjpa.jdbc.JDBCListeners", new JDBCListener [] { getListener() }); emf = (OpenJPAEntityManagerFactorySPI) OpenJPAPersistence.createEntityManagerFactory("cache-mode-invalid", "META-INF/caching-persistence-invalid.xml", propertiesMap ); Index: openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/AbstractCacheTestCase.java =================================================================== --- openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/AbstractCacheTestCase.java (revision 1384400) +++ openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/AbstractCacheTestCase.java (working copy) @@ -66,9 +66,7 @@ public OpenJPAEntityManagerFactorySPI createEntityManagerFactory(String puName, Map additionalProperties) { - Map propertiesMap = getPropertiesMap("openjpa.DataCache", "true", - "openjpa.QueryCache", "true", - "openjpa.RemoteCommitProvider", "sjvm", persistentTypes, + Map propertiesMap = getPropertiesMap( persistentTypes, "openjpa.jdbc.JDBCListeners", new JDBCListener [] { getListener() }); if (additionalProperties != null) { Set keys = additionalProperties.keySet(); Index: openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/TestCacheModeEnableSelective.java =================================================================== --- openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/TestCacheModeEnableSelective.java (revision 1384400) +++ openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/TestCacheModeEnableSelective.java (working copy) @@ -35,7 +35,7 @@ public class TestCacheModeEnableSelective extends AbstractCacheModeTestCase { - private static Cache cache = null; + protected static Cache cache = null; private static List sql = new ArrayList(); private static JDBCListener listener; @@ -49,6 +49,7 @@ if (emf == null) { emf = createEntityManagerFactory("cache-mode-enable", null); assertNotNull(emf); + assertEquals("true", emf.getConfiguration().getDataCache()); cache = emf.getCache(); assertNotNull(cache); } Index: openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/AbstractCacheModeTestCase.java =================================================================== --- openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/AbstractCacheModeTestCase.java (revision 1384400) +++ openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/AbstractCacheModeTestCase.java (working copy) @@ -24,11 +24,8 @@ import javax.persistence.CacheRetrieveMode; import javax.persistence.CacheStoreMode; import javax.persistence.EntityManager; -import javax.persistence.LockModeType; import org.apache.openjpa.jdbc.meta.ClassMapping; -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.OpenJPAEntityManagerSPI; import org.apache.openjpa.persistence.cache.jpa.model.CacheEntity; @@ -206,28 +203,30 @@ * */ 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)); + if (getCacheEnabled()) { + 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(); } - 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)); + }); + 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(); } - em.close(); - } - }, getExpectedNotInCache().length); + }, getExpectedNotInCache().length); + } } public void updateAndFind(Class classToUpdate, int idToUpdate, @@ -407,45 +406,50 @@ } public void testResultsFromQueryAreInCache() { - // clear cache - getEntityManagerFactory().getStoreCache().evictAll(); - getEntityManagerFactory().getQueryResultCache().evictAll(); + if (getCacheEnabled()) { + // clear cache + getEntityManagerFactory().getStoreCache().evictAll(); + getEntityManagerFactory().getQueryResultCache().evictAll(); - EntityManager em = getEntityManagerFactory().createEntityManager(); - String query; - for(Class cls : persistentTypes) { - query = "Select e from " + getAlias(cls) + " e"; - List res = em.createQuery(query).getResultList(); - assertNotNull(String.format("Expected to find some results when running query %s",query), res); - assertTrue(String.format("Expected more than 0 results running query %s",query),res.size() != 0 ) ; + EntityManager em = getEntityManagerFactory().createEntityManager(); + String query; + for(Class cls : persistentTypes) { + query = "Select e from " + getAlias(cls) + " e"; + List res = em.createQuery(query).getResultList(); + assertNotNull(String.format("Expected to find some results when running query %s",query), res); + assertTrue(String.format("Expected more than 0 results running query %s",query),res.size() != 0 ) ; + } + for(Class cls : getExpectedInCache()) { + assertCached(getEntityManagerFactory().getCache(), cls, 1, true); + } + + for(Class cls : getExpectedNotInCache()) { + assertCached(getEntityManagerFactory().getCache(), cls, 1, false); + } + em.close(); } - for(Class cls : getExpectedInCache()) { - assertCached(getEntityManagerFactory().getCache(), cls, 1, true); - } - - for(Class cls : getExpectedNotInCache()) { - assertCached(getEntityManagerFactory().getCache(), cls, 1, false); - } - em.close(); } public void testResultsFromFindAreInCache() { - // clear cache - getEntityManagerFactory().getStoreCache().evictAll(); - getEntityManagerFactory().getQueryResultCache().evictAll(); + if (getCacheEnabled()) { + // clear cache + getEntityManagerFactory().getStoreCache().evictAll(); + getEntityManagerFactory().getQueryResultCache().evictAll(); - EntityManager em = getEntityManagerFactory().createEntityManager(); - for(Class cls : persistentTypes) { - assertNotNull(String.format("Expected to find %s::%d from database or from cache", cls, 1),em.find(cls, 1)); + EntityManager em = getEntityManagerFactory().createEntityManager(); + for(Class cls : persistentTypes) { + assertNotNull(String.format("Expected to find %s::%d from database or from cache", cls, 1), + em.find(cls, 1)); + } + for(Class cls : getExpectedInCache()) { + assertCached(getEntityManagerFactory().getCache(), cls, 1, true); + } + + for(Class cls : getExpectedNotInCache()) { + assertCached(getEntityManagerFactory().getCache(), cls, 1, false); + } + em.close(); } - for(Class cls : getExpectedInCache()) { - assertCached(getEntityManagerFactory().getCache(), cls, 1, true); - } - - for(Class cls : getExpectedNotInCache()) { - assertCached(getEntityManagerFactory().getCache(), cls, 1, false); - } - em.close(); } private String getAlias(Class cls) { Index: openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/TestCacheModeNone.java =================================================================== --- openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/TestCacheModeNone.java (revision 1384400) +++ openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/TestCacheModeNone.java (working copy) @@ -27,9 +27,12 @@ import org.apache.openjpa.persistence.OpenJPAEntityManagerFactorySPI; import org.apache.openjpa.persistence.test.FilteringJDBCListener; +/* + * When shared-cache-mode is NONE and dataCache is not set, caching will be off. + */ public class TestCacheModeNone extends AbstractCacheModeTestCase { - private static Cache cache = null; + protected static Cache cache = null; private static List sql = new ArrayList(); private static JDBCListener listener; @@ -40,6 +43,7 @@ public OpenJPAEntityManagerFactorySPI getEntityManagerFactory() { if (emf == null) { emf = createEntityManagerFactory("cache-mode-none",null); + assertEquals("false", emf.getConfiguration().getDataCache()); assertNotNull(emf); cache = emf.getCache(); assertNotNull(cache); Index: openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/TestCacheModeDisableSelective.java =================================================================== --- openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/TestCacheModeDisableSelective.java (revision 1384400) +++ openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/TestCacheModeDisableSelective.java (working copy) @@ -35,7 +35,7 @@ public class TestCacheModeDisableSelective extends AbstractCacheModeTestCase { - private static Cache cache = null; + protected static Cache cache = null; private static List sql = new ArrayList(); private static JDBCListener listener; @@ -49,6 +49,7 @@ if (emf == null) { emf = createEntityManagerFactory("cache-mode-disable", null); assertNotNull(emf); + assertEquals("true", emf.getConfiguration().getDataCache()); cache = emf.getCache(); assertNotNull(cache); } Index: openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/TestCacheModeAll.java =================================================================== --- openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/TestCacheModeAll.java (revision 1384400) +++ openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/TestCacheModeAll.java (working copy) @@ -23,13 +23,19 @@ import javax.persistence.Cache; +import org.apache.openjpa.datacache.ConcurrentDataCache; import org.apache.openjpa.lib.jdbc.JDBCListener; import org.apache.openjpa.persistence.OpenJPAEntityManagerFactorySPI; import org.apache.openjpa.persistence.test.FilteringJDBCListener; +/* + * When shared-cache-mode is set to ALL, all entities will be cached. + * If the DataCache is not configured, the default values will be used. + * For example, CacheSize will be set to default value 1000. + */ public class TestCacheModeAll extends AbstractCacheModeTestCase { - private static Cache cache = null; + protected static Cache cache = null; private static List sql = new ArrayList(); private static JDBCListener listener; @@ -41,6 +47,11 @@ if (emf == null) { emf = createEntityManagerFactory("cache-mode-all",null); assertNotNull(emf); + ConcurrentDataCache dataCache = (ConcurrentDataCache) emf.getConfiguration() + .getDataCacheManagerInstance().getDataCache("default"); + assertNotNull(dataCache); + assertEquals(1000, dataCache.getCacheSize()); + assertEquals("true", emf.getConfiguration().getDataCache()); cache = emf.getCache(); assertNotNull(cache); } Index: openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/TestCacheModeUnspecifiedDataCacheTrue.java =================================================================== --- openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/TestCacheModeUnspecifiedDataCacheTrue.java (revision 0) +++ openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/TestCacheModeUnspecifiedDataCacheTrue.java (working copy) @@ -0,0 +1,90 @@ +/* + * 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.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.persistence.Cache; + +import org.apache.openjpa.lib.jdbc.JDBCListener; +import org.apache.openjpa.persistence.OpenJPAEntityManagerFactorySPI; +import org.apache.openjpa.persistence.test.FilteringJDBCListener; + +/* + * When shared-cache-mode is UNSPECIFIED and dataCache is true, caching will be on. + */ +public class TestCacheModeUnspecifiedDataCacheTrue extends AbstractCacheModeTestCase{ + private static Cache cache = null; + private static List sql = new ArrayList(); + private static JDBCListener listener; + + private static Class[] expectedInCache = persistentTypes; + private static Class[] expectedNotInCache = {}; + + @Override + public OpenJPAEntityManagerFactorySPI getEntityManagerFactory() { + Map props = new HashMap(); + props.put("openjpa.DataCache", "true"); + props.put("openjpa.RemoteCommitProvider", "sjvm"); + if (emf == null) { + emf = createEntityManagerFactory("cache-mode-unspecified", props); + assertNotNull(emf); + cache = emf.getCache(); + assertNotNull(cache); + } + return emf; + } + + public JDBCListener getListener() { + if (listener == null) { + listener = new FilteringJDBCListener(getSql()); + } + return listener; + } + + public List getSql() { + return sql; + } + + public void testCacheables() { + assertCacheables(cache, true); + } + + public void testUncacheables() { + assertUncacheables(cache, true); + } + + public void testUnspecified() { + assertUnspecified(cache, true); + } + + @Override + protected Class[] getExpectedInCache() { + return expectedInCache; + } + + @Override + protected Class[] getExpectedNotInCache() { + return expectedNotInCache; + } +} Index: openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/TestCacheModeNoneDataCacheTrue.java =================================================================== --- openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/TestCacheModeNoneDataCacheTrue.java (revision 0) +++ openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/TestCacheModeNoneDataCacheTrue.java (working copy) @@ -0,0 +1,47 @@ +/* + * 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.HashMap; +import java.util.Map; + +import org.apache.openjpa.persistence.OpenJPAEntityManagerFactorySPI; + +/* + * Caching is off when shared cache mode is set to NONE no matter + * dataCache is set to true or not. + * */ +public class TestCacheModeNoneDataCacheTrue extends TestCacheModeNone{ + @Override + public OpenJPAEntityManagerFactorySPI getEntityManagerFactory() { + Map props = new HashMap(); + props.put("openjpa.DataCache", "true"); + props.put("openjpa.RemoteCommitProvider", "sjvm"); + if (emf == null) { + emf = createEntityManagerFactory("cache-mode-none",props); + assertNotNull(emf); + assertEquals("true", emf.getConfiguration().getDataCache()); + cache = emf.getCache(); + assertNotNull(cache); + } + return emf; + } + +} Index: openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/TestCacheModeEnableSelectedDataCacheTrue.java =================================================================== --- openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/TestCacheModeEnableSelectedDataCacheTrue.java (revision 0) +++ openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/TestCacheModeEnableSelectedDataCacheTrue.java (working copy) @@ -0,0 +1,52 @@ +/* + * 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.HashMap; +import java.util.Map; + +import org.apache.openjpa.persistence.OpenJPAEntityManagerFactorySPI; +/* + * When ENABLE_SELECTIVE is set for the shared-cache-mode element and an entity is marked as cacheable(true), + * the entity will be cached even though DataCache ExcludedTypes indicate it should be excluded + * since shared-cache-mode take the precedence. + */ +public class TestCacheModeEnableSelectedDataCacheTrue extends TestCacheModeEnableSelective{ + + @Override + public OpenJPAEntityManagerFactorySPI getEntityManagerFactory() { + Map props = new HashMap(); + //exclude types will be ignored since shared cache mode take precedence + props.put("openjpa.DataCache", "true(ExcludedTypes=" + + "org.apache.openjpa.persistence.cache.jpa.model.CacheableEntity)"); + props.put("openjpa.RemoteCommitProvider", "sjvm"); + if (emf == null) { + emf = createEntityManagerFactory("cache-mode-enable", props); + assertNotNull(emf); + assertEquals("true(ExcludedTypes=" + + "org.apache.openjpa.persistence.cache.jpa.model.CacheableEntity)", + emf.getConfiguration().getDataCache()); + cache = emf.getCache(); + assertNotNull(cache); + } + return emf; + } + +} Index: openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/TestCacheModeDisableSelectiveDataCacheTrue.java =================================================================== --- openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/TestCacheModeDisableSelectiveDataCacheTrue.java (revision 0) +++ openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/TestCacheModeDisableSelectiveDataCacheTrue.java (working copy) @@ -0,0 +1,49 @@ +/* + * 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.HashMap; +import java.util.Map; + +import org.apache.openjpa.persistence.OpenJPAEntityManagerFactorySPI; +/* + * When DISABLE_SELECTIVE is set for the shared-cache-mode element and a entity is marked as Cacheable(false), + * the entity will not be cached even though DataCache Types indicate it should be included + * since shared-cache-mode take the precedence. + */ +public class TestCacheModeDisableSelectiveDataCacheTrue extends TestCacheModeDisableSelective{ + @Override + public OpenJPAEntityManagerFactorySPI getEntityManagerFactory() { + Map props = new HashMap(); + //include types will be ignored since the shared cache mode take precedence + props.put("openjpa.DataCache", "true(Types=" + + "org.apache.openjpa.persistence.cache.jpa.model.UncacheableEntity)"); + if (emf == null) { + emf = createEntityManagerFactory("cache-mode-disable", props); + assertNotNull(emf); + assertEquals("true(Types=" + + "org.apache.openjpa.persistence.cache.jpa.model.UncacheableEntity)", + emf.getConfiguration().getDataCache()); + cache = emf.getCache(); + assertNotNull(cache); + } + return emf; + } +} Index: openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/TestCacheModeAllDataCacheCustomized.java =================================================================== --- openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/TestCacheModeAllDataCacheCustomized.java (revision 0) +++ openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/TestCacheModeAllDataCacheCustomized.java (working copy) @@ -0,0 +1,58 @@ +/* + * 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.HashMap; +import java.util.Map; + +import org.apache.openjpa.datacache.ConcurrentDataCache; +import org.apache.openjpa.persistence.OpenJPAEntityManagerFactorySPI; + +/* + * When shared-cache-mode is set to ALL, all entities will be cached no matter + * what is the customized DataCache setting. The other DataCache + * config settings like CacheSize will be used to config the data cache. + */ +public class TestCacheModeAllDataCacheCustomized extends TestCacheModeAll{ + @Override + public OpenJPAEntityManagerFactorySPI getEntityManagerFactory() { + Map props = new HashMap(); + props.put("openjpa.DataCache", + "org.apache.openjpa.persistence.cache.jpa.DataCacheTestExtension(CacheSize=5000, " + + "ExcludedTypes=org.apache.openjpa.persistence.cache.jpa.model.UncacheableEntity)"); + props.put("openjpa.RemoteCommitProvider", "sjvm"); + if (emf == null) { + emf = createEntityManagerFactory("cache-mode-all",props); + assertNotNull(emf); + ConcurrentDataCache dataCache = (ConcurrentDataCache) emf.getConfiguration() + .getDataCacheManagerInstance().getDataCache("default"); + assertNotNull(dataCache); + assertEquals(5000, dataCache.getCacheSize()); + assertEquals("org.apache.openjpa.persistence.cache.jpa.DataCacheTestExtension(CacheSize=5000, " + + "ExcludedTypes=org.apache.openjpa.persistence.cache.jpa.model.UncacheableEntity)", + emf.getConfiguration().getDataCache()); + cache = emf.getCache(); + assertNotNull(cache); + } + return emf; + } +} + + Index: openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/TestCacheModeUnspecified.java =================================================================== --- openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/TestCacheModeUnspecified.java (revision 1384400) +++ openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/TestCacheModeUnspecified.java (working copy) @@ -27,6 +27,9 @@ import org.apache.openjpa.persistence.OpenJPAEntityManagerFactorySPI; import org.apache.openjpa.persistence.test.FilteringJDBCListener; +/* + * When shared-cache-mode is UNSPECIFIED and dataCache is not set, caching will be off. + */ public class TestCacheModeUnspecified extends AbstractCacheModeTestCase { private static Cache cache = null; @@ -41,6 +44,7 @@ if (emf == null) { emf = createEntityManagerFactory("cache-mode-unspecified", null); assertNotNull(emf); + assertEquals("false", emf.getConfiguration().getDataCache()); cache = emf.getCache(); assertNotNull(cache); } @@ -59,15 +63,15 @@ } public void testCacheables() { - assertCacheables(cache, true); + assertCacheables(cache, false); } public void testUncacheables() { - assertUncacheables(cache, true); + assertUncacheables(cache, false); } public void testUnspecified() { - assertUnspecified(cache, true); + assertUnspecified(cache, false); } @Override @@ -79,4 +83,9 @@ protected Class[] getExpectedNotInCache() { return expectedNotInCache; } + + @Override + public boolean getCacheEnabled() { + return false; + } } Index: openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/TestCacheModeEmpty.java =================================================================== --- openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/TestCacheModeEmpty.java (revision 1384400) +++ openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/TestCacheModeEmpty.java (working copy) @@ -18,6 +18,9 @@ */ package org.apache.openjpa.persistence.cache.jpa; +/* + * When both shared-cache-mode and dataCache are not set, caching will be off. + */ import java.util.ArrayList; import java.util.List; @@ -41,6 +44,7 @@ if (emf == null) { emf = createEntityManagerFactory("cache-mode-empty", null); assertNotNull(emf); + assertEquals("false", emf.getConfiguration().getDataCache()); cache = emf.getCache(); assertNotNull(cache); } @@ -59,15 +63,15 @@ } public void testCacheables() { - assertCacheables(cache, true); + assertCacheables(cache, false); } public void testUncacheables() { - assertUncacheables(cache, true); + assertUncacheables(cache, false); } public void testUnspecified() { - assertUnspecified(cache, true); + assertUnspecified(cache, false); } @Override @@ -79,4 +83,9 @@ protected Class[] getExpectedNotInCache() { return expectedNotInCache; } + + @Override + public boolean getCacheEnabled() { + return false; + } } Index: openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/DataCacheTestExtension.java =================================================================== --- openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/DataCacheTestExtension.java (revision 0) +++ openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/DataCacheTestExtension.java (working copy) @@ -0,0 +1,28 @@ +/* + * 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 org.apache.openjpa.datacache.ConcurrentDataCache; + +public class DataCacheTestExtension extends ConcurrentDataCache { + + private static final long serialVersionUID = 1L; + +} Index: openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/TestPropertyCacheModeUnspecified.java =================================================================== --- openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/TestPropertyCacheModeUnspecified.java (revision 1384400) +++ openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/cache/jpa/TestPropertyCacheModeUnspecified.java (working copy) @@ -29,6 +29,9 @@ import org.apache.openjpa.persistence.OpenJPAEntityManagerFactorySPI; import org.apache.openjpa.persistence.test.FilteringJDBCListener; +/* + * When sharedCache.mode is UNSPECIFIED and dataCache is not set, caching will be off. + */ public class TestPropertyCacheModeUnspecified extends AbstractCacheModeTestCase { private static Cache cache = null; @@ -63,15 +66,15 @@ } public void testCacheables() { - assertCacheables(cache, true); + assertCacheables(cache, false); } public void testUncacheables() { - assertUncacheables(cache, true); + assertUncacheables(cache, false); } public void testUnspecified() { - assertUnspecified(cache, true); + assertUnspecified(cache, false); } @Override @@ -83,4 +86,9 @@ protected Class[] getExpectedNotInCache() { return expectedNotInCache; } + + @Override + public boolean getCacheEnabled() { + return false; + } } Index: openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java =================================================================== --- openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java (revision 1378157) +++ openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java (working copy) @@ -352,14 +352,10 @@ pc.pcReplaceStateManager(this); FieldMetaData[] fmds = _meta.getFields(); - _loaded = new BitSet(fmds.length); + // mark primary key and non-persistent fields as loaded + _loaded = _meta.getPkAndNonPersistentManagedFmdBitSet(); _flush = new BitSet(fmds.length); - _dirty = new BitSet(fmds.length); - - // mark primary key and non-persistent fields as loaded - for(int i : _meta.getPkAndNonPersistentManagedFmdIndexes()){ - _loaded.set(i); - } + _dirty = new BitSet(fmds.length); _mappedByIdFields = _meta.getMappyedByIdFields(); @@ -3277,7 +3273,7 @@ // no listeners? LifecycleEventManager mgr = _broker.getLifecycleEventManager(); - if (mgr == null || !mgr.hasLoadListeners(getManagedInstance(), _meta)) + if (mgr == null || !mgr.isActive(_meta) || !mgr.hasLoadListeners(getManagedInstance(), _meta)) return; if (fetch == null) Index: openjpa-kernel/src/main/java/org/apache/openjpa/meta/ClassMetaData.java =================================================================== --- openjpa-kernel/src/main/java/org/apache/openjpa/meta/ClassMetaData.java (revision 1378157) +++ openjpa-kernel/src/main/java/org/apache/openjpa/meta/ClassMetaData.java (working copy) @@ -25,6 +25,7 @@ import java.security.AccessController; import java.util.ArrayList; import java.util.Arrays; +import java.util.BitSet; import java.util.Collection; import java.util.Collections; import java.util.Comparator; @@ -219,7 +220,7 @@ private boolean _abstract = false; private Boolean _hasAbstractPKField = null; private Boolean _hasPKFieldsFromAbstractClass = null; - private int[] _pkAndNonPersistentManagedFmdIndexes = null; + private BitSet _pkAndNonPersistentManagedFmdBitSet = null; private Boolean inverseManagedFields = null; private List _mappedByIdFields; private boolean _mappedByIdFieldsSet = false; @@ -2768,21 +2769,17 @@ return _srcName; } - public int[] getPkAndNonPersistentManagedFmdIndexes() { - if (_pkAndNonPersistentManagedFmdIndexes == null) { - List ids = new ArrayList(); - for (FieldMetaData fmd : getFields()) { + public BitSet getPkAndNonPersistentManagedFmdBitSet() { + if (_pkAndNonPersistentManagedFmdBitSet == null) { + FieldMetaData[] fmds = getFields(); + _pkAndNonPersistentManagedFmdBitSet = new BitSet(fmds.length); + for (FieldMetaData fmd : fmds) { if (fmd.isPrimaryKey() || fmd.getManagement() != FieldMetaData.MANAGE_PERSISTENT) { - ids.add(fmd.getIndex()); + _pkAndNonPersistentManagedFmdBitSet.set(fmd.getIndex()); } } - int idsSize = ids.size(); - _pkAndNonPersistentManagedFmdIndexes = new int[idsSize]; - for(int i = 0; i types) { _includedTypes = types; + if (log.isWarnEnabled()) + log.warn(s_loc.get("recommend_jpa2_caching", new Object[]{"Types", + DataCacheMode.ENABLE_SELECTIVE.toString()})); } public void setTypes(String types) { _includedTypes = StringUtils.isEmpty(types) ? null : new HashSet(Arrays.asList(Strings.split(types, ";", 0))); + if (log.isWarnEnabled()) + log.warn(s_loc.get("recommend_jpa2_caching", new Object[]{"Types", + DataCacheMode.ENABLE_SELECTIVE.toString()})); } public void setExcludedTypes(Set types) { _excludedTypes = types; + if (log.isWarnEnabled()) + log.warn(s_loc.get("recommend_jpa2_caching", new Object[]{"ExcludeTypes", + DataCacheMode.DISABLE_SELECTIVE.toString()})); } public void setExcludedTypes(String types) { _excludedTypes = StringUtils.isEmpty(types) ? null : new HashSet(Arrays.asList(Strings.split(types, ";", 0))); + if (log.isWarnEnabled()) + log.warn(s_loc.get("recommend_jpa2_caching", new Object[]{"ExcludeTypes", + DataCacheMode.DISABLE_SELECTIVE.toString()})); } public DataCache selectCache(OpenJPAStateManager sm) { Index: openjpa-kernel/src/main/resources/org/apache/openjpa/datacache/localizer.properties =================================================================== --- openjpa-kernel/src/main/resources/org/apache/openjpa/datacache/localizer.properties (revision 1378157) +++ openjpa-kernel/src/main/resources/org/apache/openjpa/datacache/localizer.properties (working copy) @@ -113,5 +113,7 @@ partition in the configuration "{0}". The partition name matches the default \ name reserved by OpenJPA for internal use and hence can not be used. invalid-types-excluded-types: Failed to configure openjpa.DataCache Types, ExcludedTypes. \ - Types "{0}" were found in both lists, but can only appear one of the lists. - \ No newline at end of file + Types "{0}" were found in both lists, but can only appear one of the lists. +recommend_jpa2_caching: You have specified the DataCache property "{0}", but using that \ + property is not recommended. Please utilize the JPA 2.0 shared-cache-mode element "{1}" \ + in conjunction with the javax.persistence.Cacheable annotation instead. Index: openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceProductDerivation.java =================================================================== --- openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceProductDerivation.java (revision 1378157) +++ openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceProductDerivation.java (working copy) @@ -698,11 +698,28 @@ // those. if (conf instanceof OpenJPAConfiguration) { OpenJPAConfiguration oconf = (OpenJPAConfiguration) conf; - // If the datacache is enabled, make sure we have a RemoteCommitProvider - String dc = oconf.getDataCache(); + String dataCache = oconf.getDataCache(); + String sharedDataCacheMode = oconf.getDataCacheMode(); + + if (DataCacheMode.NONE.toString().equals(sharedDataCacheMode) + && dataCache != null && !"false".equals(dataCache)) { + Log log = conf.getConfigurationLog(); + if (log.isWarnEnabled()) { + log.warn(_loc.get("shared-cache-mode-take-precedence", dataCache)); + } + } + + if ((dataCache == null || "false".equals(dataCache)) + && !DataCacheMode.NONE.toString().equals(sharedDataCacheMode) + && !DataCacheMode.UNSPECIFIED.toString().equals(sharedDataCacheMode)){ + oconf.setDataCache("true"); + } + + // If the datacache is enabled, make sure we have a RemoteCommitProvider String rcp = oconf.getRemoteCommitProvider(); + dataCache = oconf.getDataCache(); // If the datacache is set and is something other than false - if (dc != null && !"false".equals(dc)) { + if (dataCache != null && !"false".equals(dataCache)) { // If RCP is null or empty, set it to sjvm. if (rcp == null || "".equals(rcp)) { oconf.setRemoteCommitProvider("sjvm"); Index: openjpa-persistence/src/main/resources/org/apache/openjpa/persistence/localizer.properties =================================================================== --- openjpa-persistence/src/main/resources/org/apache/openjpa/persistence/localizer.properties (revision 1378157) +++ openjpa-persistence/src/main/resources/org/apache/openjpa/persistence/localizer.properties (working copy) @@ -254,3 +254,5 @@ connection will not be released until the EntityManager is closed. If the application uses container managed \ EntityManagers this property should not be used because these EntityManagers may remain open for extended periods of \ time. +shared-cache-mode-take-precedence: The DataCache is set to {0} while the shared-cache-mode Element or \ +javax.persistence.sharedCache.mode property is set to NONE. The shared-cache-mode take the precedence and caching will be disabled. \ No newline at end of file