From d8f0dfbbb671b8640f02f114013eee665a4802ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Kraus?= Date: Thu, 14 Sep 2023 14:39:54 +0200 Subject: [PATCH] jakartaee/persistence#384 - add Query.getSingleResultOrNull() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomáš Kraus --- .../models/jpa/persistence32/Pokemon.java | 5 +- .../models/jpa/persistence32/Type.java | 2 + .../jpa/persistence32/AbstractPokemon.java | 137 ++++++++++++++++++ ...derTests.java => CriteriaBuilderTest.java} | 68 +++++---- .../EntityManagerFactoryTest.java | 108 ++------------ .../tests/jpa/persistence32/QueryTest.java | 114 +++++++++++++++ .../internal/jpa/EJBQueryImpl.java | 21 +-- .../internal/jpa/EntityGraphImpl.java | 4 - .../jpa/EntityManagerFactoryDelegate.java | 3 - .../jpa/EntityManagerFactoryImpl.java | 4 - .../internal/jpa/EntityManagerImpl.java | 4 +- .../persistence/internal/jpa/QueryImpl.java | 41 +++++- .../jpa/StoredProcedureQueryImpl.java | 43 +++--- .../jpa/querydef/AbstractQueryImpl.java | 2 - .../querydef/CommonAbstractCriteriaImpl.java | 1 - .../jpa/querydef/CriteriaBuilderImpl.java | 13 +- .../jpa/querydef/CriteriaQueryImpl.java | 2 - .../internal/jpa/querydef/OrderImpl.java | 1 - .../persistence/jpa/PersistenceProvider.java | 1 - 19 files changed, 373 insertions(+), 201 deletions(-) create mode 100644 jpa/eclipselink.jpa.testapps/jpa.test.persistence32/src/test/java/org/eclipse/persistence/testing/tests/jpa/persistence32/AbstractPokemon.java rename jpa/eclipselink.jpa.testapps/jpa.test.persistence32/src/test/java/org/eclipse/persistence/testing/tests/jpa/persistence32/{CriteriaBuilderTests.java => CriteriaBuilderTest.java} (93%) create mode 100644 jpa/eclipselink.jpa.testapps/jpa.test.persistence32/src/test/java/org/eclipse/persistence/testing/tests/jpa/persistence32/QueryTest.java diff --git a/jpa/eclipselink.jpa.testapps/jpa.test.persistence32/src/main/java/org/eclipse/persistence/testing/models/jpa/persistence32/Pokemon.java b/jpa/eclipselink.jpa.testapps/jpa.test.persistence32/src/main/java/org/eclipse/persistence/testing/models/jpa/persistence32/Pokemon.java index d61f8a0e89b..a6b07ba8bd8 100644 --- a/jpa/eclipselink.jpa.testapps/jpa.test.persistence32/src/main/java/org/eclipse/persistence/testing/models/jpa/persistence32/Pokemon.java +++ b/jpa/eclipselink.jpa.testapps/jpa.test.persistence32/src/main/java/org/eclipse/persistence/testing/models/jpa/persistence32/Pokemon.java @@ -16,18 +16,19 @@ import java.util.Objects; import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.JoinColumn; import jakarta.persistence.JoinTable; import jakarta.persistence.ManyToMany; +import jakarta.persistence.NamedNativeQuery; import jakarta.persistence.NamedQuery; import jakarta.persistence.Table; @Entity @Table(name="PERSISTENCE32_POKEMON") @NamedQuery(name="Pokemon.get", query="SELECT p FROM Pokemon p WHERE p.id = :id") +@NamedNativeQuery(name="Pokemon.deleteAllTypes", query="DELETE FROM PERSISTENCE32_POKEMON_TYPE") +@NamedNativeQuery(name="Pokemon.deleteAll", query="DELETE FROM PERSISTENCE32_POKEMON") public class Pokemon { // ID is assigned in tests to avoid collisions diff --git a/jpa/eclipselink.jpa.testapps/jpa.test.persistence32/src/main/java/org/eclipse/persistence/testing/models/jpa/persistence32/Type.java b/jpa/eclipselink.jpa.testapps/jpa.test.persistence32/src/main/java/org/eclipse/persistence/testing/models/jpa/persistence32/Type.java index ce11207e001..dcf12fff6c9 100644 --- a/jpa/eclipselink.jpa.testapps/jpa.test.persistence32/src/main/java/org/eclipse/persistence/testing/models/jpa/persistence32/Type.java +++ b/jpa/eclipselink.jpa.testapps/jpa.test.persistence32/src/main/java/org/eclipse/persistence/testing/models/jpa/persistence32/Type.java @@ -16,12 +16,14 @@ import jakarta.persistence.Entity; import jakarta.persistence.Id; +import jakarta.persistence.NamedNativeQuery; import jakarta.persistence.NamedQuery; import jakarta.persistence.Table; @Entity @Table(name="PERSISTENCE32_TYPE") @NamedQuery(name="Type.all", query="SELECT t FROM Type t") +@NamedNativeQuery(name="Type.deleteAll", query="DELETE FROM PERSISTENCE32_TYPE") public class Type { @Id diff --git a/jpa/eclipselink.jpa.testapps/jpa.test.persistence32/src/test/java/org/eclipse/persistence/testing/tests/jpa/persistence32/AbstractPokemon.java b/jpa/eclipselink.jpa.testapps/jpa.test.persistence32/src/test/java/org/eclipse/persistence/testing/tests/jpa/persistence32/AbstractPokemon.java new file mode 100644 index 00000000000..e40fb842a14 --- /dev/null +++ b/jpa/eclipselink.jpa.testapps/jpa.test.persistence32/src/test/java/org/eclipse/persistence/testing/tests/jpa/persistence32/AbstractPokemon.java @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2023 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 + */ + +package org.eclipse.persistence.testing.tests.jpa.persistence32; + +import java.util.HashMap; +import java.util.Map; + +import jakarta.persistence.EntityManager; +import junit.framework.TestSuite; +import org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl; +import org.eclipse.persistence.jpa.JpaEntityManagerFactory; +import org.eclipse.persistence.testing.framework.jpa.junit.JUnitTestCase; +import org.eclipse.persistence.testing.models.jpa.persistence32.Persistence32TableCreator; +import org.eclipse.persistence.testing.models.jpa.persistence32.Type; + +/** + * Abstract jUnit test suite with Pokemon model. + */ +public abstract class AbstractPokemon extends JUnitTestCase { + + // Pokemon types. Array index is ID value. + // Value of ID = 0 does not exist so it's array instance is set to null. + static final Type[] TYPES = new Type[] { + null, // Skip array index 0 + new Type( 1, "Normal"), + new Type( 2, "Fighting"), + new Type( 3, "Flying"), + new Type( 4, "Poison"), + new Type( 5, "Ground"), + new Type( 6, "Rock"), + new Type( 7, "Bug"), + new Type( 8, "Ghost"), + new Type( 9, "Steel"), + new Type(10, "Fire"), + new Type(11, "Water"), + new Type(12, "Grass"), + new Type(13, "Electric"), + new Type(14, "Psychic"), + new Type(15, "Ice"), + new Type(16, "Dragon"), + new Type(17, "Dark"), + new Type(18, "Fairy") + }; + + /** + * Build test suite. + * Adds model test setup as first and model test cleanup as last test + * in the returned tests collection. + * + * @param name name of the suite + * @param tests tests to add to the suite + * @return collection of tests to execute + */ + static TestSuite suite(String name, AbstractPokemon... tests) { + TestSuite suite = new TestSuite(); + suite.setName(name); + suite.addTest(new AbstractPokemon("testSetup") {}); + for (AbstractPokemon test : tests) { + suite.addTest(test); + } + suite.addTest(new AbstractPokemon("testCleanup") {}); + return suite; + } + + JpaEntityManagerFactory emf = null; + + public AbstractPokemon() { + } + + public AbstractPokemon(String name) { + super(name); + setPuName(getPersistenceUnitName()); + } + + @Override + public String getPersistenceUnitName() { + return "persistence32"; + } + + @Override + public void setUp() { + super.setUp(); + emf = getEntityManagerFactory(getPersistenceUnitName()) + .unwrap(EntityManagerFactoryImpl.class); + } + + /** + * Return all pokemon types as ID {@link Map}. + * + * @param em {@link EntityManager} instance to execute the query + * @return {@link Map} with pokemon types + */ + Map pokemonTypes(EntityManager em) { + Map types = new HashMap<>(TYPES.length); + em.createNamedQuery("Type.all", Type.class) + .getResultList() + .forEach(type -> types.put(type.getId(), type)); + return types; + } + + /** + * The setup is done as a test, both to record its failure, and to allow + * execution in the server. + */ + public void testSetup() { + new Persistence32TableCreator().replaceTables(JUnitTestCase.getServerSession(getPersistenceUnitName())); + clearCache(); + emf.runInTransaction(em -> { + for (int i = 1; i < TYPES.length; i++) { + em.persist(TYPES[i]); + } + }); + } + + /** + * The setup is done as a test, both to record its failure, and to allow + * execution in the server. + */ + public void testCleanup() { + emf.runInTransaction(em -> { + em.createNamedQuery("Pokemon.deleteAllTypes").executeUpdate(); + em.createNamedQuery("Pokemon.deleteAll").executeUpdate(); + em.createNamedQuery("Type.deleteAll").executeUpdate(); + }); + } + +} diff --git a/jpa/eclipselink.jpa.testapps/jpa.test.persistence32/src/test/java/org/eclipse/persistence/testing/tests/jpa/persistence32/CriteriaBuilderTests.java b/jpa/eclipselink.jpa.testapps/jpa.test.persistence32/src/test/java/org/eclipse/persistence/testing/tests/jpa/persistence32/CriteriaBuilderTest.java similarity index 93% rename from jpa/eclipselink.jpa.testapps/jpa.test.persistence32/src/test/java/org/eclipse/persistence/testing/tests/jpa/persistence32/CriteriaBuilderTests.java rename to jpa/eclipselink.jpa.testapps/jpa.test.persistence32/src/test/java/org/eclipse/persistence/testing/tests/jpa/persistence32/CriteriaBuilderTest.java index efbd4cc8a00..35d08d8b76e 100644 --- a/jpa/eclipselink.jpa.testapps/jpa.test.persistence32/src/test/java/org/eclipse/persistence/testing/tests/jpa/persistence32/CriteriaBuilderTests.java +++ b/jpa/eclipselink.jpa.testapps/jpa.test.persistence32/src/test/java/org/eclipse/persistence/testing/tests/jpa/persistence32/CriteriaBuilderTest.java @@ -1,3 +1,15 @@ +/* + * Copyright (c) 2023 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 + */ + package org.eclipse.persistence.testing.tests.jpa.persistence32; import java.time.LocalDate; @@ -26,7 +38,7 @@ import org.eclipse.persistence.testing.models.jpa.persistence32.SyntaxEntity; import org.junit.Assert; -public class CriteriaBuilderTests extends JUnitTestCase { +public class CriteriaBuilderTest extends JUnitTestCase { // SyntaxEntity instances, array index is equal to ID // Values must be unique to get just single result and verify it by ID @@ -44,38 +56,38 @@ public class CriteriaBuilderTests extends JUnitTestCase { public static Test suite() { TestSuite suite = new TestSuite(); suite.setName("CriteriaBuilderTests"); - suite.addTest(new CriteriaBuilderTests("testSetup")); - suite.addTest(new CriteriaBuilderTests("testAndPredicateAsListOf0")); - suite.addTest(new CriteriaBuilderTests("testOrPredicateAsListOf0")); - suite.addTest(new CriteriaBuilderTests("testAndPredicateAsListOf1")); - suite.addTest(new CriteriaBuilderTests("testOrPredicateAsListOf1")); - suite.addTest(new CriteriaBuilderTests("testAndPredicateAsListOf2")); - suite.addTest(new CriteriaBuilderTests("testOrPredicateAsListOf2")); - suite.addTest(new CriteriaBuilderTests("testAndPredicateAsListOfN")); - suite.addTest(new CriteriaBuilderTests("testOrPredicateAsListOfN")); - suite.addTest(new CriteriaBuilderTests("testLeftIntLen")); - suite.addTest(new CriteriaBuilderTests("testLeftExprLen")); - suite.addTest(new CriteriaBuilderTests("testRightIntLen")); - suite.addTest(new CriteriaBuilderTests("testRightExprLen")); - suite.addTest(new CriteriaBuilderTests("testReplaceExprExpr")); - suite.addTest(new CriteriaBuilderTests("testReplaceExprStr")); - suite.addTest(new CriteriaBuilderTests("testReplaceStrExpr")); - suite.addTest(new CriteriaBuilderTests("testReplaceStrStr")); - suite.addTest(new CriteriaBuilderTests("testExtractHourFromTime")); - suite.addTest(new CriteriaBuilderTests("testExtractMinuteFromTime")); - suite.addTest(new CriteriaBuilderTests("testExtractSecondFromTime")); - suite.addTest(new CriteriaBuilderTests("testExtractYearFromDate")); - suite.addTest(new CriteriaBuilderTests("testExtractMonthFromDate")); - suite.addTest(new CriteriaBuilderTests("testExtractDayFromDate")); - suite.addTest(new CriteriaBuilderTests("testExtractQuarterFromDate")); - suite.addTest(new CriteriaBuilderTests("testExtractWeekFromDate")); + suite.addTest(new CriteriaBuilderTest("testSetup")); + suite.addTest(new CriteriaBuilderTest("testAndPredicateAsListOf0")); + suite.addTest(new CriteriaBuilderTest("testOrPredicateAsListOf0")); + suite.addTest(new CriteriaBuilderTest("testAndPredicateAsListOf1")); + suite.addTest(new CriteriaBuilderTest("testOrPredicateAsListOf1")); + suite.addTest(new CriteriaBuilderTest("testAndPredicateAsListOf2")); + suite.addTest(new CriteriaBuilderTest("testOrPredicateAsListOf2")); + suite.addTest(new CriteriaBuilderTest("testAndPredicateAsListOfN")); + suite.addTest(new CriteriaBuilderTest("testOrPredicateAsListOfN")); + suite.addTest(new CriteriaBuilderTest("testLeftIntLen")); + suite.addTest(new CriteriaBuilderTest("testLeftExprLen")); + suite.addTest(new CriteriaBuilderTest("testRightIntLen")); + suite.addTest(new CriteriaBuilderTest("testRightExprLen")); + suite.addTest(new CriteriaBuilderTest("testReplaceExprExpr")); + suite.addTest(new CriteriaBuilderTest("testReplaceExprStr")); + suite.addTest(new CriteriaBuilderTest("testReplaceStrExpr")); + suite.addTest(new CriteriaBuilderTest("testReplaceStrStr")); + suite.addTest(new CriteriaBuilderTest("testExtractHourFromTime")); + suite.addTest(new CriteriaBuilderTest("testExtractMinuteFromTime")); + suite.addTest(new CriteriaBuilderTest("testExtractSecondFromTime")); + suite.addTest(new CriteriaBuilderTest("testExtractYearFromDate")); + suite.addTest(new CriteriaBuilderTest("testExtractMonthFromDate")); + suite.addTest(new CriteriaBuilderTest("testExtractDayFromDate")); + suite.addTest(new CriteriaBuilderTest("testExtractQuarterFromDate")); + suite.addTest(new CriteriaBuilderTest("testExtractWeekFromDate")); return suite; } - public CriteriaBuilderTests() { + public CriteriaBuilderTest() { } - public CriteriaBuilderTests(String name) { + public CriteriaBuilderTest(String name) { super(name); setPuName(getPersistenceUnitName()); } diff --git a/jpa/eclipselink.jpa.testapps/jpa.test.persistence32/src/test/java/org/eclipse/persistence/testing/tests/jpa/persistence32/EntityManagerFactoryTest.java b/jpa/eclipselink.jpa.testapps/jpa.test.persistence32/src/test/java/org/eclipse/persistence/testing/tests/jpa/persistence32/EntityManagerFactoryTest.java index b6d8a605977..42e9eb5a042 100644 --- a/jpa/eclipselink.jpa.testapps/jpa.test.persistence32/src/test/java/org/eclipse/persistence/testing/tests/jpa/persistence32/EntityManagerFactoryTest.java +++ b/jpa/eclipselink.jpa.testapps/jpa.test.persistence32/src/test/java/org/eclipse/persistence/testing/tests/jpa/persistence32/EntityManagerFactoryTest.java @@ -15,7 +15,6 @@ import java.sql.Connection; import java.sql.PreparedStatement; import java.util.Collections; -import java.util.HashMap; import java.util.List; import java.util.Map; @@ -27,53 +26,21 @@ import jakarta.persistence.PersistenceException; import jakarta.persistence.PersistenceUnitTransactionType; import junit.framework.Test; -import junit.framework.TestSuite; -import org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl; -import org.eclipse.persistence.jpa.JpaEntityManagerFactory; -import org.eclipse.persistence.testing.framework.jpa.junit.JUnitTestCase; -import org.eclipse.persistence.testing.models.jpa.persistence32.Persistence32TableCreator; import org.eclipse.persistence.testing.models.jpa.persistence32.Pokemon; import org.eclipse.persistence.testing.models.jpa.persistence32.Type; -public class EntityManagerFactoryTest extends JUnitTestCase { - - // Pokemon types. Array index is ID value. Value of ID = 0 does not exist, - // so it's array instance is set to null. - private static final Type[] TYPES = new Type[] { - new Type( 1, "Normal"), - new Type( 2, "Fighting"), - new Type( 3, "Flying"), - new Type( 4, "Poison"), - new Type( 5, "Ground"), - new Type( 6, "Rock"), - new Type( 7, "Bug"), - new Type( 8, "Ghost"), - new Type( 9, "Steel"), - new Type(10, "Fire"), - new Type(11, "Water"), - new Type(12, "Grass"), - new Type(13, "Electric"), - new Type(14, "Psychic"), - new Type(15, "Ice"), - new Type(16, "Dragon"), - new Type(17, "Dark"), - new Type(18, "Fairy") - }; - - private JpaEntityManagerFactory emf = null; +public class EntityManagerFactoryTest extends AbstractPokemon { public static Test suite() { - TestSuite suite = new TestSuite(); - suite.setName("EntityManagerFactoryTest"); - suite.addTest(new EntityManagerFactoryTest("testSetup")); - suite.addTest(new EntityManagerFactoryTest("testCallInTransaction")); - suite.addTest(new EntityManagerFactoryTest("testRunInTransaction")); - suite.addTest(new EntityManagerFactoryTest("testRunWithConnection")); - suite.addTest(new EntityManagerFactoryTest("testCallWithConnection")); - suite.addTest(new EntityManagerFactoryTest("testCreateCustomEntityManagerFactory")); - suite.addTest(new EntityManagerFactoryTest("testCreateConflictingCustomEntityManagerFactory")); - suite.addTest(new EntityManagerFactoryTest("testCreateConflictingConfiguredEntityManagerFactory")); - return suite; + return suite( + "EntityManagerFactoryTest", + new EntityManagerFactoryTest("testCallInTransaction"), + new EntityManagerFactoryTest("testRunInTransaction"), + new EntityManagerFactoryTest("testRunWithConnection"), + new EntityManagerFactoryTest("testCallWithConnection"), + new EntityManagerFactoryTest("testCreateCustomEntityManagerFactory"), + new EntityManagerFactoryTest("testCreateConflictingCustomEntityManagerFactory"), + new EntityManagerFactoryTest("testCreateConflictingConfiguredEntityManagerFactory")); } public EntityManagerFactoryTest() { @@ -84,51 +51,9 @@ public EntityManagerFactoryTest(String name) { setPuName(getPersistenceUnitName()); } - @Override - public String getPersistenceUnitName() { - return "persistence32"; - } - - @Override - public void setUp() { - super.setUp(); - emf = getEntityManagerFactory(getPersistenceUnitName()).unwrap(EntityManagerFactoryImpl.class); - } - - @Override - public void tearDown() { - super.tearDown(); - } - - /** - * The setup is done as a test, both to record its failure, and to allow - * execution in the server. - */ - public void testSetup() { - new Persistence32TableCreator().replaceTables(JUnitTestCase.getServerSession(getPersistenceUnitName())); - clearCache(); - // emf = getEntityManagerFactory(getPersistenceUnitName()); - try (EntityManager em = emf.createEntityManager()) { - EntityTransaction et = em.getTransaction(); - try { - et.begin(); - for (Type type : TYPES) { - em.persist(type); - } - et.commit(); - } catch (Exception e) { - et.rollback(); - throw e; - } - } - } - public void testCallInTransaction() { Pokemon pokemon = emf.callInTransaction(em -> { - Map types = new HashMap<>(24); - em.createNamedQuery("Type.all", Type.class) - .getResultList() - .forEach(type -> types.put(type.getId(), type)); + Map types = pokemonTypes(em); Pokemon newPokemon = new Pokemon(1, "Pidgey", List.of(types.get(1), types.get(3))); em.persist(newPokemon); return newPokemon; @@ -139,10 +64,7 @@ public void testCallInTransaction() { public void testRunInTransaction() { Pokemon[] pokemon = new Pokemon[1]; emf.runInTransaction(em -> { - Map types = new HashMap<>(24); - em.createNamedQuery("Type.all", Type.class) - .getResultList() - .forEach(type -> types.put(type.getId(), type)); + Map types = pokemonTypes(em); Pokemon newPokemon = new Pokemon(2, "Beedrill", List.of(types.get(7), types.get(4))); em.persist(newPokemon); pokemon[0] = newPokemon; @@ -158,7 +80,7 @@ public void testRunWithConnection() { et.begin(); em.runWithConnection( connection -> { - Pokemon newPokemon = new Pokemon(3, "Squirtle", List.of(TYPES[10])); + Pokemon newPokemon = new Pokemon(3, "Squirtle", List.of(TYPES[11])); try (PreparedStatement stmt = connection.prepareStatement( "INSERT INTO PERSISTENCE32_POKEMON (ID, NAME) VALUES(?, ?)")) { stmt.setInt(1, newPokemon.getId()); @@ -196,7 +118,7 @@ public void testCallWithConnection() { et.begin(); pokemon = em.callWithConnection( connection -> { - Pokemon newPokemon = new Pokemon(4, "Caterpie", List.of(TYPES[6])); + Pokemon newPokemon = new Pokemon(4, "Caterpie", List.of(TYPES[7])); try (PreparedStatement stmt = connection.prepareStatement( "INSERT INTO PERSISTENCE32_POKEMON (ID, NAME) VALUES(?, ?)")) { stmt.setInt(1, newPokemon.getId()); @@ -234,7 +156,7 @@ public void testCreateCustomEntityManagerFactory() { configuration.managedClass(org.eclipse.persistence.testing.models.jpa.persistence32.Type.class); configuration.transactionType(PersistenceUnitTransactionType.RESOURCE_LOCAL); configuration.provider("org.eclipse.persistence.jpa.PersistenceProvider"); - Pokemon pokemon = new Pokemon(5, "Primeape", List.of(TYPES[1])); + Pokemon pokemon = new Pokemon(5, "Primeape", List.of(TYPES[2])); try (EntityManagerFactory emfFromConfig = Persistence.createEntityManagerFactory(configuration)) { try (EntityManager em = emfFromConfig.createEntityManager()) { EntityTransaction et = em.getTransaction(); diff --git a/jpa/eclipselink.jpa.testapps/jpa.test.persistence32/src/test/java/org/eclipse/persistence/testing/tests/jpa/persistence32/QueryTest.java b/jpa/eclipselink.jpa.testapps/jpa.test.persistence32/src/test/java/org/eclipse/persistence/testing/tests/jpa/persistence32/QueryTest.java new file mode 100644 index 00000000000..e9eeb65b970 --- /dev/null +++ b/jpa/eclipselink.jpa.testapps/jpa.test.persistence32/src/test/java/org/eclipse/persistence/testing/tests/jpa/persistence32/QueryTest.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2023 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 + */ + +package org.eclipse.persistence.testing.tests.jpa.persistence32; + +import java.util.List; +import java.util.Map; + +import jakarta.persistence.NoResultException; +import jakarta.persistence.NonUniqueResultException; +import junit.framework.Test; +import org.eclipse.persistence.testing.models.jpa.persistence32.Pokemon; +import org.junit.Assert; + +public class QueryTest extends AbstractPokemon { + + // Pokemons. Array index is ID value. + // Value of ID = 0 does not exist so it's array instance is set to null. + static final Pokemon[] POKEMONS = new Pokemon[] { + null, // Skip array index 0 + new Pokemon(1, "Pidgey", List.of(TYPES[1], TYPES[3])), + new Pokemon(2, "Beedrill", List.of(TYPES[7], TYPES[4])), + new Pokemon(3, "Squirtle", List.of(TYPES[11])), + new Pokemon(4, "Caterpie", List.of(TYPES[7])) + }; + + public static Test suite() { + return suite( + "QueryTest", + new QueryTest("testSetup"), + new QueryTest("testGetSingleResultWithEmptyResult"), + new QueryTest("testGetSingleResultWithSingleResult"), + new QueryTest("testGetSingleResultWithMultipleResults"), + new QueryTest("testGetSingleResultOrNullWithEmptyResult"), + new QueryTest("testGetSingleResultOrNullWithSingleResult"), + new QueryTest("testGetSingleResultOrNullWithMultipleResults") + ); + } + + Map pokemons = null; + + public QueryTest() { + } + + public QueryTest(String name) { + super(name); + setPuName(getPersistenceUnitName()); + } + + /** + * The setup is done as a test, both to record its failure, and to allow + * execution in the server. + */ + public void testSetup() { + emf.runInTransaction(em -> { + for (int i = 1; i < POKEMONS.length; i++) { + em.persist(POKEMONS[i]); + } + }); + } + + public void testGetSingleResultWithEmptyResult() { + Assert.assertThrows( + "Query pokemon with not existing name shall throw an exception", + NoResultException.class, + () -> emf.runInTransaction(em -> em.createQuery( + "SELECT p FROM Pokemon p WHERE p.name = 'Charizard'", Pokemon.class).getSingleResult()) + ); + } + + public void testGetSingleResultWithSingleResult() { + Pokemon pokemon = emf.callInTransaction(em -> em.createQuery( + "SELECT p FROM Pokemon p WHERE p.name = 'Pidgey'", Pokemon.class).getSingleResult()); + Assert.assertNotNull("Query pokemon with existing name shall not return null", pokemon); + } + + public void testGetSingleResultWithMultipleResults() { + Assert.assertThrows( + "Query all pokemons shall throw an exception", + NonUniqueResultException.class, + () -> emf.callInTransaction(em -> em.createQuery( + "SELECT p FROM Pokemon p ", Pokemon.class).getSingleResult())); + } + + public void testGetSingleResultOrNullWithEmptyResult() { + Pokemon pokemon = emf.callInTransaction(em -> em.createQuery( + "SELECT p FROM Pokemon p WHERE p.name = 'Charizard'", Pokemon.class).getSingleResultOrNull()); + Assert.assertNull("Query pokemon with not existing name shall return null", pokemon); + } + + public void testGetSingleResultOrNullWithSingleResult() { + Pokemon pokemon = emf.callInTransaction(em -> em.createQuery( + "SELECT p FROM Pokemon p WHERE p.name = 'Pidgey'", Pokemon.class).getSingleResultOrNull()); + Assert.assertNotNull("Query pokemon with existing name shall not return null", pokemon); + } + + public void testGetSingleResultOrNullWithMultipleResults() { + Assert.assertThrows( + "Query all pokemons shall throw an exception", + NonUniqueResultException.class, + () -> emf.callInTransaction(em -> em.createQuery( + "SELECT p FROM Pokemon p ", Pokemon.class).getSingleResultOrNull())); + } + +} diff --git a/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/EJBQueryImpl.java b/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/EJBQueryImpl.java index b5253eb19f1..fd842fdddde 100644 --- a/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/EJBQueryImpl.java +++ b/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/EJBQueryImpl.java @@ -330,13 +330,6 @@ public Integer getTimeout() { throw new UnsupportedOperationException("Jakarta Persistence 3.2 API was not implemented yet"); } - /** - * Set the query timeout. - * - * @param timeout the timeout, or {@code null} to indicate no timeout - * @return the same query instance - * @since 4.1 - */ @Override public TypedQuery setTimeout(Integer timeout) { throw new UnsupportedOperationException("Jakarta Persistence 3.2 API was not implemented yet"); @@ -432,24 +425,16 @@ public Cursor getResultCursor() { } } - /** - * Execute a query that returns a single result. - * - * @return the result - * @throws jakarta.persistence.EntityNotFoundException - * if there is no result - * @throws jakarta.persistence.NonUniqueResultException - * if more than one result - */ @Override + @SuppressWarnings("unchecked") public X getSingleResult() { return (X) super.getSingleResult(); } - // TODO-API-3.2 @Override + @SuppressWarnings("unchecked") public X getSingleResultOrNull() { - throw new UnsupportedOperationException("Jakarta Persistence 3.2 API was not implemented yet"); + return (X) super.getSingleResultOrNull(); } /** diff --git a/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/EntityGraphImpl.java b/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/EntityGraphImpl.java index c91306c6247..08763287606 100644 --- a/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/EntityGraphImpl.java +++ b/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/EntityGraphImpl.java @@ -80,7 +80,6 @@ public String getName() { return attributeGroup.getName(); } - // TODO-API-3.2 @Override public void addAttributeNode(String attributeName) { if (!isMutable) { @@ -105,7 +104,6 @@ public void addAttributeNodes(String... attributeNames) { } } - // TODO-API-3.2 @Override public void addAttributeNode(Attribute attribute) { if (!isMutable) { @@ -166,7 +164,6 @@ public Subgraph addSubgraph(Attribute attribute) { return addSubgraph(attribute.getName(), type); } - // TODO-API-3.2 @Override public Subgraph addTreatedSubgraph(Class type) { if (!this.isMutable) { @@ -192,7 +189,6 @@ public Subgraph addSubclassSubgraph(Class type) { return addTreatedSubgraph((Class)type); } - // TODO-API-3.2 @Override public Subgraph addTreatedSubgraph(Attribute attribute, Class type) { return addSubgraph(attribute.getName(), type); diff --git a/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/EntityManagerFactoryDelegate.java b/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/EntityManagerFactoryDelegate.java index 0ce0521f739..83382e688ad 100644 --- a/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/EntityManagerFactoryDelegate.java +++ b/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/EntityManagerFactoryDelegate.java @@ -729,7 +729,6 @@ public boolean isLoaded(Object entity, String attributeName) { EntityManagerFactoryImpl.isLoaded(entity, attributeName, session)); } - // TODO-API-3.2 @Override public boolean isLoaded(E entity, Attribute attribute) { return isLoaded(entity, attribute.getName()); @@ -853,7 +852,6 @@ public void addNamedEntityGraph(String graphName, EntityGraph entityGraph this.getAbstractSession().getDescriptor(((EntityGraphImpl)entityGraph).getClassType()).addAttributeGroup(group); } - // TODO-API-3.2 @Override public void runInTransaction(Consumer work) { try (EntityManager em = createEntityManager()) { @@ -881,7 +879,6 @@ public void runInTransaction(Consumer work) { } } - // TODO-API-3.2 @Override public R callInTransaction(Function work) { try (EntityManager em = createEntityManager()) { diff --git a/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/EntityManagerFactoryImpl.java b/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/EntityManagerFactoryImpl.java index 68e117e862b..85fec80a38a 100644 --- a/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/EntityManagerFactoryImpl.java +++ b/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/EntityManagerFactoryImpl.java @@ -454,7 +454,6 @@ public PersistenceUnitUtil getPersistenceUnitUtil() { return delegate.getPersistenceUnitUtil(); } - // TODO-API-3.2 @Override public PersistenceUnitTransactionType getTransactionType() { return delegate.getTransactionType(); @@ -603,7 +602,6 @@ public boolean isLoaded(Object entity, String attributeName) { return delegate.isLoaded(entity, attributeName); } - // TODO-API-3.2 @Override public boolean isLoaded(E e, Attribute attribute) { return delegate.isLoaded(e, attribute); @@ -731,13 +729,11 @@ public void addNamedEntityGraph(String graphName, EntityGraph entityGraph this.getServerSession().getDescriptor(((EntityGraphImpl)entityGraph).getClassType()).addAttributeGroup(group); } - // TODO-API-3.2 @Override public void runInTransaction(Consumer work) { delegate.runInTransaction(work); } - // TODO-API-3.2 @Override public R callInTransaction(Function work) { return delegate.callInTransaction(work); diff --git a/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/EntityManagerImpl.java b/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/EntityManagerImpl.java index b54abe2b7c9..93a319de633 100644 --- a/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/EntityManagerImpl.java +++ b/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/EntityManagerImpl.java @@ -831,7 +831,7 @@ public T find(Class entityClass, Object primaryKey, LockModeType lockMode } } - // TODO-API-3.2 - FindOption not defined in EclipseLink scope, just in API. + // TODO-API-3.2 - Missing tests @Override public T find(Class entityClass, Object primaryKey, FindOption... options) { // Passing default find query hints, may be overwritten by options @@ -1456,7 +1456,6 @@ public jakarta.persistence.EntityTransaction getTransaction() { } } - // TODO-API-3.2 @Override public void runWithConnection(ConnectionConsumer action) { if (getAbstractSession().getAccessors().size() > 1) { @@ -1474,7 +1473,6 @@ public void runWithConnection(ConnectionConsumer action) { } } - // TODO-API-3.2 @Override public T callWithConnection(ConnectionFunction function) { if (getAbstractSession().getAccessors().size() > 1) { diff --git a/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/QueryImpl.java b/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/QueryImpl.java index 0d76ca40e3c..7d1cbc613cf 100644 --- a/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/QueryImpl.java +++ b/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/QueryImpl.java @@ -495,6 +495,29 @@ public List getResultList() { } } + /** + * Execute a SELECT query that returns a single untyped result. + * + * @return the result, or {@code null} if there is no result + * @throws NonUniqueResultException if more than one result + * @throws IllegalStateException if called for a Java Persistence query + * language UPDATE or DELETE statement + * @throws QueryTimeoutException if the query execution exceeds the query + * timeout value set and only the statement is rolled back + * @throws TransactionRequiredException if a lock mode other than NONE has + * been been set and there is no transaction or the persistence + * context has not been joined to the transaction + * @throws PessimisticLockException if pessimistic locking fails and the + * transaction is rolled back + * @throws LockTimeoutException if pessimistic locking fails and only the + * statement is rolled back + * @throws PersistenceException if the query execution exceeds the query + * timeout value set and the transaction is rolled back + */ + public Object getSingleResultOrNull() { + return getSingleResult(false); + } + /** * Execute a SELECT query that returns a single untyped result. * @@ -516,6 +539,10 @@ public List getResultList() { * timeout value set and the transaction is rolled back */ public Object getSingleResult() { + return getSingleResult(true); + } + + private Object getSingleResult(boolean failOnEmpty) { boolean rollbackOnException = true; // bug51411440: need to throw IllegalStateException if query // executed on closed em @@ -529,18 +556,22 @@ public Object getSingleResult() { throw new IllegalStateException(ExceptionLocalization.buildMessage("incorrect_query_for_get_single_result")); } Object result = executeReadQuery(); - if (result instanceof List) { - List results = (List) result; + if (result instanceof List results) { if (results.isEmpty()) { - rollbackOnException = false; - throwNoResultException(ExceptionLocalization.buildMessage("no_entities_retrieved_for_get_single_result", null)); + if (failOnEmpty) { + rollbackOnException = false; + throwNoResultException(ExceptionLocalization.buildMessage("no_entities_retrieved_for_get_single_result", + null)); + } else { + return null; + } } else if (results.size() > 1) { rollbackOnException = false; throwNonUniqueResultException(ExceptionLocalization.buildMessage("too_many_results_for_get_single_result", null)); } return results.get(0); } else { - if (result == null) { + if (failOnEmpty && result == null) { rollbackOnException = false; throwNoResultException(ExceptionLocalization.buildMessage("no_entities_retrieved_for_get_single_result", null)); } diff --git a/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/StoredProcedureQueryImpl.java b/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/StoredProcedureQueryImpl.java index afa8c9b98e8..3101a289dd8 100644 --- a/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/StoredProcedureQueryImpl.java +++ b/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/StoredProcedureQueryImpl.java @@ -120,7 +120,7 @@ public StoredProcedureQueryImpl(String name, EntityManagerImpl entityManager) { * execute call available and therefore should not be called unless an * execute statement was issued by the user. */ - protected List buildResultRecords(ResultSet resultSet) { + protected List buildResultRecords(ResultSet resultSet) { try { AbstractSession session = (AbstractSession) getActiveSession(); DatabaseAccessor accessor = (DatabaseAccessor) executeCall.getQuery().getAccessor(); @@ -621,12 +621,17 @@ protected ResultSetMappingQuery getResultSetMappingQuery() { } } - /** - * Execute the query and return the single query result. - * @return a single result object. - */ + @Override + public Object getSingleResultOrNull() { + return getSingleResult(false); + } + @Override public Object getSingleResult() { + return getSingleResult(true); + } + + private Object getSingleResult(boolean failOnEmpty) { // bug51411440: need to throw IllegalStateException if query // executed on closed em this.entityManager.verifyOpenWithSetRollbackOnly(); @@ -644,28 +649,28 @@ public Object getSingleResult() { // If the return value is true indicating a result set then // build and return the single result. if (execute()) { - return getSingleResult(); + return getSingleResult(failOnEmpty); } else { throw new IllegalStateException(ExceptionLocalization.buildMessage("incorrect_spq_query_for_get_result_list")); } } else { if (hasMoreResults()) { // Build the result records first. - List results; + List results; if (isOutputCursorResultSet) { // Return result set list for the current outputCursorIndex. if (hasPositionalParameters()) { - results = (List) getOutputParameterValue(getCall().getOutputCursors().get(outputCursorIndex++).getIndex() + 1); + results = (List) getOutputParameterValue(getCall().getOutputCursors().get(outputCursorIndex++).getIndex() + 1); } else { - results = (List) getOutputParameterValue(getCall().getOutputCursors().get(outputCursorIndex++).getName()); + results = (List) getOutputParameterValue(getCall().getOutputCursors().get(outputCursorIndex++).getName()); } // Update the hasMoreResults flag. hasMoreResults = (outputCursorIndex < getCall().getOutputCursors().size()); } else { // Build the result records first. - List result = buildResultRecords(executeStatement.getResultSet()); + List result = buildResultRecords(executeStatement.getResultSet()); // Move the result pointer. moveResultPointer(); @@ -675,11 +680,14 @@ public Object getSingleResult() { if (results.size() > 1) { throwNonUniqueResultException(ExceptionLocalization.buildMessage("too_many_results_for_get_single_result", null)); - } else if (results.isEmpty()) { + } else if (failOnEmpty && results.isEmpty()) { throwNoResultException(ExceptionLocalization.buildMessage("no_entities_retrieved_for_get_single_result", null)); } - // TODO: if hasMoreResults is true, we 'could' and maybe should throw an exception here. + // If hasMoreResults is true, we should throw an exception here. + if (results.size() > 1 || hasMoreResults) { + throwNonUniqueResultException(ExceptionLocalization.buildMessage("too_many_results_for_get_single_result", null)); + } return results.get(0); } else { @@ -688,10 +696,7 @@ public Object getSingleResult() { } } catch (LockTimeoutException e) { throw e; - } catch (PersistenceException e) { - setRollbackOnly(); - throw e; - } catch (IllegalStateException e) { + } catch (PersistenceException | IllegalStateException e) { setRollbackOnly(); throw e; } catch (Exception e) { @@ -702,12 +707,6 @@ public Object getSingleResult() { } } - // TODO-API-3.2 - @Override - public Object getSingleResultOrNull() { - throw new UnsupportedOperationException("Jakarta Persistence 3.2 API was not implemented yet"); - } - /** * Returns the update count or -1 if there is no pending result * or if the next result is not an update count. diff --git a/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/querydef/AbstractQueryImpl.java b/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/querydef/AbstractQueryImpl.java index fabe9705e4b..fbabc45d440 100644 --- a/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/querydef/AbstractQueryImpl.java +++ b/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/querydef/AbstractQueryImpl.java @@ -139,7 +139,6 @@ public AbstractQuery having(Predicate... restrictions) { return having(restrictions != null ? List.of(restrictions) : null); } - // TODO-API-3.2 @Override public AbstractQuery having(List restrictions) { Predicate predicate = queryBuilder.and(restrictions); @@ -305,7 +304,6 @@ public AbstractQuery where(Predicate... restrictions) { return (AbstractQuery) super.where(restrictions); } - // TODO-API-3.2 @Override @SuppressWarnings("unchecked") public AbstractQuery where(List restrictions) { diff --git a/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/querydef/CommonAbstractCriteriaImpl.java b/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/querydef/CommonAbstractCriteriaImpl.java index 34230268a59..331ea8f1f41 100644 --- a/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/querydef/CommonAbstractCriteriaImpl.java +++ b/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/querydef/CommonAbstractCriteriaImpl.java @@ -179,7 +179,6 @@ public Subquery subquery(Class type) { return new SubQueryImpl(metamodel, type, queryBuilder, this); } - // TODO-API-3.2 @Override public Subquery subquery(EntityType type) { return subquery(type.getJavaType()); diff --git a/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/querydef/CriteriaBuilderImpl.java b/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/querydef/CriteriaBuilderImpl.java index 608292e5d89..9276e1c922e 100644 --- a/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/querydef/CriteriaBuilderImpl.java +++ b/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/querydef/CriteriaBuilderImpl.java @@ -460,7 +460,6 @@ public Predicate and(Predicate... restrictions) { return and(restrictions != null ? List.of(restrictions) : null); } - // TODO-API-3.2 @Override public Predicate and(List restrictions) { // PERF: Build simple cases directly @@ -492,7 +491,6 @@ public Predicate or(Predicate... restrictions) { return or(restrictions != null ? List.of(restrictions) : null); } - // TODO-API-3.2 @Override public Predicate or(List restrictions) { // PERF: Build simple cases directly @@ -1889,7 +1887,6 @@ public Predicate notLike(Expression x, String pattern, char escapeChar){ return this.notLike(x, this.internalLiteral(pattern), this.internalLiteral(escapeChar)); } - // TODO-API-3.2 @Override public Expression concat(List> expressions) { switch(expressions != null ? expressions.size() : 0) { @@ -2160,7 +2157,6 @@ public Expression length(Expression x){ return new FunctionExpressionImpl(metamodel, ClassConstants.INTEGER, ((InternalSelection)x).getCurrentNode().length(), buildList(x), "length"); } - // TODO-API-3.2 @Override public Expression left(Expression expression, int len) { return new FunctionExpressionImpl<>( @@ -2168,7 +2164,6 @@ public Expression left(Expression expression, int len) { currentNode(expression).left(len), buildList(expression), "left"); } - // TODO-API-3.2 @Override public Expression left(Expression expression, Expression len) { return new FunctionExpressionImpl<>( @@ -2176,7 +2171,6 @@ public Expression left(Expression expression, Expression right(Expression expression, int len) { return new FunctionExpressionImpl<>( @@ -2184,7 +2178,6 @@ public Expression right(Expression expression, int len) { currentNode(expression).right(len), buildList(expression), "right"); } - // TODO-API-3.2 @Override public Expression right(Expression expression, Expression len) { return new FunctionExpressionImpl<>( @@ -2192,7 +2185,6 @@ public Expression right(Expression expression, Expression replace(Expression expression, Expression substring, Expression replacement) { return new FunctionExpressionImpl<>( @@ -2201,7 +2193,6 @@ public Expression replace(Expression expression, Expression replace(Expression expression, String substring, Expression replacement) { return new FunctionExpressionImpl<>( @@ -2210,7 +2201,6 @@ public Expression replace(Expression expression, String substrin buildList(expression), "replace"); } - // TODO-API-3.2 @Override public Expression replace(Expression expression, Expression substring, String replacement) { return new FunctionExpressionImpl<>( @@ -2219,7 +2209,6 @@ public Expression replace(Expression expression, Expression replace(Expression expression, String substring, String replacement) { return new FunctionExpressionImpl<>( @@ -2361,11 +2350,11 @@ public Expression localTime() { return new ExpressionImpl(metamodel, ClassConstants.LOCAL_TIME, new ExpressionBuilder().localTime()); } - // TODO-API-3.2 - not sure whether (Class) temporal.getJavaType() is sufficient for result class @Override @SuppressWarnings("unchecked") public Expression extract(TemporalField field, Expression temporal) { return new FunctionExpressionImpl<>( + // Java type took from Expression, but not sure whether this will work for everything this.metamodel, (Class) temporal.getJavaType(), // JPA API: field.toString() returns name of the part to be extracted currentNode(temporal).extract(field.toString()), buildList(temporal), "extract"); diff --git a/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/querydef/CriteriaQueryImpl.java b/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/querydef/CriteriaQueryImpl.java index 4eecf9da9ed..37d63691058 100644 --- a/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/querydef/CriteriaQueryImpl.java +++ b/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/querydef/CriteriaQueryImpl.java @@ -249,7 +249,6 @@ public CriteriaQuery where(Predicate... restrictions) { return (CriteriaQuery) super.where(restrictions); } - // TODO-API-3.2 @Override public CriteriaQuery where(List restrictions) { return (CriteriaQuery) super.where(restrictions); @@ -301,7 +300,6 @@ public CriteriaQuery having(Predicate... restrictions) { return this; } - // TODO-API-3.2 @Override public CriteriaQuery having(List restrictions) { super.having(restrictions); diff --git a/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/querydef/OrderImpl.java b/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/querydef/OrderImpl.java index f862661f68b..92f59b1153c 100644 --- a/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/querydef/OrderImpl.java +++ b/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/internal/jpa/querydef/OrderImpl.java @@ -54,7 +54,6 @@ public boolean isAscending() { return this.isAscending; } - // TODO-API-3.2 @Override public Nulls getNullPrecedence() { return nullPrecedence; diff --git a/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/jpa/PersistenceProvider.java b/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/jpa/PersistenceProvider.java index 60cbe5685cd..5da83f9a652 100644 --- a/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/jpa/PersistenceProvider.java +++ b/jpa/org.eclipse.persistence.jpa/src/main/java/org/eclipse/persistence/jpa/PersistenceProvider.java @@ -185,7 +185,6 @@ public EntityManagerFactory createEntityManagerFactory(String emName, Map return null; } - // TODO-API-3.2 @Override public EntityManagerFactory createEntityManagerFactory(PersistenceConfiguration configuration) { JPAInitializer initializer = getInitializer(configuration.name(), configuration.properties());