This is an automated email from the ASF dual-hosted git repository. pcristof pushed a commit to branch OPENJPA-2940 in repository https://gitbox.apache.org/repos/asf/openjpa.git
commit 9ae04d7dddba1f6db4f3822f5e56a031e2c05636 Author: Paulo Cristovão de Araújo Silva Filho <pcris...@gmail.com> AuthorDate: Fri Jul 18 09:37:38 2025 -0300 [OPENJPA-2940][WIP] Intermmediate commit * Removing unused import in BrokerImpl * Implemented new PersistenceUnitUtil load methods --- .../java/org/apache/openjpa/kernel/BrokerImpl.java | 1 - .../TestEntityManagerFactoryLoading.java | 232 +++++++++++++++++++++ .../persistence/EntityManagerFactoryImpl.java | 15 +- .../persistence/OpenJPAPersistenceUtil.java | 25 +++ 4 files changed, 269 insertions(+), 4 deletions(-) diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java index e51c8a103..8b3e4332d 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java @@ -62,7 +62,6 @@ import org.apache.openjpa.kernel.exps.ExpressionParser; import org.apache.openjpa.lib.conf.Configurations; import org.apache.openjpa.lib.instrumentation.InstrumentationLevel; import org.apache.openjpa.lib.log.Log; -import org.apache.openjpa.lib.util.J2DoPrivHelper; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.lib.util.ReferenceHashMap; import org.apache.openjpa.lib.util.ReferenceHashSet; diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/fetchgroups/TestEntityManagerFactoryLoading.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/fetchgroups/TestEntityManagerFactoryLoading.java new file mode 100644 index 000000000..579e70a2d --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/fetchgroups/TestEntityManagerFactoryLoading.java @@ -0,0 +1,232 @@ +/* + * 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 static org.junit.Assert.*; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.apache.openjpa.persistence.OpenJPAEntityManager; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import jakarta.persistence.EntityManager; +import jakarta.persistence.EntityManagerFactory; +import jakarta.persistence.Persistence; +import jakarta.persistence.PersistenceConfiguration; +import jakarta.persistence.metamodel.Attribute; + +public class TestEntityManagerFactoryLoading { + + private static final int MANAGERS_COUNT = 3; + + private static final int EMPLOYEES_PER_MANAGER = 5; + + private static final int EMPLOYEES_COUNT = MANAGERS_COUNT * EMPLOYEES_PER_MANAGER; + + private EntityManagerFactory emf; + + private Map<Integer, FGManager> managers = new HashMap<>(); + + private Set<FGEmployee> employees = new HashSet<FGEmployee>(); + + @Before + public void beforeEach() { + PersistenceConfiguration conf = new PersistenceConfiguration("test"); + conf.property(PersistenceConfiguration.SCHEMAGEN_DATABASE_ACTION, "drop-and-create"); + conf.managedClass(FGManager.class); + conf.managedClass(FGDepartment.class); + conf.managedClass(FGEmployee.class); + conf.managedClass(FGAddress.class); + + emf = Persistence.createEntityManagerFactory(conf); + emf.runInTransaction(this::loadTestData); + } + + @After + public void afterEach() { + if (emf != null && emf.isOpen()) { + emf.close(); + } + } + + @Test + public void testLoadingLazyAttributeByName() { + assertNotNull(emf); + EntityManager em = null; + try { + em = emf.createEntityManager(); + + FGManager manager = em.find(FGManager.class, 1); + + assertFalse(emf.getPersistenceUnitUtil().isLoaded(manager, "employees")); + + emf.getPersistenceUnitUtil().load(manager, "employees"); + + assertTrue(emf.getPersistenceUnitUtil().isLoaded(manager, "employees")); + + assertEquals(EMPLOYEES_PER_MANAGER, manager.getEmployees().size()); + } finally { + if (em != null && em.isOpen()) { + em.close(); + } + } + } + + @Test + public void testLoadingLazyAttribute() { + assertNotNull(emf); + EntityManager em = null; + try { + em = emf.createEntityManager(); + + FGManager manager = em.find(FGManager.class, 1); + Attribute<? super FGManager,?> attribute = em.getMetamodel().entity(FGManager.class).getCollection("employees"); + + assertFalse(emf.getPersistenceUnitUtil().isLoaded(manager, attribute)); + + emf.getPersistenceUnitUtil().load(manager, attribute); + + assertTrue(emf.getPersistenceUnitUtil().isLoaded(manager, attribute)); + + assertEquals(EMPLOYEES_PER_MANAGER, manager.getEmployees().size()); + } finally { + if (em != null && em.isOpen()) { + em.close(); + } + } + } + + @Test + public void testLoadingUnmanagedEntity() { + FGManager manager = new FGManager(); + manager.setId(1); + + try { + emf.getPersistenceUnitUtil().load(manager); + fail("Should have thrown IllegalArgumentException"); + } catch (IllegalArgumentException ex) { + assertTrue(ex.getMessage().contains("not persistent")); + } + + } + + @Test + public void testLoadingEntity() { + EntityManager em = null; + try { + em = emf.createEntityManager(); + FGManager manager = em.find(FGManager.class, 1); + String originalName = manager.getFirstName(); + manager.setFirstName("Changed name"); + assertNotEquals(originalName, manager.getFirstName()); + emf.getPersistenceUnitUtil().load(manager); + assertEquals(originalName, manager.getFirstName()); + } finally { + if (em != null && em.isOpen()) { + em.close(); + } + } + + } + + private void loadTestData(EntityManager em) { + + managers.clear(); + employees.clear(); + + int empIdIndex = 1; + + // Create Managers + for (int i = 0; i < MANAGERS_COUNT; 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); + + managers.put(mgr.getId(), mgr); + } + + // Create Employees + for (int i = 0; i < EMPLOYEES_COUNT; i++) { + int id = empIdIndex++; + int mgrId = (id % MANAGERS_COUNT) + 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); + emp.setManager(managers.get(mgrId)); + + em.persist(emp); + + employees.add(emp); + } + + } + + 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; + } + +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerFactoryImpl.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerFactoryImpl.java index 476918da1..47d06467b 100644 --- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerFactoryImpl.java +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerFactoryImpl.java @@ -61,6 +61,7 @@ import org.apache.openjpa.persistence.criteria.OpenJPACriteriaBuilder; import org.apache.openjpa.persistence.meta.MetamodelImpl; import org.apache.openjpa.persistence.query.OpenJPAQueryBuilder; import org.apache.openjpa.persistence.query.QueryBuilderImpl; +import org.apache.openjpa.util.Exceptions; import org.apache.openjpa.util.OpenJPAException; import org.apache.openjpa.util.UserException; @@ -583,17 +584,25 @@ public class EntityManagerFactoryImpl @Override public void load(Object entity) { - throw new UnsupportedOperationException("Not yet implemented (JPA 3.2)"); + if (!OpenJPAPersistenceUtil.isManagedBy(this, entity)) { + throw new IllegalArgumentException(_loc.get("invalid_entity_argument", + "load", entity == null ? "null" : Exceptions.toString(entity)).getMessage()); + } + OpenJPAPersistenceUtil.load(this, entity); } @Override public void load(Object entity, String attributeName) { - throw new UnsupportedOperationException("Not yet implemented (JPA 3.2)"); + if (!OpenJPAPersistenceUtil.isManagedBy(this, entity)) { + throw new IllegalArgumentException(_loc.get("invalid_entity_argument", + "load", entity == null ? "null" : Exceptions.toString(entity)).getMessage()); + } + OpenJPAPersistenceUtil.load(this, entity, attributeName); } @Override public <E> void load(E entity, Attribute<? super E, ?> attribute) { - throw new UnsupportedOperationException("Not yet implemented (JPA 3.2)"); + load(entity, attribute.getName()); } private void validateCfNameProps(OpenJPAConfiguration conf, String cfName, String cf2Name) { diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/OpenJPAPersistenceUtil.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/OpenJPAPersistenceUtil.java index 7e04b506a..a1ae22fa9 100644 --- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/OpenJPAPersistenceUtil.java +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/OpenJPAPersistenceUtil.java @@ -28,6 +28,7 @@ import jakarta.persistence.spi.LoadState; import org.apache.openjpa.enhance.PersistenceCapable; import org.apache.openjpa.enhance.StateManager; import org.apache.openjpa.kernel.Broker; +import org.apache.openjpa.kernel.OpCallbacks; import org.apache.openjpa.kernel.OpenJPAStateManager; import org.apache.openjpa.kernel.StateManagerImpl; import org.apache.openjpa.meta.FieldMetaData; @@ -104,6 +105,30 @@ public class OpenJPAPersistenceUtil { } return false; } + + public static void load(OpenJPAEntityManagerFactory emf, Object entity) { + if (isManagedBy(emf, entity)) { + PersistenceCapable pc = (PersistenceCapable) entity; + if (pc.pcGetGenericContext() instanceof Broker broker && !broker.isClosed()) { + JPAFacadeHelper.toEntityManager(broker).refresh(entity); + } + } + } + + public static void load(OpenJPAEntityManagerFactory emf, Object entity, String attributeName) { + if (entity == null || !isManagedBy(emf, entity)) { + return; + } + if (entity instanceof PersistenceCapable pc) { + StateManager sm = pc.pcGetStateManager(); + FieldMetaData field = null; + if (sm != null + && sm instanceof OpenJPAStateManager osm + && (field = osm.getMetaData().getField(attributeName)) != null) { + sm.accessingField(field.getIndex()); + } + } + } /** * Determines whether the attribute on the specified object is loaded and