From 634eb8829bdb87ad740e65271b34e6d9fcce99e1 Mon Sep 17 00:00:00 2001 From: Nathan Rauh Date: Fri, 19 Jun 2026 16:05:12 -0500 Subject: [PATCH] TCK tests for NativeQuery Co-authored-by-AI: IBM Bob 1.0.3 --- .../persistence/stateless/Catalog.java | 40 ++++- .../stateless/NativeQueryTests.java | 146 ++++++++++++++++++ 2 files changed, 185 insertions(+), 1 deletion(-) create mode 100644 tck/src/main/java/ee/jakarta/tck/data/standalone/persistence/stateless/NativeQueryTests.java diff --git a/tck/src/main/java/ee/jakarta/tck/data/standalone/persistence/stateless/Catalog.java b/tck/src/main/java/ee/jakarta/tck/data/standalone/persistence/stateless/Catalog.java index b8c885ce8..ccaded118 100644 --- a/tck/src/main/java/ee/jakarta/tck/data/standalone/persistence/stateless/Catalog.java +++ b/tck/src/main/java/ee/jakarta/tck/data/standalone/persistence/stateless/Catalog.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023,2024 Contributors to the Eclipse Foundation + * Copyright (c) 2023,2026 Contributors to the Eclipse Foundation * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -22,18 +22,22 @@ import java.util.stream.Stream; import ee.jakarta.tck.data.standalone.persistence.Product; +import ee.jakarta.tck.data.standalone.persistence._Product; import jakarta.data.Order; +import jakarta.data.constraint.Like; import jakarta.data.repository.By; import jakarta.data.repository.DataRepository; import jakarta.data.repository.Delete; import jakarta.data.repository.Find; import jakarta.data.repository.Insert; +import jakarta.data.repository.Is; import jakarta.data.repository.OrderBy; import jakarta.data.repository.Param; import jakarta.data.repository.Query; import jakarta.data.repository.Repository; import jakarta.data.repository.Save; import jakarta.data.repository.Update; +import jakarta.persistence.query.NativeQuery; @Repository public interface Catalog extends DataRepository { @@ -44,6 +48,15 @@ public interface Catalog extends DataRepository { @Insert Product[] addMultiple(Product... products); + @NativeQuery(""" + DELETE FROM Product + WHERE UPPER(name) = UPPER(?) AND versionNum = ? + """) + int deleteIfNamed(String productName, long version); + + @Delete + long discardAllMatching(@By(ID) @Is(Like.class) String productIdPattern); + @Find Optional get(String productNum); @@ -53,12 +66,37 @@ public interface Catalog extends DataRepository { @Update Product[] modifyMultiple(Product... products); + @Find + @OrderBy(_Product.NAME) + @OrderBy(_Product.PRODUCTNUM) + List named(@By(_Product.NAME) Like namePattern); + + @NativeQuery("SELECT name FROM Product WHERE productNum = ?") + Optional nameOf(String prodNum); + + @NativeQuery("SELECT COUNT(*) FROM Product WHERE price > ?") + long numPricedAbove(double minPrice); + + @NativeQuery(""" + SELECT * FROM Product + WHERE price >= ? AND price <= ? + ORDER BY price ASC + """) + List pricedWithin(double minPrice, double maxPrice); + @Delete void remove(Product product); @Delete void removeMultiple(Product... products); + @NativeQuery(""" + UPDATE Product + SET price = ? + WHERE productNum = ? + """) + int reprice(double newPrice, String productNumber); + @Save void save(Product product); diff --git a/tck/src/main/java/ee/jakarta/tck/data/standalone/persistence/stateless/NativeQueryTests.java b/tck/src/main/java/ee/jakarta/tck/data/standalone/persistence/stateless/NativeQueryTests.java new file mode 100644 index 000000000..87c56f3a4 --- /dev/null +++ b/tck/src/main/java/ee/jakarta/tck/data/standalone/persistence/stateless/NativeQueryTests.java @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * 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. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ +package ee.jakarta.tck.data.standalone.persistence.stateless; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.List; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.WebArchive; + +import ee.jakarta.tck.data.framework.junit.anno.Assertion; +import ee.jakarta.tck.data.framework.junit.anno.Persistence; +import ee.jakarta.tck.data.framework.junit.anno.Standalone; +import ee.jakarta.tck.data.standalone.persistence.Product; +import ee.jakarta.tck.data.standalone.persistence.Product.Department; +import jakarta.inject.Inject; + +/** + * Tests of NativeQuery methods on a repository. + */ +@Standalone +@Persistence +public class NativeQueryTests { + + @Deployment + public static WebArchive createDeployment() { + return ShrinkWrap.create(WebArchive.class) + .addClasses(Catalog.class, + Product.class); + } + + @Inject + Catalog catalog; + + @Assertion(id = "1218", strategy = """ + Use a repository method annotated NativeQuery to run a SQL + SELECT query that returns a count value. + """) + public void testSQLSelectCount() { + catalog.discardAllMatching("TEST-PROD-%"); + + catalog.add(Product.of( + "air fryer", 53.99, "TEST-PROD-2000", Department.APPLIANCES)); + catalog.add(Product.of( + "golf clubs", 599.99, "TEST-PROD-2001", Department.SPORTING_GOODS)); + catalog.add(Product.of( + "rain jacket", 44.99, "TEST-PROD-2002", Department.CLOTHING)); + + assertEquals(2L, + catalog.numPricedAbove(50.0)); + } + + @Assertion(id = "1218", strategy = """ + Use a repository method annotated NativeQuery to run a SQL + SELECT query that retrieves entities. + """) + public void testSQLSelectEntities() { + catalog.discardAllMatching("TEST-PROD-%"); + + catalog.add(Product.of( + "refrigerator", 859.98, "TEST-PROD-2003", Department.APPLIANCES)); + catalog.add(Product.of( + "kayak", 748.99, "TEST-PROD-2004", Department.SPORTING_GOODS)); + catalog.add(Product.of( + "winter coat", 229.99, "TEST-PROD-2005", Department.CLOTHING)); + catalog.add(Product.of( + "tennis balls", 9.98, "TEST-PROD-2006", Department.SPORTING_GOODS)); + catalog.add(Product.of( + "flour", 2.19, "TEST-PROD-2007", Department.GROCERY)); + + assertEquals(List.of("winter coat", + "kayak"), + catalog.pricedWithin(100.0, 750.0) + .stream() + .map(Product::getName) + .toList()); + } + + @Assertion(id = "1218", strategy = """ + Use a repository method annotated NativeQuery to run a SQL + SELECT query that retrieves an entity attribute. + """) + public void testSQLSelectEntityAttribute() { + catalog.discardAllMatching("TEST-PROD-%"); + + catalog.add(Product.of( + "camp stove", 89.99, "TEST-PROD-2008", Department.SPORTING_GOODS)); + catalog.add(Product.of( + "t-shirt", 3.99, "TEST-PROD-2009", Department.CLOTHING)); + catalog.add(Product.of( + "hockey stick", 79.99, "TEST-PROD-2010", Department.SPORTING_GOODS)); + + assertEquals("t-shirt", + catalog.nameOf("TEST-PROD-2009") + .orElseThrow()); + } + + @Assertion(id = "1218", strategy = """ + Use a repository method annotated NativeQuery to run a SQL + UPDATE statement. + """) + public void testSQLUpdate() { + catalog.discardAllMatching("TEST-PROD-%"); + + catalog.add(Product.of( + "smartphone", 799.99, "TEST-PROD-2011", Department.ELECTRONICS)); + catalog.add(Product.of( + "running shoes", 129.99, "TEST-PROD-2012", Department.SPORTING_GOODS)); + catalog.add(Product.of( + "backpack", 39.99, "TEST-PROD-2013", Department.CLOTHING)); + + int updated = catalog.reprice(749.99, "TEST-PROD-2011"); + assertEquals(1, + updated); + + Product smartphone = catalog.get("TEST-PROD-2011").orElseThrow(); + assertEquals(749.99, + smartphone.getPrice(), + 0.001); + + Product shoes = catalog.get("TEST-PROD-2012").orElseThrow(); + assertEquals(129.99, + shoes.getPrice(), + 0.001); + + Product backpack = catalog.get("TEST-PROD-2013").orElseThrow(); + assertEquals(39.99, + backpack.getPrice(), + 0.001); + } +}