OPENJPA-2414: FinderCache does not consider active Fetch Groups/FetchPlan added Fields

git-svn-id: https://svn.apache.org/repos/asf/openjpa/branches/2.1.x@1516197 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Jody Grassel 2013-08-21 16:15:00 +00:00
parent 3c5b28e49e
commit 3edd740d81
5 changed files with 1007 additions and 12 deletions

View File

@ -107,6 +107,12 @@ public class FinderCacheImpl
if (fetch.getReadLockLevel() != 0) {
return null;
}
// FinderCache only operates with Default Fetch Plans
if (!fetch.isDefaultPUFetchGroupConfigurationOnly()) {
return null;
}
boolean ignore = isHinted(fetch, QueryHints.HINT_IGNORE_FINDER);
boolean invalidate = isHinted(fetch, QueryHints.HINT_INVALIDATE_FINDER);
if (invalidate) {
@ -144,6 +150,12 @@ public class FinderCacheImpl
if (fetch.getReadLockLevel() != 0) {
return null;
}
// FinderCache only operates with Default Fetch Plans
if (!fetch.isDefaultPUFetchGroupConfigurationOnly()) {
return null;
}
boolean recache = isHinted(fetch, QueryHints.HINT_RECACHE_FINDER);
if (isExcluded(mapping)) {
return recache ? put(mapping, select) : null;

View File

@ -587,4 +587,12 @@ public class DelegatingFetchConfiguration
throw translate(re);
}
}
public boolean isDefaultPUFetchGroupConfigurationOnly() {
try {
return _fetch.isDefaultPUFetchGroupConfigurationOnly();
} catch (RuntimeException re) {
throw translate(re);
}
}
}

View File

@ -468,4 +468,10 @@ public interface FetchConfiguration
* @since 0.4.1
*/
public FetchConfiguration traverse(FieldMetaData fm);
/**
* Affirm if the Fetch Plan currently matches the Persistence Unit's configured default.
*
*/
public boolean isDefaultPUFetchGroupConfigurationOnly();
}

View File

