blob: 4ffcaa9644b3775a44d4844dfbdda2ff1547085a [file] [log] [blame]
/*
* Copyright (c) 2011, 2021 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 v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
// Contributors:
// 05/19/2010-2.1 ailitchev - Bug 244124 - Add Nested FetchGroup
package org.eclipse.persistence.testing.tests.jpa.fetchgroups;
import java.util.HashMap;
import java.util.List;
import jakarta.persistence.EntityManager;
import jakarta.persistence.TypedQuery;
import junit.framework.TestSuite;
import org.eclipse.persistence.config.DescriptorCustomizer;
import org.eclipse.persistence.config.QueryHints;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.indirection.IndirectCollection;
import org.eclipse.persistence.indirection.ValueHolderInterface;
import org.eclipse.persistence.mappings.ForeignReferenceMapping;
import org.eclipse.persistence.queries.FetchGroup;
import org.eclipse.persistence.queries.LoadGroup;
import org.eclipse.persistence.testing.models.jpa.advanced.Address;
import org.eclipse.persistence.testing.models.jpa.advanced.Employee;
import org.eclipse.persistence.testing.models.jpa.advanced.PhoneNumber;
import org.junit.Test;
/**
* Test named nested FetchGroup usage.
*
* @author dclarke
* @since EclipseLink 2.1
*/
public class NestedDefaultFetchGroupTests extends BaseFetchGroupTests {
public NestedDefaultFetchGroupTests() {
super();
}
public NestedDefaultFetchGroupTests(String name) {
super(name);
}
public static junit.framework.Test suite() {
TestSuite suite = new TestSuite();
suite.setName("NestedDefaultFetchGroupTests");
suite.addTest(new NestedDefaultFetchGroupTests("testSetup"));
suite.addTest(new NestedDefaultFetchGroupTests("findMinEmployee"));
suite.addTest(new NestedDefaultFetchGroupTests("findMinEmployeeLoadAddressAndPhoneUsingFetchGroup"));
if (!isJPA10()) {
suite.addTest(new NestedDefaultFetchGroupTests("findMinEmployeeLoadAddress"));
suite.addTest(new NestedDefaultFetchGroupTests("findMinEmployeeLoadPhones"));
suite.addTest(new NestedDefaultFetchGroupTests("findMinEmployeeLoadAddressAndPhones"));
suite.addTest(new NestedDefaultFetchGroupTests("allAddress"));
suite.addTest(new NestedDefaultFetchGroupTests("allPhone"));
suite.addTest(new NestedDefaultFetchGroupTests("singleResultMinEmployeeFetchJoinAddress"));
suite.addTest(new NestedDefaultFetchGroupTests("singleResultMinEmployeeFetchJoinAddressLoad"));
}
return suite;
}
/*
* Set default fetch groups.
*
* @see EmployeeCustomizer
* @see PhoneCustomizer
*/
@Override
public void setUp() {
super.setUp();
try {
(new EmployeeCustomizer()).customize(employeeDescriptor);
(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(employeeDescriptor, defaultEmployeeFG, 0);
assertConfig(phoneDescriptor, defaultPhoneFG, 0);
}
@Test
public void findMinEmployee() {
internalFindMinEmployee(false, false, false);
}
@Test
public void findMinEmployeeLoadAddress() {
internalFindMinEmployee(true, false, true);
}
public void findMinEmployeeLoadPhones() {
internalFindMinEmployee(false, true, true);
}
public void findMinEmployeeLoadAddressAndPhones() {
internalFindMinEmployee(true, true, true);
}
public void findMinEmployeeLoadAddressAndPhoneUsingFetchGroup() {
internalFindMinEmployee(true, true, false);
}
void internalFindMinEmployee(boolean loadAddress, boolean loadPhones, boolean useLoadGroup) {
EntityManager em = createEntityManager();
beginTransaction(em);
int minId = minEmployeeIdWithAddressAndPhones(em);
assertEquals(1, getQuerySQLTracker(em).getTotalSQLSELECTCalls());
boolean load = false;
boolean originalLoad = false;
if(!useLoadGroup) {
assertTrue(loadAddress == loadPhones);
load = loadAddress;
originalLoad = defaultEmployeeFG.shouldLoad();
if(load != originalLoad) {
defaultEmployeeFG.setShouldLoad(load);
}
}
try {
Employee emp;
if(useLoadGroup) {
LoadGroup lg = defaultEmployeeFG.toLoadGroup();
if(!loadAddress) {
lg.removeAttribute("address");
}
if(!loadPhones) {
lg.removeAttribute("phoneNumbers");
}
HashMap<String, Object> hints = new HashMap(1);
hints.put(QueryHints.LOAD_GROUP, lg);
emp = em.find(Employee.class, minId, hints);
} else {
emp = em.find(Employee.class, minId);
}
assertNotNull(emp);
int nExpected = 2;
if(loadAddress) {
nExpected++;
}
if(loadPhones) {
nExpected++;
}
assertEquals(nExpected, getQuerySQLTracker(em).getTotalSQLSELECTCalls());
boolean addressInstantiated = ((ValueHolderInterface) employeeDescriptor.getMappingForAttributeName("address").getAttributeValueFromObject(emp)).isInstantiated();
assertTrue(loadAddress == addressInstantiated);
boolean phonesInstantiated = ((IndirectCollection) employeeDescriptor.getMappingForAttributeName("phoneNumbers").getAttributeValueFromObject(emp)).isInstantiated();
assertTrue(loadPhones == phonesInstantiated);
emp.getAddress();
emp.getPhoneNumbers().size();
assertEquals(4, getQuerySQLTracker(em).getTotalSQLSELECTCalls());
assertFetched(emp, defaultEmployeeFG);
assertFetchedAttribute(emp, "address");
assertFetchedAttribute(emp, "phoneNumbers");
// Check Address
FetchGroup fgAddress = defaultEmployeeFG.getGroup("address");
assertFetched(emp.getAddress(), fgAddress);
// Check phones
FetchGroup fgPhones = defaultEmployeeFG.getGroup("phoneNumbers");
for (PhoneNumber phone: emp.getPhoneNumbers()) {
assertFetched(phone, fgPhones);
}
} finally {
if(!useLoadGroup) {
if(load != originalLoad) {
defaultEmployeeFG.setShouldLoad(originalLoad);
}
}
if (isTransactionActive(em)){
rollbackTransaction(em);
}
closeEntityManager(em);
}
}
/* void internalFindMinEmployee(boolean loadAddress, boolean loadPhones) {
EntityManager em = createEntityManager();
int minId = minEmployeeIdWithAddressAndPhones(em);
assertEquals(1, getQuerySQLTracker(em).getTotalSQLSELECTCalls());
FetchGroup fg = employeeDescriptor.getFetchGroupManager().getDefaultFetchGroup();
FetchGroup phonesFg = fg.getGroup("phoneNumbers");
FetchGroup fgAddress = fg.getGroup("address");
boolean originalLoadAddress = fgAddress.shouldLoad();
if(originalLoadAddress != loadAddress) {
fgAddress.setShouldLoad(loadAddress);
}
FetchGroup fgPhones = fg.getGroup("phoneNumbers");
boolean originalLoadPhones = fgPhones.shouldLoad();
if(originalLoadPhones != loadPhones) {
fgPhones.setShouldLoad(loadPhones);
}
try {
Employee emp = em.find(Employee.class, minId);
assertNotNull(emp);
int nExpected = 2;
if(loadAddress) {
nExpected++;
}
if(loadPhones) {
nExpected++;
}
assertEquals(nExpected, getQuerySQLTracker(em).getTotalSQLSELECTCalls());
boolean addressInstantiated = ((ValueHolderInterface)((ForeignReferenceMapping)employeeDescriptor.getMappingForAttributeName("address")).getAttributeValueFromObject(emp)).isInstantiated();
boolean phonesInstantiated = ((IndirectCollection)((ForeignReferenceMapping)employeeDescriptor.getMappingForAttributeName("phoneNumbers")).getAttributeValueFromObject(emp)).isInstantiated();
if(loadAddress) {
assertTrue(addressInstantiated);
}
if(loadPhones) {
assertTrue(phonesInstantiated);
}
emp.getAddress();
emp.getPhoneNumbers().size();
assertEquals(4, getQuerySQLTracker(em).getTotalSQLSELECTCalls());
assertFetched(emp, defaultEmployeeFG);
assertFetchedAttribute(emp, "address");
assertFetchedAttribute(emp, "phoneNumbers");
// Check Address
assertFetched(emp.getAddress(), fgAddress);
// Check phones
for (PhoneNumber phone: emp.getPhoneNumbers()) {
assertFetched(phone, fgPhones);
}
} finally {
if(originalLoadAddress != loadAddress) {
fgAddress.setShouldLoad(originalLoadAddress);
}
if(originalLoadPhones != loadPhones) {
fgPhones.setShouldLoad(originalLoadPhones);
}
}
}*/
@Test
public void allAddress() {
EntityManager em = createEntityManager();
List<Address> allAddresses = em.createQuery("SELECT a FROM Address a", Address.class).getResultList();
for (Address address: allAddresses) {
assertNoFetchGroup(address);
}
}
@Test
public void allPhone() {
EntityManager em = createEntityManager();
List<PhoneNumber> allPhones = em.createQuery("SELECT p FROM PhoneNumber p", PhoneNumber.class).getResultList();
for (PhoneNumber phone: allPhones) {
assertFetched(phone, defaultPhoneFG);
}
}
@Test
public void singleResultMinEmployeeFetchJoinAddress() {
internalSingleResultMinEmployeeFetchJoinAddress(false);
}
public void singleResultMinEmployeeFetchJoinAddressLoad() {
internalSingleResultMinEmployeeFetchJoinAddress(true);
}
void internalSingleResultMinEmployeeFetchJoinAddress(boolean shouldLoad) {
EntityManager em = createEntityManager();
TypedQuery<Employee> query = em.createQuery("SELECT e FROM Employee e JOIN FETCH e.address WHERE e.id IN (SELECT MIN(p.id) FROM PhoneNumber p)", Employee.class);
if(shouldLoad) {
query.setHint(QueryHints.LOAD_GROUP_ATTRIBUTE, "phoneNumbers");
}
Employee emp = query.getSingleResult();
assertNotNull(emp);
int nExpected = 1;
if(shouldLoad) {
nExpected++;
}
assertEquals(nExpected, getQuerySQLTracker(em).getTotalSQLSELECTCalls());
}
public static class EmployeeCustomizer implements DescriptorCustomizer {
@Override
public void customize(ClassDescriptor descriptor) throws Exception {
defaultEmployeeFG = new FetchGroup("Employee.default");
defaultEmployeeFG.addAttribute("firstName");
defaultEmployeeFG.addAttribute("lastName");
defaultEmployeeFG.addAttribute("address.country");
defaultEmployeeFG.addAttribute("phoneNumbers.areaCode");
descriptor.getFetchGroupManager().setDefaultFetchGroup(defaultEmployeeFG);
}
}
/* public static class PhoneCustomizer implements DescriptorCustomizer {
public void customize(ClassDescriptor descriptor) throws Exception {
defaultPhoneFG = new FetchGroup<PhoneNumber>("PhoneNumber.default");
defaultPhoneFG.addAttribute("number");
descriptor.getFetchGroupManager().setDefaultFetchGroup(defaultPhoneFG);
}
}*/
}