From 96ef4256a88d8d13302445f54c763189cdf767f4 Mon Sep 17 00:00:00 2001 From: Gavin King Date: Sat, 21 Mar 2026 19:14:55 +0100 Subject: [PATCH 1/2] replace @XxxxQueryOptions with one @StaticQuryOptions annotation alternate solution to #806 --- .../jakarta/persistence/QueryFlushMode.java | 3 +- .../java/jakarta/persistence/Reference.java | 6 +- .../persistence/TypedQueryReference.java | 13 ++-- .../persistence/query/StaticNativeQuery.java | 2 +- .../persistence/query/StaticQuery.java | 2 +- ...ryOptions.java => StaticQueryOptions.java} | 37 +++++---- .../query/StaticStatementReference.java | 8 +- .../query/StaticTypedQueryReference.java | 18 ++--- .../persistence/query/WriteQueryOptions.java | 76 ------------------- .../main/asciidoc/appA-revision-history.adoc | 2 +- .../main/asciidoc/appF-static-queries.adoc | 10 +-- .../main/asciidoc/ch03-entity-operations.adoc | 4 +- .../src/main/asciidoc/ch05-metamodel-api.adoc | 6 +- .../asciidoc/ch10-metadata-annotations.adoc | 38 ++-------- 14 files changed, 62 insertions(+), 163 deletions(-) rename api/src/main/java/jakarta/persistence/query/{ReadQueryOptions.java => StaticQueryOptions.java} (81%) delete mode 100644 api/src/main/java/jakarta/persistence/query/WriteQueryOptions.java diff --git a/api/src/main/java/jakarta/persistence/QueryFlushMode.java b/api/src/main/java/jakarta/persistence/QueryFlushMode.java index be0c288f0..a67493063 100644 --- a/api/src/main/java/jakarta/persistence/QueryFlushMode.java +++ b/api/src/main/java/jakarta/persistence/QueryFlushMode.java @@ -75,8 +75,7 @@ * @see Query#setQueryFlushMode(QueryFlushMode) * @see NamedQuery#flush * @see NamedNativeQuery#flush - * @see jakarta.persistence.query.ReadQueryOptions#flush - * @see jakarta.persistence.query.WriteQueryOptions#flush + * @see jakarta.persistence.query.StaticQueryOptions#flush * @see FlushModeType * * @author Gavin King diff --git a/api/src/main/java/jakarta/persistence/Reference.java b/api/src/main/java/jakarta/persistence/Reference.java index 5b0d91429..7ebb09965 100644 --- a/api/src/main/java/jakarta/persistence/Reference.java +++ b/api/src/main/java/jakarta/persistence/Reference.java @@ -44,8 +44,7 @@ public sealed interface Reference /** * A map keyed by hint name of all hints specified via * {@link NamedQuery#hints}, {@link NamedNativeQuery#hints}, - * {@link jakarta.persistence.query.ReadQueryOptions#hints}, or - * {@link jakarta.persistence.query.WriteQueryOptions#hints}. + * {@link jakarta.persistence.query.StaticQueryOptions#hints}, or *

