/******************************************************************************* * Copyright (c) 2009, 2015 Oracle and/or its affiliates. All rights reserved. * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 * which accompanies this distribution. * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html * and the Eclipse Distribution License is available at * http://www.eclipse.org/org/documents/edl-v10.php. * * Contributors: * 05/19/2010-2.1 ailitchev - Bug 244124 - Add Nested FetchGroup ******************************************************************************/ package org.eclipse.persistence.testing.tests.jpa.fetchgroups; import java.util.ArrayList; import java.util.List; import javax.persistence.EntityManager; import javax.persistence.Query; import junit.framework.TestSuite; import org.eclipse.persistence.config.QueryHints; import org.eclipse.persistence.internal.queries.AttributeItem; import org.eclipse.persistence.queries.FetchGroup; import org.eclipse.persistence.queries.FetchGroupTracker; import org.eclipse.persistence.testing.models.jpa.advanced.Employee; import org.eclipse.persistence.testing.models.jpa.advanced.PhoneNumber; import org.eclipse.persistence.testing.models.jpa.advanced.Employee.Gender; import org.junit.Test; /** * @author dclarke * @since EclipseLink 2.1 */ public class NestedNamedFetchGroupTests extends BaseFetchGroupTests { public NestedNamedFetchGroupTests() { super(); } public NestedNamedFetchGroupTests(String name) { super(name); } public static junit.framework.Test suite() { TestSuite suite = new TestSuite(); suite.setName("NestedNamedFetchGroupTests"); suite.addTest(new NestedNamedFetchGroupTests("testSetup")); suite.addTest(new NestedNamedFetchGroupTests("dynamicFetchGroup_EmployeeAddress")); suite.addTest(new NestedNamedFetchGroupTests("dynamicFetchGroup_Employee_NullAddress")); suite.addTest(new NestedNamedFetchGroupTests("dynamicFetchGroup_EmployeeAddressNullPhone")); suite.addTest(new NestedNamedFetchGroupTests("dynamicFetchGroup_EmployeeAddressEmptyPhone")); suite.addTest(new NestedNamedFetchGroupTests("dynamicHierarchicalFetchGroup")); return suite; } /* * Set default fetch groups. * * @see PhoneCustomizer */ public void setUp() { super.setUp(); try { (new PhoneCustomizer()).customize(phoneDescriptor); // reprepare read queries after all fetch groups set into all descriptors. reprepareReadQueries(employeeDescriptor); reprepareReadQueries(phoneDescriptor); } catch (RuntimeException rtEx) { throw rtEx; } catch (Exception ex) { throw new RuntimeException(ex); } assertConfig(phoneDescriptor, defaultPhoneFG, 0); } @Test public void dynamicFetchGroup_EmployeeAddress() throws Exception { EntityManager em = createEntityManager(); try { beginTransaction(em); Query query = em.createQuery("SELECT e FROM Employee e WHERE e.gender = :GENDER"); query.setParameter("GENDER", Gender.Male); // Define the fields to be fetched on Employee FetchGroup fg = new FetchGroup(); fg.addAttribute("firstName"); fg.addAttribute("lastName"); fg.addAttribute("address"); fg.addAttribute("address.city"); fg.addAttribute("address.postalCode"); // Configure the dynamic FetchGroup query.setHint(QueryHints.FETCH_GROUP, fg); List<Employee> emps = query.getResultList(); assertNotNull(emps); for (Employee emp : emps) { FetchGroupTracker tracker = (FetchGroupTracker) emp; assertNotNull(tracker._persistence_getFetchGroup()); // Verify specified fields plus mandatory ones are loaded assertTrue(tracker._persistence_isAttributeFetched("id")); assertTrue(tracker._persistence_isAttributeFetched("firstName")); assertTrue(tracker._persistence_isAttributeFetched("lastName")); assertTrue(tracker._persistence_isAttributeFetched("version")); // Verify the other fields are not loaded assertFalse(tracker._persistence_isAttributeFetched("salary")); assertFalse(tracker._persistence_isAttributeFetched("startTime")); assertFalse(tracker._persistence_isAttributeFetched("endTime")); // Force the loading of lazy fields and verify emp.getSalary(); assertTrue(tracker._persistence_isAttributeFetched("salary")); assertTrue(tracker._persistence_isAttributeFetched("startTime")); assertTrue(tracker._persistence_isAttributeFetched("endTime")); // Now we'll check the address uses the provided dynamic fetch-group FetchGroupTracker addrTracker = (FetchGroupTracker) emp.getAddress(); assertNotNull("Address does not have a FetchGroup", addrTracker._persistence_getFetchGroup()); assertTrue(addrTracker._persistence_isAttributeFetched("city")); assertTrue(addrTracker._persistence_isAttributeFetched("postalCode")); assertFalse(addrTracker._persistence_isAttributeFetched("street")); assertFalse(addrTracker._persistence_isAttributeFetched("country")); // Now we'll check the phoneNumbers use of the default fetch group for (PhoneNumber phone : emp.getPhoneNumbers()) { FetchGroupTracker phoneTracker = (FetchGroupTracker) phone; assertNotNull("PhoneNumber does not have a FetchGroup", phoneTracker._persistence_getFetchGroup()); assertTrue(phoneTracker._persistence_isAttributeFetched("number")); assertFalse(phoneTracker._persistence_isAttributeFetched("areaCode")); } } } finally { if (isTransactionActive(em)){ rollbackTransaction(em); } closeEntityManager(em); } } @Test public void dynamicFetchGroup_Employee_NullAddress() throws Exception { EntityManager em = createEntityManager(); Query query = em.createQuery("SELECT e FROM Employee e WHERE e.gender = :GENDER"); query.setParameter("GENDER", Gender.Male); // Define the fields to be fetched on Employee FetchGroup empGroup = new FetchGroup(); empGroup.addAttribute("firstName"); empGroup.addAttribute("lastName"); empGroup.addAttribute("address"); // Define the fields to be fetched on Address FetchGroup addressGroup = new FetchGroup(); addressGroup.addAttribute("city"); addressGroup.addAttribute("postalCode"); empGroup.addAttribute("address"); // Configure the dynamic FetchGroup query.setHint(QueryHints.FETCH_GROUP, empGroup); List<Employee> emps = query.getResultList(); assertNotNull(emps); for (Employee emp : emps) { FetchGroupTracker tracker = (FetchGroupTracker) emp; assertNotNull(tracker._persistence_getFetchGroup()); // Verify specified fields plus mandatory ones are loaded assertTrue(tracker._persistence_isAttributeFetched("id")); assertTrue(tracker._persistence_isAttributeFetched("firstName")); assertTrue(tracker._persistence_isAttributeFetched("lastName")); assertTrue(tracker._persistence_isAttributeFetched("version")); // Verify the other fields are not loaded assertFalse(tracker._persistence_isAttributeFetched("salary")); assertFalse(tracker._persistence_isAttributeFetched("startTime")); assertFalse(tracker._persistence_isAttributeFetched("endTime")); // Force the loading of lazy fields and verify emp.getSalary(); assertTrue(tracker._persistence_isAttributeFetched("salary")); assertTrue(tracker._persistence_isAttributeFetched("startTime")); assertTrue(tracker._persistence_isAttributeFetched("endTime")); // Now we'll check the address uses the provided dynamic fetch-group FetchGroupTracker addrTracker = (FetchGroupTracker) emp.getAddress(); assertNull("Address has an unexpected FetchGroup", addrTracker._persistence_getFetchGroup()); // Now we'll check the phoneNumbers use of the default fetch group for (PhoneNumber phone : emp.getPhoneNumbers()) { FetchGroupTracker phoneTracker = (FetchGroupTracker) phone; assertNotNull("PhoneNumber does not have a FetchGroup", phoneTracker._persistence_getFetchGroup()); assertTrue(phoneTracker._persistence_isAttributeFetched("number")); assertFalse(phoneTracker._persistence_isAttributeFetched("areaCode")); } } } @Test public void dynamicFetchGroup_EmployeeAddressNullPhone() throws Exception { EntityManager em = createEntityManager(); try { beginTransaction(em); Query query = em.createQuery("SELECT e FROM Employee e WHERE e.gender = :GENDER"); query.setParameter("GENDER", Gender.Male); // Define the fields to be fetched on Employee FetchGroup empGroup = new FetchGroup(); empGroup.addAttribute("firstName"); empGroup.addAttribute("lastName"); empGroup.addAttribute("address"); // Define the fields to be fetched on Address FetchGroup addressGroup = new FetchGroup(); addressGroup.addAttribute("city"); addressGroup.addAttribute("postalCode"); empGroup.addAttribute("address", addressGroup); //empGroup.addAttribute("phoneNumbers").setUseDefaultFetchGroup(false); FetchGroup fullPhone = this.phoneDescriptor.getFetchGroupManager().createFullFetchGroup(); // to preclude Employee from being loaded by phoneNumber.owner add it to the fetch group fullPhone.addAttribute("owner.id"); empGroup.addAttribute("phoneNumbers", fullPhone); // Configure the dynamic FetchGroup query.setHint(QueryHints.FETCH_GROUP, empGroup); List<Employee> emps = query.getResultList(); assertNotNull(emps); for (Employee emp : emps) { FetchGroupTracker tracker = (FetchGroupTracker) emp; assertNotNull(tracker._persistence_getFetchGroup()); // Verify specified fields plus mandatory ones are loaded assertTrue(tracker._persistence_isAttributeFetched("id")); assertTrue(tracker._persistence_isAttributeFetched("firstName")); assertTrue(tracker._persistence_isAttributeFetched("lastName")); assertTrue(tracker._persistence_isAttributeFetched("version")); // Verify the other fields are not loaded assertFalse(tracker._persistence_isAttributeFetched("salary")); assertFalse(tracker._persistence_isAttributeFetched("startTime")); assertFalse(tracker._persistence_isAttributeFetched("endTime")); // Force the loading of lazy fields and verify emp.getSalary(); assertTrue(tracker._persistence_isAttributeFetched("salary")); assertTrue(tracker._persistence_isAttributeFetched("startTime")); assertTrue(tracker._persistence_isAttributeFetched("endTime")); // Now we'll check the address uses the provided dynamic fetch-group FetchGroupTracker addrTracker = (FetchGroupTracker) emp.getAddress(); assertNotNull("Address does not have a FetchGroup", addrTracker._persistence_getFetchGroup()); assertTrue(addrTracker._persistence_isAttributeFetched("city")); assertTrue(addrTracker._persistence_isAttributeFetched("postalCode")); assertFalse(addrTracker._persistence_isAttributeFetched("street")); assertFalse(addrTracker._persistence_isAttributeFetched("country")); // Now we'll check the phoneNumbers use of the default fetch group for (PhoneNumber phone : emp.getPhoneNumbers()) { FetchGroupTracker phoneTracker = (FetchGroupTracker) phone; assertNull("PhoneNumber has a FetchGroup", phoneTracker._persistence_getFetchGroup()); } } } finally { if (isTransactionActive(em)){ rollbackTransaction(em); } closeEntityManager(em); } } @Test public void dynamicFetchGroup_EmployeeAddressEmptyPhone() throws Exception { EntityManager em = createEntityManager(); try { beginTransaction(em); Query query = em.createQuery("SELECT e FROM Employee e WHERE e.gender = :GENDER"); query.setParameter("GENDER", Gender.Male); // Define the fields to be fetched on Employee FetchGroup empGroup = new FetchGroup(); empGroup.addAttribute("firstName"); empGroup.addAttribute("lastName"); empGroup.addAttribute("address"); // Define the fields to be fetched on Address FetchGroup addressGroup = new FetchGroup(); addressGroup.addAttribute("city"); addressGroup.addAttribute("postalCode"); empGroup.addAttribute("address", addressGroup); // to preclude Employee from being loaded by phoneNumber.owner add it to the fetch group FetchGroup ownerId = new FetchGroup(); ownerId.addAttribute("owner.id"); empGroup.addAttribute("phoneNumbers", ownerId); // Configure the dynamic FetchGroup query.setHint(QueryHints.FETCH_GROUP, empGroup); List<Employee> emps = query.getResultList(); assertNotNull(emps); for (Employee emp : emps) { FetchGroupTracker tracker = (FetchGroupTracker) emp; assertNotNull(tracker._persistence_getFetchGroup()); // Verify specified fields plus mandatory ones are loaded assertTrue(tracker._persistence_isAttributeFetched("id")); assertTrue(tracker._persistence_isAttributeFetched("firstName")); assertTrue(tracker._persistence_isAttributeFetched("lastName")); assertTrue(tracker._persistence_isAttributeFetched("version")); // Verify the other fields are not loaded assertFalse(tracker._persistence_isAttributeFetched("salary")); assertFalse(tracker._persistence_isAttributeFetched("startTime")); assertFalse(tracker._persistence_isAttributeFetched("endTime")); // Force the loading of lazy fields and verify emp.getSalary(); assertTrue(tracker._persistence_isAttributeFetched("salary")); assertTrue(tracker._persistence_isAttributeFetched("startTime")); assertTrue(tracker._persistence_isAttributeFetched("endTime")); // Now we'll check the address uses the provided dynamic fetch-group FetchGroupTracker addrTracker = (FetchGroupTracker) emp.getAddress(); assertNotNull("Address does not have a FetchGroup", addrTracker._persistence_getFetchGroup()); assertTrue(addrTracker._persistence_isAttributeFetched("city")); assertTrue(addrTracker._persistence_isAttributeFetched("postalCode")); assertFalse(addrTracker._persistence_isAttributeFetched("street")); assertFalse(addrTracker._persistence_isAttributeFetched("country")); // Now we'll check the phoneNumbers use of the default fetch group for (PhoneNumber phone : emp.getPhoneNumbers()) { FetchGroupTracker phoneTracker = (FetchGroupTracker) phone; assertNotNull("PhoneNumber does not have a FetchGroup", phoneTracker._persistence_getFetchGroup()); assertFalse(phoneTracker._persistence_isAttributeFetched("number")); assertFalse(phoneTracker._persistence_isAttributeFetched("areaCode")); phone.getNumber(); assertTrue(phoneTracker._persistence_isAttributeFetched("number")); assertTrue(phoneTracker._persistence_isAttributeFetched("areaCode")); } } } finally { if (isTransactionActive(em)){ rollbackTransaction(em); } closeEntityManager(em); } } @Test public void dynamicHierarchicalFetchGroup() throws Exception { EntityManager em = createEntityManager(); Query query = em.createQuery("SELECT e FROM Employee e WHERE e.gender = :GENDER"); query.setParameter("GENDER", Gender.Male); // Define the fields to be fetched on Employee FetchGroup fg = new FetchGroup(); fg.addAttribute("firstName"); fg.addAttribute("lastName"); fg.addAttribute("salary"); fg.addAttribute("gender"); fg.addAttribute("manager.firstName"); fg.addAttribute("manager.lastName"); fg.addAttribute("manager.salary"); fg.addAttribute("manager.gender"); fg.addAttribute("manager.manager.firstName"); fg.addAttribute("manager.manager.lastName"); fg.addAttribute("manager.manager.salary"); fg.addAttribute("manager.manager.gender"); AttributeItem mgrItem = fg.getItem("manager"); assertNotNull(mgrItem); assertNotNull(mgrItem.getGroup()); AttributeItem mgrMgrItem = fg.getItem("manager.manager"); assertNotNull(mgrMgrItem); assertNotNull(mgrMgrItem.getGroup()); query.setHint(QueryHints.FETCH_GROUP, fg); List<Employee> emps = query.getResultList(); int numSelect = getQuerySQLTracker(em).getTotalSQLSELECTCalls(); List<Employee> loadedEmps = new ArrayList<Employee>(); loadedEmps.addAll(emps); for (Employee emp : emps) { if (!loadedEmps.contains(emp)) { assertFetched(emp, fg); } assertNotFetchedAttribute(emp, "startDate"); loadedEmps.add(emp); } // TODO assertEquals(1 + loadedEmps.size() - emps.size(), numSelect); } }