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 85fb76146a3f25688e5869a1ac5acc3a4b0e39d6 Author: Paulo Cristovão de Araújo Silva Filho <[email protected]> AuthorDate: Wed Jul 16 11:28:32 2025 -0300 [OPENJPA-2940][WIP] Implemented call and run in transaction EMF methods --- .../TestEntityManagerFactoryTransactions.java | 89 ++++++++++++++++++++++ .../persistence/EntityManagerFactoryImpl.java | 46 ++++++++++- 2 files changed, 132 insertions(+), 3 deletions(-) diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/TestEntityManagerFactoryTransactions.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/TestEntityManagerFactoryTransactions.java new file mode 100644 index 000000000..ed716b958 --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/TestEntityManagerFactoryTransactions.java @@ -0,0 +1,89 @@ +/* + * 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; + +import static org.junit.Assert.*; + +import org.junit.Before; +import org.junit.Test; + +import jakarta.persistence.EntityManager; +import jakarta.persistence.EntityManagerFactory; +import jakarta.persistence.Persistence; +import jakarta.persistence.PersistenceConfiguration; + +public class TestEntityManagerFactoryTransactions { + + private EntityManagerFactory emf; + + @Before + public void before() { + PersistenceConfiguration conf = new PersistenceConfiguration("test"); + conf.provider(PersistenceProviderImpl.class.getCanonicalName()); + conf.property(PersistenceConfiguration.SCHEMAGEN_DATABASE_ACTION, "drop-and-create"); + conf.managedClass(Country.class); + + emf = Persistence.createEntityManagerFactory(conf); + } + + public void after() { + if (emf.isOpen()) { + emf.close(); + } + } + + @Test + public void testCallInTransaction() { + Country country = emf.callInTransaction(em -> { + Country c = new Country(250l, "France"); + em.persist(c); + return c; + }); + EntityManager em = emf.createEntityManager(); + Country c1 = em.find(Country.class, 250l); + assertNotNull(c1); + assertEquals(country.getId(), c1.getId()); + assertEquals("France", c1.getName()); + em.close(); + } + + @Test + public void testRunInTransaction() { + Country a = new Country(36, "Australia"); + emf.runInTransaction(em -> em.persist(a)); + EntityManager em = emf.createEntityManager(); + assertNotNull(em.find(Country.class, 36)); + em.close(); + } + + @Test + public void testCallInTransactionException() { + try { + Country b = new Country(44, "Bahamas"); + emf.runInTransaction(em -> { + em.persist(b); + throw new IllegalStateException("some-exception"); + }); + fail("Should have rethrown exception"); + } catch (Throwable t) { + assertTrue(t.getMessage().startsWith("some-exception")); + } + } + +} 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 3d7d951b8..476918da1 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,8 @@ 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.OpenJPAException; +import org.apache.openjpa.util.UserException; /** * Implementation of {@link EntityManagerFactory} that acts as a @@ -509,12 +511,47 @@ public class EntityManagerFactoryImpl @Override public <R> R callInTransaction(Function<EntityManager, R> work) { - throw new UnsupportedOperationException("Not yet implemented (JPA 3.2)"); + EntityManager em = createEntityManager(); + boolean startedTransaction = false; + boolean jtaTransaction = getTransactionType() == PersistenceUnitTransactionType.JTA; + Broker broker = em.unwrap(Broker.class); + try { + if (jtaTransaction) { + if (!broker.syncWithManagedTransaction()) { + broker.begin(); + startedTransaction = true; + } + } else { + em.getTransaction().begin(); + startedTransaction = true; + } + R result = work.apply(em); + if (startedTransaction) { + if (jtaTransaction) { + broker.commit(); + } else { + em.getTransaction().commit(); + } + } + return result; + } catch (Exception ex) { + if (jtaTransaction) { + broker.rollback(); + } else { + em.getTransaction().rollback(); + } + throw new UserException(ex.getMessage(), ex); + } finally { + em.close(); + } } @Override public void runInTransaction(Consumer<EntityManager> work) { - throw new UnsupportedOperationException("Not yet implemented (JPA 3.2)"); + callInTransaction(em -> { + work.accept(em); + return null; + }); } @Override @@ -529,7 +566,9 @@ public class EntityManagerFactoryImpl @Override public PersistenceUnitTransactionType getTransactionType() { - throw new UnsupportedOperationException("Not yet implemented (JPA 3.2)"); + return "managed".equalsIgnoreCase(_factory.getConfiguration().getTransactionMode()) + ? PersistenceUnitTransactionType.JTA + : PersistenceUnitTransactionType.RESOURCE_LOCAL; } @Override @@ -581,4 +620,5 @@ public class EntityManagerFactoryImpl } } } + }