* Any attempted mutation of the returned map results in an * {@link UnsupportedOperationException}. @@ -113,8 +112,7 @@ public sealed interface Reference * {@code null} if no timeout was specified. * * @see Query#setTimeout(Timeout) - * @see jakarta.persistence.query.ReadQueryOptions#timeout - * @see jakarta.persistence.query.WriteQueryOptions#timeout + * @see jakarta.persistence.query.StaticQueryOptions#timeout * @since 4.0 */ Timeout getTimeout(); diff --git a/api/src/main/java/jakarta/persistence/TypedQueryReference.java b/api/src/main/java/jakarta/persistence/TypedQueryReference.java index 278e0ef6d..a29415323 100644 --- a/api/src/main/java/jakarta/persistence/TypedQueryReference.java +++ b/api/src/main/java/jakarta/persistence/TypedQueryReference.java @@ -16,8 +16,7 @@ package jakarta.persistence; -import java.util.List; -import java.util.Map; +import jakarta.persistence.query.StaticQueryOptions; /** * A reference to a typed named query declared via the @@ -110,7 +109,7 @@ public non-sealed interface TypedQueryReference extends Reference { * {@link EntityHandler} should be used. * * @see TypedQuery#setCacheRetrieveMode - * @see jakarta.persistence.query.ReadQueryOptions#cacheRetrieveMode + * @see StaticQueryOptions#cacheRetrieveMode * @since 4.0 */ CacheRetrieveMode getCacheRetrieveMode(); @@ -121,7 +120,7 @@ public non-sealed interface TypedQueryReference extends Reference { * {@link EntityHandler} should be used. * * @see TypedQuery#setCacheStoreMode - * @see jakarta.persistence.query.ReadQueryOptions#cacheStoreMode + * @see StaticQueryOptions#cacheStoreMode * @since 4.0 */ CacheStoreMode getCacheStoreMode(); @@ -133,7 +132,7 @@ public non-sealed interface TypedQueryReference extends Reference { * * @see TypedQuery#setLockMode * @see NamedQuery#lockMode - * @see jakarta.persistence.query.ReadQueryOptions#lockMode + * @see StaticQueryOptions#lockMode * @since 4.0 */ LockModeType getLockMode(); @@ -145,7 +144,7 @@ public non-sealed interface TypedQueryReference extends Reference { * * @see TypedQuery#setLockScope * @see NamedQuery#lockScope - * @see jakarta.persistence.query.ReadQueryOptions#lockScope + * @see StaticQueryOptions#lockScope * @since 4.0 */ PessimisticLockScope getPessimisticLockScope(); @@ -156,7 +155,7 @@ public non-sealed interface TypedQueryReference extends Reference { * specified. * * @see NamedQuery#entityGraph - * @see jakarta.persistence.query.ReadQueryOptions#entityGraph + * @see StaticQueryOptions#entityGraph * @since 4.0 */ String getEntityGraphName(); diff --git a/api/src/main/java/jakarta/persistence/query/StaticNativeQuery.java b/api/src/main/java/jakarta/persistence/query/StaticNativeQuery.java index 7c5ef3a5b..267d88b12 100644 --- a/api/src/main/java/jakarta/persistence/query/StaticNativeQuery.java +++ b/api/src/main/java/jakarta/persistence/query/StaticNativeQuery.java @@ -40,7 +40,7 @@ * interface Library { * * @StaticNativeQuery("select * from books where title like ?") - * @ReadQueryOptions(cacheStoreMode = CacheStoreMode.BYPASS) + * @StaticQueryOptions(cacheStoreMode = CacheStoreMode.BYPASS) * List findBooksByTitle(String title); * * @StaticNativeQuery("select * from books where isbn = ?") diff --git a/api/src/main/java/jakarta/persistence/query/StaticQuery.java b/api/src/main/java/jakarta/persistence/query/StaticQuery.java index 79faf7095..386bc59a1 100644 --- a/api/src/main/java/jakarta/persistence/query/StaticQuery.java +++ b/api/src/main/java/jakarta/persistence/query/StaticQuery.java @@ -42,7 +42,7 @@ * interface Library { * * @StaticQuery("from Book where title like :title") - * @ReadQueryOptions(cacheStoreMode = CacheStoreMode.BYPASS) + * @StaticQueryOptions(cacheStoreMode = CacheStoreMode.BYPASS) * List findBooksByTitle(String title); * * @StaticQuery("from Book where isbn = :isbn") diff --git a/api/src/main/java/jakarta/persistence/query/ReadQueryOptions.java b/api/src/main/java/jakarta/persistence/query/StaticQueryOptions.java similarity index 81% rename from api/src/main/java/jakarta/persistence/query/ReadQueryOptions.java rename to api/src/main/java/jakarta/persistence/query/StaticQueryOptions.java index 83401097d..f1dbc5d13 100644 --- a/api/src/main/java/jakarta/persistence/query/ReadQueryOptions.java +++ b/api/src/main/java/jakarta/persistence/query/StaticQueryOptions.java @@ -30,17 +30,13 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME; /** - *

Configures options that affect the execution of a - * database read operation. This annotation may be applied - * to: + *