@ -145,6 +145,7 @@ public class FetchConfigurationImpl
public Map<String,Object> hints = null;
public boolean fetchGroupContainsDefault = false;
public boolean fetchGroupContainsAll = false;
public boolean fetchGroupIsPUDefault = false;
public boolean extendedPathLookup = false;
public DataCacheRetrieveMode cacheRetrieveMode = DataCacheRetrieveMode.USE;
public DataCacheStoreMode cacheStoreMode = DataCacheStoreMode.USE;
@ -328,17 +329,21 @@ public class FetchConfigurationImpl
|| _state.fetchGroups.contains(FetchGroup.NAME_ALL));
}
public boolean hasFetchGroupDefault() {
// Fetch group All includes fetch group Default by definition
return _state.fetchGroupContainsDefault ||
_state.fetchGroupContainsAll;
}
public boolean hasFetchGroupAll() {
return _state.fetchGroupContainsAll;
}
public boolean hasFetchGroupDefault() {
// Fetch group All includes fetch group Default by definition
return _state.fetchGroupContainsDefault ||
_state.fetchGroupContainsAll;
}
public boolean hasFetchGroupAll() {
return _state.fetchGroupContainsAll;
}
public FetchConfiguration addFetchGroup(String name) {
return addFetchGroup(name, true);
}
private FetchConfiguration addFetchGroup(String name, boolean recomputeIsDefault) {
if (StringUtils.isEmpty(name))
throw new UserException(_loc.get("null-fg"));
@ -352,6 +357,9 @@ public class FetchConfigurationImpl
else if (FetchGroup.NAME_DEFAULT.equals(name))
_state.fetchGroupContainsDefault = true;
} finally {
if (recomputeIsDefault) {
verifyDefaultPUFetchGroups();
}
unlock();
}
return this;
@ -361,11 +369,17 @@ public class FetchConfigurationImpl
if (groups == null || groups.isEmpty())
return this;
for (String group : groups)
addFetchGroup(group);
addFetchGroup(group, false);
verifyDefaultPUFetchGroups();
return this;
}
public FetchConfiguration removeFetchGroup(String group) {
return removeFetchGroup(group, true);
}
private FetchConfiguration removeFetchGroup(String group, boolean recomputeIsDefault) {
lock();
try {
if (_state.fetchGroups != null) {
@ -376,6 +390,9 @@ public class FetchConfigurationImpl
_state.fetchGroupContainsDefault = false;
}
} finally {
if (recomputeIsDefault) {
verifyDefaultPUFetchGroups();
}
unlock();
}
return this;
@ -386,8 +403,9 @@ public class FetchConfigurationImpl
try {
if (_state.fetchGroups != null && groups != null)
for (String group : groups)
removeFetchGroup(group);
removeFetchGroup(group, false);
} finally {
verifyDefaultPUFetchGroups();
unlock();
}
return this;
@ -402,6 +420,7 @@ public class FetchConfigurationImpl
_state.fetchGroupContainsDefault = true;
}
} finally {
verifyDefaultPUFetchGroups();
unlock();
}
return this;
@ -414,6 +433,37 @@ public class FetchConfigurationImpl
getFetchGroupsList()));
return this;
}
/**
* Determine if the current selection of FetchGroups is equivalent to the Configuration's default FetchGroups
*
*/
private void verifyDefaultPUFetchGroups() {
_state.fetchGroupIsPUDefault = false;
if (_state.fields != null && !_state.fields.isEmpty()) {
return;
}
if (_state.fetchGroups != null && _state.ctx != null) {
List<String> defaultPUFetchGroups = Arrays.asList(_state.ctx.getConfiguration().getFetchGroupsList());
if (_state.fetchGroups.size() != defaultPUFetchGroups.size()) {
return;
}
for (String fetchGroupName : defaultPUFetchGroups) {
if (!_state.fetchGroups.contains(fetchGroupName)) {
return;
}
}
_state.fetchGroupIsPUDefault = true;
}
}
public boolean isDefaultPUFetchGroupConfigurationOnly() {
return _state.fetchGroupIsPUDefault;
}
public Set<String> getFields() {
if (_state.fields == null) return Collections.emptySet();

View File

@ -0,0 +1,919 @@
/*
* 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.fetchgroups;
import java.util.HashSet;
import org.apache.openjpa.persistence.FetchPlan;
import org.apache.openjpa.persistence.OpenJPAEntityManager;
import org.apache.openjpa.persistence.OpenJPAEntityManagerFactory;
import org.apache.openjpa.persistence.test.SingleEMTestCase;
public class TestFetchGroups extends SingleEMTestCase {
private static final int empPerMgr = 5;
private static final int mgrCount = 3;
private static final int empCount = mgrCount * empPerMgr;
private HashSet<FGEmployee> employeeSet = new HashSet<FGEmployee>();
private HashSet<FGManager> managerSet = new HashSet<FGManager>();
public void setUp() {
super.setUp(CLEAR_TABLES,
FGManager.class, FGDepartment.class, FGEmployee.class, FGAddress.class);
createEmployeeData();
}
/**
* Verify the "default" fetch plan that models JPA's expected eager/lazy fetch load behaviors.
*/
public void testDefaultFetchPlan001() {
OpenJPAEntityManager em = emf.createEntityManager();
FetchPlan fp = em.getFetchPlan();
assertNotNull(fp);
assertNotNull(fp.getFetchGroups());
assertEquals(1, fp.getFetchGroups().size());
assertTrue(fp.getFetchGroups().contains("default"));
FGManager mgr = managerSet.iterator().next();
assertNotNull(mgr);
FGManager findMgr = em.find(FGManager.class, mgr.getId());
em.close();
assertEquals(mgr.getId(), findMgr.getId());
assertEquals(mgr.getFirstName(), findMgr.getFirstName());
assertEquals(mgr.getLastName(), findMgr.getLastName());
assertNull(findMgr.getDescription()); // Should be lazy-loaded
}
/**
* Verify that adding a FetchGroup to the fetch plan makes a normally JPA determined lazy loaded
* field to behave as an eagerly loaded field.
*/
public void testDefaultFetchPlan002() {
OpenJPAEntityManager em = emf.createEntityManager();
FetchPlan fp = em.getFetchPlan();
assertNotNull(fp);
fp.addFetchGroup("DescFetchGroup");
assertNotNull(fp.getFetchGroups());
assertEquals(2, fp.getFetchGroups().size());
assertTrue(fp.getFetchGroups().contains("default"));
assertTrue(fp.getFetchGroups().contains("DescFetchGroup"));
FGManager mgr = managerSet.iterator().next();
assertNotNull(mgr);
FGManager findMgr = em.find(FGManager.class, mgr.getId());
em.close();
assertEquals(mgr.getId(), findMgr.getId());
assertEquals(mgr.getFirstName(), findMgr.getFirstName());
assertEquals(mgr.getLastName(), findMgr.getLastName());
assertEquals(mgr.getDescription(), findMgr.getDescription()); // Should not be lazy-loaded
}
/**
* Verify the use of the "openjpa.FetchGroups" property when used to add a fetch group
* to the default fetch plan. Note when overriding that "default" must be included in the list.
*/
public void testPctxDefaultFetchPlan001() {
OpenJPAEntityManagerFactory emf2 = createNamedEMF(getPersistenceUnitName(),
FGManager.class, FGDepartment.class, FGEmployee.class, FGAddress.class,
"openjpa.FetchGroups", "default,DescFetchGroup");
OpenJPAEntityManager em = emf2.createEntityManager();
FetchPlan fp = em.getFetchPlan();
assertNotNull(fp);
assertNotNull(fp.getFetchGroups());
assertEquals(2, fp.getFetchGroups().size());
assertTrue(fp.getFetchGroups().contains("default"));
assertTrue(fp.getFetchGroups().contains("DescFetchGroup"));
FGManager mgr = managerSet.iterator().next();
assertNotNull(mgr);
FGManager findMgr = em.find(FGManager.class, mgr.getId());
em.close();
emf2.close();
assertEquals(mgr.getId(), findMgr.getId());
assertEquals(mgr.getFirstName(), findMgr.getFirstName());
assertEquals(mgr.getLastName(), findMgr.getLastName());
assertEquals(mgr.getDescription(), findMgr.getDescription()); // Should not be lazy-loaded
}
/**
* Verify the use of the "openjpa.FetchGroups" property - when a list not containing "default"
* is provided, then the PCtx's default fetch plan should not include it. This renders
* fields normally eagerly loaded as per JPA rules to behave as lazy loaded fields.
*
* Note that fetch groups are case sensitive, "default" != "Default".
*/
public void testPctxDefaultFetchPlan002() {
OpenJPAEntityManagerFactory emf2 = createNamedEMF(getPersistenceUnitName(),
FGManager.class, FGDepartment.class, FGEmployee.class, FGAddress.class,
"openjpa.FetchGroups", "Default,DescFetchGroup");
OpenJPAEntityManager em = emf2.createEntityManager();
FetchPlan fp = em.getFetchPlan();
assertNotNull(fp);
assertNotNull(fp.getFetchGroups());
assertEquals(2, fp.getFetchGroups().size());
assertTrue(fp.getFetchGroups().contains("Default")); // Not the same as "default"
assertTrue(fp.getFetchGroups().contains("DescFetchGroup"));
FGManager mgr = managerSet.iterator().next();
assertNotNull(mgr);
FGManager findMgr = em.find(FGManager.class, mgr.getId());
em.close();
emf2.close();
assertEquals(mgr.getId(), findMgr.getId()); // Identity is always loaded
assertNull(findMgr.getFirstName());
assertNull(findMgr.getLastName());
assertEquals(mgr.getDescription(), findMgr.getDescription()); // Should not be lazy-loaded
}
/**
* Test clearFetchGroups(), which removes all fetch groups from the fetch plan and reactivates
* the "default" fetch plan.
*
* Note that the method does not place "default" back in the list of active fetch groups, OPENJPA-2413
* was opened to note this behavior.
*/
public void testClearFetchGroups001() {
OpenJPAEntityManagerFactory emf2 = createNamedEMF(getPersistenceUnitName(),
FGManager.class, FGDepartment.class, FGEmployee.class, FGAddress.class,
"openjpa.FetchGroups", "Default,DescFetchGroup");
OpenJPAEntityManager em = emf2.createEntityManager();
FetchPlan fp = em.getFetchPlan();
assertNotNull(fp);
assertNotNull(fp.getFetchGroups());
assertEquals(2, fp.getFetchGroups().size());
assertTrue(fp.getFetchGroups().contains("Default")); // Not the same as "default"
assertTrue(fp.getFetchGroups().contains("DescFetchGroup"));
fp.clearFetchGroups();
assertNotNull(fp.getFetchGroups());
assertEquals(0, fp.getFetchGroups().size());
FGManager mgr = managerSet.iterator().next();
assertNotNull(mgr);
FGManager findMgr = em.find(FGManager.class, mgr.getId());
em.close();
emf2.close();
assertEquals(mgr.getId(), findMgr.getId());
assertEquals(mgr.getFirstName(), findMgr.getFirstName());
assertEquals(mgr.getLastName(), findMgr.getLastName());
assertNull(findMgr.getDescription()); // Should be lazy-loaded
}
/**
* The resetFetchGroups() method restores the fetch plan's active fetch plans to
* the PCtx's configured default.
*/
public void testResetFetchGroups001() {
OpenJPAEntityManagerFactory emf2 = createNamedEMF(getPersistenceUnitName(),
FGManager.class, FGDepartment.class, FGEmployee.class, FGAddress.class,
"openjpa.FetchGroups", "Default,DescFetchGroup");
OpenJPAEntityManager em = emf2.createEntityManager();
FetchPlan fp = em.getFetchPlan();
assertNotNull(fp);
assertNotNull(fp.getFetchGroups());
assertEquals(2, fp.getFetchGroups().size());
assertTrue(fp.getFetchGroups().contains("Default")); // Not the same as "default"
assertTrue(fp.getFetchGroups().contains("DescFetchGroup"));
// Remember, OPENJPA-2413 sets the list to be empty instead of containing "default"
fp.clearFetchGroups();
assertNotNull(fp.getFetchGroups());
assertEquals(0, fp.getFetchGroups().size());
// Reset to the PCtx default Fetch Plan
fp.resetFetchGroups();
assertNotNull(fp);
assertNotNull(fp.getFetchGroups());
assertEquals(2, fp.getFetchGroups().size());
assertTrue(fp.getFetchGroups().contains("Default")); // Not the same as "default"
assertTrue(fp.getFetchGroups().contains("DescFetchGroup"));
// Verify that the PCtx default fetch plan was properly restored. "default" should not be enabled
// since it was not listed by openjpa.FetchGroups.
FGManager mgr = managerSet.iterator().next();
assertNotNull(mgr);
FGManager findMgr = em.find(FGManager.class, mgr.getId());
em.close();
emf2.close();
assertEquals(mgr.getId(), findMgr.getId()); // Identity is always loaded
// assertNull(findMgr.getFirstName()); // Commented out, for OPENJPA-2420
// assertNull(findMgr.getLastName());
assertEquals(mgr.getDescription(), findMgr.getDescription()); // Should not be lazy-loaded
}
/**
* Baseline test for Finder Cache
*/
public void testFinderCache001() {
OpenJPAEntityManager em = emf.createEntityManager();
FetchPlan fp = em.getFetchPlan();
assertNotNull(fp);
assertNotNull(fp.getFetchGroups());
assertEquals(1, fp.getFetchGroups().size());
assertTrue(fp.getFetchGroups().contains("default"));
FGManager mgr = managerSet.iterator().next();
assertNotNull(mgr);
{
// First find, to prime the Finder Cache
FGManager findMgr = em.find(FGManager.class, mgr.getId());
em.clear();
assertEquals(mgr.getId(), findMgr.getId());
assertEquals(mgr.getFirstName(), findMgr.getFirstName());
assertEquals(mgr.getLastName(), findMgr.getLastName());
assertNull(findMgr.getDescription()); // Should be lazy-loaded
}
{
// Second find, should rely on the finder cache to reuse generated SQL.
FGManager findMgr = em.find(FGManager.class, mgr.getId());
em.clear();
assertEquals(mgr.getId(), findMgr.getId());
assertEquals(mgr.getFirstName(), findMgr.getFirstName());
assertEquals(mgr.getLastName(), findMgr.getLastName());
assertNull(findMgr.getDescription()); // Should be lazy-loaded
}
em.close();
}
/**
* Only SQL generated by the PCtx's default fetch plan should be used by the finder cache,
* as it currently lacks the ability to distinguish fetch plan configuration in its key value.
* The PCtx's default fetch plan is the normal plan not modified by the "openjpa.FetchGroups"
* property.
*
* In this variant, a find using the default fetch plan is first executed to prime the finder cache.
* Finds operating under a modified fetch plan should not utilize sql stored in the finder cache.
*/
public void testFinderCache002() {
OpenJPAEntityManager em = emf.createEntityManager();
FetchPlan fp = em.getFetchPlan();
assertNotNull(fp);
assertNotNull(fp.getFetchGroups());
assertEquals(1, fp.getFetchGroups().size());
assertTrue(fp.getFetchGroups().contains("default"));
FGManager mgr = managerSet.iterator().next();
assertNotNull(mgr);
{
// First find, to prime the Finder Cache
FGManager findMgr = em.find(FGManager.class, mgr.getId());
em.clear();
assertEquals(mgr.getId(), findMgr.getId());
assertEquals(mgr.getFirstName(), findMgr.getFirstName());
assertEquals(mgr.getLastName(), findMgr.getLastName());
assertNull(findMgr.getDescription()); // Should be lazy-loaded
}
{
// Second find, should rely on the finder cache to reuse generated SQL.
FGManager findMgr = em.find(FGManager.class, mgr.getId());
em.clear();
assertEquals(mgr.getId(), findMgr.getId());
assertEquals(mgr.getFirstName(), findMgr.getFirstName());
assertEquals(mgr.getLastName(), findMgr.getLastName());
assertNull(findMgr.getDescription()); // Should be lazy-loaded
}
// Add a fetch group to the fetch plan and verify expected behavior
fp.addFetchGroup("DescFetchGroup");
assertNotNull(fp.getFetchGroups());
assertEquals(2, fp.getFetchGroups().size());
assertTrue(fp.getFetchGroups().contains("default"));
assertTrue(fp.getFetchGroups().contains("DescFetchGroup"));
{
// Second find, should rely on the finder cache to reuse generated SQL.
FGManager findMgr = em.find(FGManager.class, mgr.getId());
em.clear();
assertEquals(mgr.getId(), findMgr.getId());
assertEquals(mgr.getFirstName(), findMgr.getFirstName());
assertEquals(mgr.getLastName(), findMgr.getLastName());
assertEquals(mgr.getDescription(), findMgr.getDescription()); // Should not be lazy-loaded
}
// Remove the fetch group previously added, and verify expected behavior
fp.removeFetchGroup("DescFetchGroup");
assertNotNull(fp.getFetchGroups());
assertEquals(1, fp.getFetchGroups().size());
assertTrue(fp.getFetchGroups().contains("default"));
assertFalse(fp.getFetchGroups().contains("DescFetchGroup"));
{
FGManager findMgr = em.find(FGManager.class, mgr.getId());
em.clear();
assertEquals(mgr.getId(), findMgr.getId());
assertEquals(mgr.getFirstName(), findMgr.getFirstName());
assertEquals(mgr.getLastName(), findMgr.getLastName());
assertNull(findMgr.getDescription()); // Should be lazy-loaded
}
// Add a fetch group to the fetch plan and verify expected behavior
fp.addFetchGroup("DescFetchGroup");
assertNotNull(fp.getFetchGroups());
assertEquals(2, fp.getFetchGroups().size());
assertTrue(fp.getFetchGroups().contains("default"));
assertTrue(fp.getFetchGroups().contains("DescFetchGroup"));
{
// Second find, should rely on the finder cache to reuse generated SQL.
FGManager findMgr = em.find(FGManager.class, mgr.getId());
em.clear();
assertEquals(mgr.getId(), findMgr.getId());
assertEquals(mgr.getFirstName(), findMgr.getFirstName());
assertEquals(mgr.getLastName(), findMgr.getLastName());
assertEquals(mgr.getDescription(), findMgr.getDescription()); // Should not be lazy-loaded
}
// Reset the fetch plan, and verify expected behavior
fp.resetFetchGroups();
assertNotNull(fp.getFetchGroups());
assertEquals(1, fp.getFetchGroups().size());
assertTrue(fp.getFetchGroups().contains("default"));
assertFalse(fp.getFetchGroups().contains("DescFetchGroup"));
{
FGManager findMgr = em.find(FGManager.class, mgr.getId());
em.clear();
assertEquals(mgr.getId(), findMgr.getId());
assertEquals(mgr.getFirstName(), findMgr.getFirstName());
assertEquals(mgr.getLastName(), findMgr.getLastName());
assertNull(findMgr.getDescription()); // Should be lazy-loaded
}
// Add a fetch group to the fetch plan and verify expected behavior
fp.addFetchGroup("DescFetchGroup");
assertNotNull(fp.getFetchGroups());
assertEquals(2, fp.getFetchGroups().size());
assertTrue(fp.getFetchGroups().contains("default"));
assertTrue(fp.getFetchGroups().contains("DescFetchGroup"));
{
// Second find, should rely on the finder cache to reuse generated SQL.
FGManager findMgr = em.find(FGManager.class, mgr.getId());
em.clear();
assertEquals(mgr.getId(), findMgr.getId());
assertEquals(mgr.getFirstName(), findMgr.getFirstName());
assertEquals(mgr.getLastName(), findMgr.getLastName());
assertEquals(mgr.getDescription(), findMgr.getDescription()); // Should not be lazy-loaded
}
// Clear all fetch groups, and verify expected behavior
// Note, due to OPENJPA-2413 even though it behaves as if the "default" fetch group is enabled,
// it will not show up in the list of active fetch groups.
fp.clearFetchGroups();
assertNotNull(fp.getFetchGroups());
assertEquals(0, fp.getFetchGroups().size());
assertFalse(fp.getFetchGroups().contains("default"));
assertFalse(fp.getFetchGroups().contains("DescFetchGroup"));
{
FGManager findMgr = em.find(FGManager.class, mgr.getId());
em.clear();
assertEquals(mgr.getId(), findMgr.getId());
assertEquals(mgr.getFirstName(), findMgr.getFirstName());
assertEquals(mgr.getLastName(), findMgr.getLastName());
assertNull(findMgr.getDescription()); // Should be lazy-loaded
}
em.close();
}
/**
* Only SQL generated by the PCtx's default fetch plan should be used by the finder cache,
* as it currently lacks the ability to distinguish fetch plan configuration in its key value.
* The PCtx's default fetch plan is the normal plan not modified by the "openjpa.FetchGroups"
* property.
*
* In this variant, a find using a modified fetch plan is first executed, which should not be added
* to the finder cache.
*/
public void testFinderCache003() {
OpenJPAEntityManager em = emf.createEntityManager();
FetchPlan fp = em.getFetchPlan();
assertNotNull(fp);
fp.addFetchGroup("DescFetchGroup");
assertNotNull(fp.getFetchGroups());
assertEquals(2, fp.getFetchGroups().size());
assertTrue(fp.getFetchGroups().contains("default"));
assertTrue(fp.getFetchGroups().contains("DescFetchGroup"));
FGManager mgr = managerSet.iterator().next();
assertNotNull(mgr);
{
FGManager findMgr = em.find(FGManager.class, mgr.getId());
em.clear();
assertEquals(mgr.getId(), findMgr.getId());
assertEquals(mgr.getFirstName(), findMgr.getFirstName());
assertEquals(mgr.getLastName(), findMgr.getLastName());
assertEquals(mgr.getDescription(), findMgr.getDescription()); // Should not be lazy-loaded
}
// Remove the "DescFetchGroup" fetch group, and verify expected behavior
fp.removeFetchGroup("DescFetchGroup");
assertNotNull(fp.getFetchGroups());
assertEquals(1, fp.getFetchGroups().size());
assertTrue(fp.getFetchGroups().contains("default"));
assertFalse(fp.getFetchGroups().contains("DescFetchGroup"));
{
FGManager findMgr = em.find(FGManager.class, mgr.getId());
em.clear();
assertEquals(mgr.getId(), findMgr.getId());
assertEquals(mgr.getFirstName(), findMgr.getFirstName());
assertEquals(mgr.getLastName(), findMgr.getLastName());
assertNull(findMgr.getDescription()); // Should be lazy-loaded
}
// Restore the fetch group to the fetch plan and verify expected behavior
fp.addFetchGroup("DescFetchGroup");
assertNotNull(fp.getFetchGroups());
assertEquals(2, fp.getFetchGroups().size());
assertTrue(fp.getFetchGroups().contains("default"));
assertTrue(fp.getFetchGroups().contains("DescFetchGroup"));
{
// Second find, should rely on the finder cache to reuse generated SQL.
FGManager findMgr = em.find(FGManager.class, mgr.getId());
em.clear();
assertEquals(mgr.getId(), findMgr.getId());
assertEquals(mgr.getFirstName(), findMgr.getFirstName());
assertEquals(mgr.getLastName(), findMgr.getLastName());
assertEquals(mgr.getDescription(), findMgr.getDescription()); // Should not be lazy-loaded
}
// Remove the "DescFetchGroup" fetch group, and verify expected behavior
fp.removeFetchGroup("DescFetchGroup");
assertNotNull(fp.getFetchGroups());
assertEquals(1, fp.getFetchGroups().size());
assertTrue(fp.getFetchGroups().contains("default"));
assertFalse(fp.getFetchGroups().contains("DescFetchGroup"));
{
FGManager findMgr = em.find(FGManager.class, mgr.getId());
em.clear();
assertEquals(mgr.getId(), findMgr.getId());
assertEquals(mgr.getFirstName(), findMgr.getFirstName());
assertEquals(mgr.getLastName(), findMgr.getLastName());
assertNull(findMgr.getDescription()); // Should be lazy-loaded
}
// Restore the fetch group to the fetch plan and verify expected behavior
fp.addFetchGroup("DescFetchGroup");
assertNotNull(fp.getFetchGroups());
assertEquals(2, fp.getFetchGroups().size());
assertTrue(fp.getFetchGroups().contains("default"));
assertTrue(fp.getFetchGroups().contains("DescFetchGroup"));
{
// Second find, should rely on the finder cache to reuse generated SQL.
FGManager findMgr = em.find(FGManager.class, mgr.getId());
em.clear();
assertEquals(mgr.getId(), findMgr.getId());
assertEquals(mgr.getFirstName(), findMgr.getFirstName());
assertEquals(mgr.getLastName(), findMgr.getLastName());
assertEquals(mgr.getDescription(), findMgr.getDescription()); // Should not be lazy-loaded
}
// Reset the fetch plan, and verify expected behavior
fp.resetFetchGroups();
assertNotNull(fp.getFetchGroups());
assertEquals(1, fp.getFetchGroups().size());
assertTrue(fp.getFetchGroups().contains("default"));
assertFalse(fp.getFetchGroups().contains("DescFetchGroup"));
{
FGManager findMgr = em.find(FGManager.class, mgr.getId());
em.clear();
assertEquals(mgr.getId(), findMgr.getId());
assertEquals(mgr.getFirstName(), findMgr.getFirstName());
assertEquals(mgr.getLastName(), findMgr.getLastName());
assertNull(findMgr.getDescription()); // Should be lazy-loaded
}
// Restore the fetch group to the fetch plan and verify expected behavior
fp.addFetchGroup("DescFetchGroup");
assertNotNull(fp.getFetchGroups());
assertEquals(2, fp.getFetchGroups().size());
assertTrue(fp.getFetchGroups().contains("default"));
assertTrue(fp.getFetchGroups().contains("DescFetchGroup"));
{
// Second find, should rely on the finder cache to reuse generated SQL.
FGManager findMgr = em.find(FGManager.class, mgr.getId());
em.clear();
assertEquals(mgr.getId(), findMgr.getId());
assertEquals(mgr.getFirstName(), findMgr.getFirstName());
assertEquals(mgr.getLastName(), findMgr.getLastName());
assertEquals(mgr.getDescription(), findMgr.getDescription()); // Should not be lazy-loaded
}
// Clear all fetch groups, and verify expected behavior
// Note, due to OPENJPA-2413 even though it behaves as if the "default" fetch group is enabled,
// it will not show up in the list of active fetch groups.
fp.clearFetchGroups();
assertNotNull(fp.getFetchGroups());
assertEquals(0, fp.getFetchGroups().size());
assertFalse(fp.getFetchGroups().contains("default"));
assertFalse(fp.getFetchGroups().contains("DescFetchGroup"));
{
FGManager findMgr = em.find(FGManager.class, mgr.getId());
em.clear();
assertEquals(mgr.getId(), findMgr.getId());
assertEquals(mgr.getFirstName(), findMgr.getFirstName());
assertEquals(mgr.getLastName(), findMgr.getLastName());
assertNull(findMgr.getDescription()); // Should be lazy-loaded
}
em.close();
}
/**
* Only SQL generated by the PCtx's default fetch plan should be used by the finder cache,
* as it currently lacks the ability to distinguish fetch plan configuration in its key value.
* The PCtx's default fetch plan is modified by the "openjpa.FetchGroups" property.
*
*/
public void testFinderCache004() {
OpenJPAEntityManagerFactory emf2 = createNamedEMF(getPersistenceUnitName(),
FGManager.class, FGDepartment.class, FGEmployee.class, FGAddress.class,
"openjpa.FetchGroups", "default,DescFetchGroup");
OpenJPAEntityManager em = emf2.createEntityManager();
FetchPlan fp = em.getFetchPlan();
assertNotNull(fp);
assertNotNull(fp.getFetchGroups());
assertEquals(2, fp.getFetchGroups().size());
assertTrue(fp.getFetchGroups().contains("default"));
assertTrue(fp.getFetchGroups().contains("DescFetchGroup"));
FGManager mgr = managerSet.iterator().next();
assertNotNull(mgr);
{
// First find, to prime the Finder Cache
FGManager findMgr = em.find(FGManager.class, mgr.getId());
em.clear();
assertEquals(mgr.getId(), findMgr.getId());
assertEquals(mgr.getFirstName(), findMgr.getFirstName());
assertEquals(mgr.getLastName(), findMgr.getLastName());
assertEquals(mgr.getDescription(), findMgr.getDescription()); // Should not be lazy-loaded
}
{
// Second find, should rely on the finder cache to reuse generated SQL.
FGManager findMgr = em.find(FGManager.class, mgr.getId());
em.clear();
assertEquals(mgr.getId(), findMgr.getId());
assertEquals(mgr.getFirstName(), findMgr.getFirstName());
assertEquals(mgr.getLastName(), findMgr.getLastName());
assertEquals(mgr.getDescription(), findMgr.getDescription()); // Should not be lazy-loaded
}
// Remove a fetch group to the fetch plan and verify expected behavior
fp.removeFetchGroup("DescFetchGroup");
assertNotNull(fp.getFetchGroups());
assertEquals(1, fp.getFetchGroups().size());
assertTrue(fp.getFetchGroups().contains("default"));
assertFalse(fp.getFetchGroups().contains("DescFetchGroup"));
{
// Second find, should rely on the finder cache to reuse generated SQL.
FGManager findMgr = em.find(FGManager.class, mgr.getId());
em.clear();
assertEquals(mgr.getId(), findMgr.getId());
assertEquals(mgr.getFirstName(), findMgr.getFirstName());
assertEquals(mgr.getLastName(), findMgr.getLastName());
assertNull(findMgr.getDescription()); // Should be lazy-loaded
}
// Restore the fetch group previously removed, and verify expected behavior
fp.addFetchGroup("DescFetchGroup");
assertNotNull(fp.getFetchGroups());
assertEquals(2, fp.getFetchGroups().size());
assertTrue(fp.getFetchGroups().contains("default"));
assertTrue(fp.getFetchGroups().contains("DescFetchGroup"));
{
FGManager findMgr = em.find(FGManager.class, mgr.getId());
em.clear();
assertEquals(mgr.getId(), findMgr.getId());
assertEquals(mgr.getFirstName(), findMgr.getFirstName());
assertEquals(mgr.getLastName(), findMgr.getLastName());
assertEquals(mgr.getDescription(), findMgr.getDescription()); // Should not be lazy-loaded
}
// Remove a fetch group to the fetch plan and verify expected behavior
fp.removeFetchGroup("DescFetchGroup");
assertNotNull(fp.getFetchGroups());
assertEquals(1, fp.getFetchGroups().size());
assertTrue(fp.getFetchGroups().contains("default"));
assertFalse(fp.getFetchGroups().contains("DescFetchGroup"));
{
// Second find, should rely on the finder cache to reuse generated SQL.
FGManager findMgr = em.find(FGManager.class, mgr.getId());
em.clear();
assertEquals(mgr.getId(), findMgr.getId());
assertEquals(mgr.getFirstName(), findMgr.getFirstName());
assertEquals(mgr.getLastName(), findMgr.getLastName());
assertNull(findMgr.getDescription()); // Should be lazy-loaded
}
// Reset the fetch plan, and verify expected behavior
fp.resetFetchGroups();
assertNotNull(fp.getFetchGroups());
assertEquals(2, fp.getFetchGroups().size());
assertTrue(fp.getFetchGroups().contains("default"));
assertTrue(fp.getFetchGroups().contains("DescFetchGroup"));
{
FGManager findMgr = em.find(FGManager.class, mgr.getId());
em.clear();
assertEquals(mgr.getId(), findMgr.getId());
assertEquals(mgr.getFirstName(), findMgr.getFirstName());
assertEquals(mgr.getLastName(), findMgr.getLastName());
assertEquals(mgr.getDescription(), findMgr.getDescription()); // Should not be lazy-loaded
}
// Clear all fetch groups, and verify expected behavior
// Note, due to OPENJPA-2413 even though it behaves as if the "default" fetch group is enabled,
// it will not show up in the list of active fetch groups.
fp.clearFetchGroups();
assertNotNull(fp.getFetchGroups());
assertEquals(0, fp.getFetchGroups().size());
assertFalse(fp.getFetchGroups().contains("default"));
assertFalse(fp.getFetchGroups().contains("DescFetchGroup"));
{
FGManager findMgr = em.find(FGManager.class, mgr.getId());
em.clear();
assertEquals(mgr.getId(), findMgr.getId());
assertEquals(mgr.getFirstName(), findMgr.getFirstName());
assertEquals(mgr.getLastName(), findMgr.getLastName());
assertNull(findMgr.getDescription()); // Should be lazy-loaded
}
em.close();
emf2.close();
}
/**
* Only SQL generated by the PCtx's default fetch plan should be used by the finder cache,
* as it currently lacks the ability to distinguish fetch plan configuration in its key value.
* The PCtx's default fetch plan is modified by the "openjpa.FetchGroups" property.
*
* In this variant, a find using a modified fetch plan is first executed, which should not be added
* to the finder cache.
*/
public void testFinderCache005() {
OpenJPAEntityManagerFactory emf2 = createNamedEMF(getPersistenceUnitName(),
FGManager.class, FGDepartment.class, FGEmployee.class, FGAddress.class,
"openjpa.FetchGroups", "default,DescFetchGroup");
OpenJPAEntityManager em = emf2.createEntityManager();
FetchPlan fp = em.getFetchPlan();
assertNotNull(fp);
assertNotNull(fp.getFetchGroups());
assertEquals(2, fp.getFetchGroups().size());
assertTrue(fp.getFetchGroups().contains("default"));
assertTrue(fp.getFetchGroups().contains("DescFetchGroup"));
FGManager mgr = managerSet.iterator().next();
assertNotNull(mgr);
fp.removeFetchGroup("DescFetchGroup");
assertEquals(1, fp.getFetchGroups().size());
assertTrue(fp.getFetchGroups().contains("default"));
assertFalse(fp.getFetchGroups().contains("DescFetchGroup"));
{
FGManager findMgr = em.find(FGManager.class, mgr.getId());
em.clear();
assertEquals(mgr.getId(), findMgr.getId());
assertEquals(mgr.getFirstName(), findMgr.getFirstName());
assertEquals(mgr.getLastName(), findMgr.getLastName());
assertNull(findMgr.getDescription()); // Should be lazy-loaded
}
// Restore the "DescFetchGroup" fetch group, and verify expected behavior
fp.addFetchGroup("DescFetchGroup");
assertNotNull(fp.getFetchGroups());
assertEquals(2, fp.getFetchGroups().size());
assertTrue(fp.getFetchGroups().contains("default"));
assertTrue(fp.getFetchGroups().contains("DescFetchGroup"));
{
FGManager findMgr = em.find(FGManager.class, mgr.getId());
em.clear();
assertEquals(mgr.getId(), findMgr.getId());
assertEquals(mgr.getFirstName(), findMgr.getFirstName());
assertEquals(mgr.getLastName(), findMgr.getLastName());
assertEquals(mgr.getDescription(), findMgr.getDescription()); // Should not be lazy-loaded
}
// Remove the "DescFetchGroup" fetch group, and verify expected behavior
fp.removeFetchGroup("DescFetchGroup");
assertNotNull(fp.getFetchGroups());
assertEquals(1, fp.getFetchGroups().size());
assertTrue(fp.getFetchGroups().contains("default"));
assertFalse(fp.getFetchGroups().contains("DescFetchGroup"));
{
FGManager findMgr = em.find(FGManager.class, mgr.getId());
em.clear();
assertEquals(mgr.getId(), findMgr.getId());
assertEquals(mgr.getFirstName(), findMgr.getFirstName());
assertEquals(mgr.getLastName(), findMgr.getLastName());
assertNull(findMgr.getDescription()); // Should be lazy-loaded
}
// Reset the fetch plan, and verify expected behavior
fp.resetFetchGroups();
assertNotNull(fp.getFetchGroups());
assertEquals(2, fp.getFetchGroups().size());
assertTrue(fp.getFetchGroups().contains("default"));
assertTrue(fp.getFetchGroups().contains("DescFetchGroup"));
{
FGManager findMgr = em.find(FGManager.class, mgr.getId());
em.clear();
assertEquals(mgr.getId(), findMgr.getId());
assertEquals(mgr.getFirstName(), findMgr.getFirstName());
assertEquals(mgr.getLastName(), findMgr.getLastName());
assertEquals(mgr.getDescription(), findMgr.getDescription()); // Should not be lazy-loaded
}
// Remove the "DescFetchGroup" fetch group, and verify expected behavior
fp.removeFetchGroup("DescFetchGroup");
assertNotNull(fp.getFetchGroups());
assertEquals(1, fp.getFetchGroups().size());
assertTrue(fp.getFetchGroups().contains("default"));
assertFalse(fp.getFetchGroups().contains("DescFetchGroup"));
{
FGManager findMgr = em.find(FGManager.class, mgr.getId());
em.clear();
assertEquals(mgr.getId(), findMgr.getId());
assertEquals(mgr.getFirstName(), findMgr.getFirstName());
assertEquals(mgr.getLastName(), findMgr.getLastName());
assertNull(findMgr.getDescription()); // Should be lazy-loaded
}
// Clear all fetch groups, and verify expected behavior
// Note, due to OPENJPA-2413 even though it behaves as if the "default" fetch group is enabled,
// it will not show up in the list of active fetch groups.
fp.clearFetchGroups();
assertNotNull(fp.getFetchGroups());
assertEquals(0, fp.getFetchGroups().size());
assertFalse(fp.getFetchGroups().contains("default"));
assertFalse(fp.getFetchGroups().contains("DescFetchGroup"));
{
FGManager findMgr = em.find(FGManager.class, mgr.getId());
em.clear();
assertEquals(mgr.getId(), findMgr.getId());
assertEquals(mgr.getFirstName(), findMgr.getFirstName());
assertEquals(mgr.getLastName(), findMgr.getLastName());
assertNull(findMgr.getDescription()); // Should be lazy-loaded
}
em.close();
emf2.close();
}
private void createEmployeeData() {
OpenJPAEntityManager em = emf.createEntityManager();
employeeSet.clear();
managerSet.clear();
int empIdIndex = 1;
em.getTransaction().begin();
// Create Managers
for (int i = 1; i < mgrCount; i++) {
int id = empIdIndex++;
FGAddress addr = createAddress(id);
em.persist(addr);
FGDepartment dept = createDepartment(id);
em.persist(dept);
FGManager mgr = new FGManager();
mgr.setId(id);
mgr.setFirstName("First-" + id);
mgr.setLastName("Last-" + id);
mgr.setMData("MData-" + id);
mgr.setRating("Rating-" + id);
mgr.setDescription("Manager-" + id);
mgr.setAddress(addr);
mgr.setDept(dept);
em.persist(mgr);
managerSet.add(mgr);
}
// Create Employees
for (int i = 1; i < empCount; i++) {
int id = empIdIndex++;
int mgrId = (id % empPerMgr) + 1;
FGAddress addr = createAddress(id);
em.persist(addr);
FGDepartment dept = createDepartment(id);
em.persist(dept);
FGEmployee emp = new FGEmployee();
emp.setId(id);
emp.setFirstName("First-" + id);
emp.setLastName("Last-" + id);
emp.setRating("Rating-" + id);
emp.setDescription("Employee-" + id);
emp.setAddress(addr);
emp.setDept(dept);
em.persist(emp);
employeeSet.add(emp);
}
em.getTransaction().commit();
em.close();
}
private FGAddress createAddress(int id) {
FGAddress addr = new FGAddress();
addr.setId(id);
addr.setStreet("Street-" + id);
addr.setCity("City-" + id);
addr.setState("State-" + id);
addr.setZip(id);
return addr;
}
private FGDepartment createDepartment(int id) {
FGDepartment dept = new FGDepartment();
dept.setId(id);
dept.setName("Department-" + id);
return dept;
}
}