Configures options that affect the execution of a query. + * This annotation may be applied to: *

@@ -48,17 +44,19 @@ *

This annotation must be respected by an implementation * of Jakarta Data backed by Jakarta Persistence. * - * @see WriteQueryOptions - * * @since 4.0 */ @Target(METHOD) @Retention(RUNTIME) -public @interface ReadQueryOptions { +public @interface StaticQueryOptions { /** * The {@linkplain CacheStoreMode cache store mode} to use. * The presence of this annotation overrides the default * cache store mode of the persistence context. + *

+ * This option applies when the query is a JPQL {@code select} + * query or a native query that returns a result set. + * * @see jakarta.persistence.TypedQuery#setCacheStoreMode */ CacheStoreMode cacheStoreMode() default CacheStoreMode.USE; @@ -67,6 +65,10 @@ * The {@linkplain CacheRetrieveMode cache retrieve mode} * to use. The presence of this annotation overrides the * default cache retrieve mode of the persistence context. + *

+ * This option applies when the query is a JPQL {@code select} + * query or a native query that returns a result set. + * * @see jakarta.persistence.TypedQuery#setCacheRetrieveMode */ CacheRetrieveMode cacheRetrieveMode() default CacheRetrieveMode.USE; @@ -93,6 +95,10 @@ *

If a lock mode is explicitly specified for a * {@linkplain StaticNativeQuery native query}, the behavior * is undefined and unportable between persistence providers. + *

+ * This option applies when the query is a JPQL {@code select} + * query or a native query that returns a result set. + * * @see jakarta.persistence.TypedQuery#setLockMode */ LockModeType lockMode() default LockModeType.NONE; @@ -100,6 +106,9 @@ /** * The pessimistic lock scope to use in query execution if a * pessimistic lock mode is specified via {@link #lockMode}. + *

+ * This option applies when the query is a JPQL {@code select} + * query or a native query that returns a result set. */ PessimisticLockScope lockScope() default PessimisticLockScope.NORMAL; @@ -112,6 +121,9 @@ * entity type, the behavior is undefined. The entity graph * is interpreted as a load graph. The entity graph specified * here may be overridden by calling {@code setEntityGraph()}. + *

+ * This option applies when the query is a JPQL {@code select}. + * * * @see jakarta.persistence.NamedEntityGraph#name */ @@ -121,7 +133,6 @@ * The {@linkplain QueryFlushMode query flush mode} to use when * executing the query. * @see Query#setQueryFlushMode(QueryFlushMode) - * @since 4.0 */ QueryFlushMode flush() default QueryFlushMode.DEFAULT; } \ No newline at end of file diff --git a/api/src/main/java/jakarta/persistence/query/StaticStatementReference.java b/api/src/main/java/jakarta/persistence/query/StaticStatementReference.java index 5ee4f1d2e..f7408a5f7 100644 --- a/api/src/main/java/jakarta/persistence/query/StaticStatementReference.java +++ b/api/src/main/java/jakarta/persistence/query/StaticStatementReference.java @@ -48,7 +48,7 @@ public class StaticStatementReference /** * Intended for use in code generated by an annotation processor. * This constructor overload is adapted to the case where the - * program element is annotated with {@link WriteQueryOptions}. + * program element is annotated with {@link StaticQueryOptions}. * * @param queryName The name of the query, the concatenation of * the unqualified name of the annotated type, @@ -62,8 +62,8 @@ public class StaticStatementReference * annotated member * @param arguments The arguments supplied to the parameters * at runtime - * @param timeout See {@link WriteQueryOptions#timeout} - * @param hints See {@link WriteQueryOptions#hints} + * @param timeout See {@link StaticQueryOptions#timeout} + * @param hints See {@link StaticQueryOptions#hints} */ public StaticStatementReference( String queryName, @@ -87,7 +87,7 @@ public StaticStatementReference( /** * Intended for use in code generated by an annotation processor. * This constructor overload is adapted to the case where the - * program element is not annotated with {@link WriteQueryOptions}. + * program element is not annotated with {@link StaticQueryOptions}. * * @param queryName The name of the query, the concatenation of * the unqualified name of the annotated type, diff --git a/api/src/main/java/jakarta/persistence/query/StaticTypedQueryReference.java b/api/src/main/java/jakarta/persistence/query/StaticTypedQueryReference.java index c2c1303fb..5cb49def3 100644 --- a/api/src/main/java/jakarta/persistence/query/StaticTypedQueryReference.java +++ b/api/src/main/java/jakarta/persistence/query/StaticTypedQueryReference.java @@ -61,7 +61,7 @@ public class StaticTypedQueryReference /** * Intended for use in code generated by an annotation processor. * This constructor overload is adapted to the case where the - * program element is annotated with {@link ReadQueryOptions}. + * program element is annotated with {@link StaticQueryOptions}. * * @param queryName The name of the query, the concatenation of * the unqualified name of the annotated type, @@ -77,13 +77,13 @@ public class StaticTypedQueryReference * annotated member * @param arguments The arguments supplied to the parameters * at runtime - * @param cacheRetrieveMode See {@link ReadQueryOptions#cacheRetrieveMode} - * @param cacheStoreMode See {@link ReadQueryOptions#cacheStoreMode} - * @param lockMode See {@link ReadQueryOptions#lockMode} - * @param lockScope See {@link ReadQueryOptions#lockScope} - * @param timeout See {@link ReadQueryOptions#timeout} - * @param entityGraphName See {@link ReadQueryOptions#entityGraph} - * @param hints See {@link ReadQueryOptions#hints} + * @param cacheRetrieveMode See {@link StaticQueryOptions#cacheRetrieveMode} + * @param cacheStoreMode See {@link StaticQueryOptions#cacheStoreMode} + * @param lockMode See {@link StaticQueryOptions#lockMode} + * @param lockScope See {@link StaticQueryOptions#lockScope} + * @param timeout See {@link StaticQueryOptions#timeout} + * @param entityGraphName See {@link StaticQueryOptions#entityGraph} + * @param hints See {@link StaticQueryOptions#hints} */ public StaticTypedQueryReference( String queryName, @@ -119,7 +119,7 @@ public StaticTypedQueryReference( /** * Intended for use in code generated by an annotation processor. * This constructor overload is adapted to the case where the - * program element is not annotated with {@link ReadQueryOptions}. + * program element is not annotated with {@link StaticQueryOptions}. * * @param queryName The name of the query, the concatenation of * the unqualified name of the annotated type, diff --git a/api/src/main/java/jakarta/persistence/query/WriteQueryOptions.java b/api/src/main/java/jakarta/persistence/query/WriteQueryOptions.java deleted file mode 100644 index 4f3abf9bd..000000000 --- a/api/src/main/java/jakarta/persistence/query/WriteQueryOptions.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2025 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, - * 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: -// Gavin King - 4.0 - -package jakarta.persistence.query; - -import jakarta.persistence.Query; -import jakarta.persistence.QueryFlushMode; -import jakarta.persistence.QueryHint; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -/** - *

Configures options that affect the execution of a - * database write operation. This annotation may be applied - * to: - *

- * - *

This annotation must be respected by an implementation - * of Jakarta Data backed by Jakarta Persistence. - * - * @see ReadQueryOptions - * - * @since 4.0 - */ -@Target(METHOD) -@Retention(RUNTIME) -public @interface WriteQueryOptions { - /** - * A query timeout in milliseconds. - * By default, there is no timeout. - * @see jakarta.persistence.Query#setTimeout - */ - int timeout() default -1; - - /** - * Query properties and hints. - * May include vendor-specific query hints. - * @see jakarta.persistence.Query#setHint(String, Object) - */ - QueryHint[] hints() default {}; - - /** - * The {@linkplain QueryFlushMode query flush mode} to use when - * executing the query. - * @see Query#setQueryFlushMode(QueryFlushMode) - * @since 4.0 - */ - QueryFlushMode flush() default QueryFlushMode.DEFAULT; -} \ No newline at end of file diff --git a/spec/src/main/asciidoc/appA-revision-history.adoc b/spec/src/main/asciidoc/appA-revision-history.adoc index de70b2a4d..0b20495c9 100644 --- a/spec/src/main/asciidoc/appA-revision-history.adoc +++ b/spec/src/main/asciidoc/appA-revision-history.adoc @@ -13,7 +13,7 @@ This appendix lists the significant changes that have been made during the devel Added `EntityAgent` and `EntityHandler` -Added `@StaticQuery`, `@StaticNativeQuery`, `@ReadQueryOptions`, `@WriteQueryOptions` and `StaticStatementReference` for declaring static queries at the method level, along with additional members of `TypedQueryReference` +Added `@StaticQuery`, `@StaticNativeQuery`, `@StaticQueryOptions`, and `StaticStatementReference` for declaring static queries at the method level, along with additional members of `TypedQueryReference` Added a new API for programmatic SQL result set mappings diff --git a/spec/src/main/asciidoc/appF-static-queries.adoc b/spec/src/main/asciidoc/appF-static-queries.adoc index 853955007..86d5deb3d 100644 --- a/spec/src/main/asciidoc/appF-static-queries.adoc +++ b/spec/src/main/asciidoc/appF-static-queries.adoc @@ -14,16 +14,10 @@ include::../../../../api/src/main/java/jakarta/persistence/query/StaticQuery.jav include::../../../../api/src/main/java/jakarta/persistence/query/StaticNativeQuery.java[lines=18..-1] ---- -=== `ReadQueryOptions` +=== `StaticQueryOptions` [source,java] ---- -include::../../../../api/src/main/java/jakarta/persistence/query/ReadQueryOptions.java[lines=18..-1] ----- - -=== `WriteQueryOptions` -[source,java] ----- -include::../../../../api/src/main/java/jakarta/persistence/query/WriteQueryOptions.java[lines=18..-1] +include::../../../../api/src/main/java/jakarta/persistence/query/StaticQueryOptions.java[lines=18..-1] ---- === `StaticStatementReference` diff --git a/spec/src/main/asciidoc/ch03-entity-operations.adoc b/spec/src/main/asciidoc/ch03-entity-operations.adoc index 390818914..509478d92 100644 --- a/spec/src/main/asciidoc/ch03-entity-operations.adoc +++ b/spec/src/main/asciidoc/ch03-entity-operations.adoc @@ -3243,7 +3243,7 @@ Execution of a JPQL query obtains a lock on queried records if the application requests such a lock by: - calling `setLockMode()`, or -- specifying the `lockMode` member of the `@ReadQueryOptions` or +- specifying the `lockMode` member of the `@StaticQueryOptions` or `@NamedQuery` annotation. If a query is executed when no transaction is active, then the specified @@ -3260,7 +3260,7 @@ object.] The scope of a pessimistic lock, as defined above in <>, is controlled by: - calling `setLockScope()`, or -- specifying the `lockScope` member of the `@ReadQueryOptions` or +- specifying the `lockScope` member of the `@StaticQueryOptions` or `@NamedQuery` annotation. If the lock mode type is `PESSIMISTIC_READ`, diff --git a/spec/src/main/asciidoc/ch05-metamodel-api.adoc b/spec/src/main/asciidoc/ch05-metamodel-api.adoc index d187bd76c..2055d4b82 100644 --- a/spec/src/main/asciidoc/ch05-metamodel-api.adoc +++ b/spec/src/main/asciidoc/ch05-metamodel-api.adoc @@ -209,8 +209,8 @@ public static TypedQueryReference m(T1 p1, T2 p2, ...) { ---- + where (`h1`, `v1`), (`h2`, `v2`), etc., are `hints` and `o1`, `o2`, etc., -are options specified by any `@ReadQueryOptions` annotation of `m`. If the -annotated method has more parameters than the query specified by the +are options specified by any `@StaticQueryOptions` annotation of `m`. If +the annotated method has more parameters than the query specified by the annotation `value` member, the annotation processor is permitted to ignore the method parameters which do not correspond to parameters of the query, but this behavior is not required and is not portable between different @@ -240,7 +240,7 @@ public static StatementReference m(T1 p1, T2 p2, ...) { ---- + where (`h1`, `v1`), (`h2`, `v2`), etc., are `hints` and `o1`, `o2`, etc., -are options specified by any `@WriteQueryOptions` annotation of `m`. If +are options specified by any `@StaticQueryOptions` annotation of `m`. If the annotated method has more parameters than the query specified by the annotation `value` member, the annotation processor is permitted to ignore the method parameters which do not correspond to parameters of the query, diff --git a/spec/src/main/asciidoc/ch10-metadata-annotations.adoc b/spec/src/main/asciidoc/ch10-metadata-annotations.adoc index b9a21d423..2f1602169 100644 --- a/spec/src/main/asciidoc/ch10-metadata-annotations.adoc +++ b/spec/src/main/asciidoc/ch10-metadata-annotations.adoc @@ -915,16 +915,14 @@ public @interface StaticNativeQuery { The semantics of this annotation are defined by its Javadoc, and in <>. -==== ReadQueryOptions Annotation +==== StaticQueryOptions Annotation -Configures options that affect the execution of a database read -operation. This annotation may be applied to: +Configures options that affect the execution of a query. This +annotation may be applied to: - a method with a `StaticQuery` or Jakarta Data - `jakarta.data.repository.Query` annotation whose `value` member - specifies a `SELECT` statement, -- a method with a `StaticNativeQuery` annotation whose `value` - member specifies a SQL operation which returns a result set, or + `jakarta.data.repository.Query` annotation, +- a method with a `StaticNativeQuery` annotation, or - a Jakarta Data repository method annotated `jakarta.data.repository.Find`. @@ -932,7 +930,7 @@ operation. This annotation may be applied to: ---- @Target(METHOD) @Retention(RUNTIME) -public @interface ReadQueryOptions { +public @interface StaticQueryOptions { CacheStoreMode cacheStoreMode() default CacheStoreMode.USE; CacheRetrieveMode cacheRetrieveMode() default CacheRetrieveMode.USE; int timeout() default -1; @@ -941,27 +939,3 @@ public @interface ReadQueryOptions { String entityGraph() default ""; } ---- - -==== WriteQueryOptions Annotation - -Configures options that affect the execution of a database write -operation. This annotation may be applied to: - -- a method with a `StaticQuery` or Jakarta Data - `jakarta.data.repository.Query` annotation whose `value` member - specifies an `UPDATE` or `DELETE` statement, -- a method with a `StaticNativeQuery` annotation whose `value` - member specifies a SQL operation which returns a row count, or -- a Jakarta Data repository method annotated - `jakarta.data.repository.Delete` that uses the - parameter-based automatic query pattern. - -[source,java] ----- -@Target(METHOD) -@Retention(RUNTIME) -public @interface WriteQueryOptions { - int timeout() default -1; - QueryHint[] hints() default {}; -} ----- \ No newline at end of file From 8915873bfcd6c70b19764b38321d22fdcd9b3ed6 Mon Sep 17 00:00:00 2001 From: Gavin King Date: Tue, 24 Mar 2026 09:59:10 +0100 Subject: [PATCH 2/2] Apply suggestion from @njr-11 Co-authored-by: Nathan Rauh --- .../java/jakarta/persistence/query/StaticQueryOptions.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/api/src/main/java/jakarta/persistence/query/StaticQueryOptions.java b/api/src/main/java/jakarta/persistence/query/StaticQueryOptions.java index f1dbc5d13..9c07cb73e 100644 --- a/api/src/main/java/jakarta/persistence/query/StaticQueryOptions.java +++ b/api/src/main/java/jakarta/persistence/query/StaticQueryOptions.java @@ -36,6 +36,9 @@ *

  • a method with a {@link StaticQuery} or Jakarta Data * {@code jakarta.data.repository.Query} annotation, *
  • a method with a {@link StaticNativeQuery} annotation, + *
  • a Jakarta Data repository method annotated + * {@code jakarta.data.repository.Delete} that uses the + * parameter-based automatic query pattern, * or *
  • a Jakarta Data repository method annotated * {@code jakarta.data.repository.Find}.