Skip to content

Commit

Permalink
improvements to named query-defining annotations
Browse files Browse the repository at this point in the history
1. add @NamedQuery.resultClass for jakartaee#505
2. clarify the semantics surrounding named query
   result types (this was pretty much unspecified)
3. improve @NamedQuery and @NamedNativeQuery jdoc
  • Loading branch information
gavinking committed Nov 5, 2023
1 parent 231ff19 commit c8cbeae
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 49 deletions.
71 changes: 65 additions & 6 deletions api/src/main/java/jakarta/persistence/NamedNativeQuery.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,54 @@
/**
* Declares a named native SQL query and, optionally, the mapping
* of the result of the native SQL query. Query names are scoped
* to the persistence unit. The {@code NamedNativeQuery} annotation
* can be applied to an entity or mapped superclass.
* to the persistence unit. A named query may be executed by
* calling {@link EntityManager#createNamedQuery(String, Class)}.
*
* <p> In simple cases, a {@link #resultClass} specifies how the
* native SQL query result set should be interpreted, for example:
* {@snippet :
* @NamedNativeQuery(
* name = "findWidgets",
* query = "SELECT o.id, o.quantity, o.item " +
* "FROM Order o, Item i " +
* "WHERE (o.item = i.id) AND (i.name = 'widget')",
* resultClass = com.acme.Order.class
* )}
*
* <p>
* In more complicated cases, a {@linkplain SqlResultSetMapping
* result set mapping} is needed, which may be specified using
* either a separate annotation:
* {@snippet :
* @NamedNativeQuery(
* name = "OrderItems",
* query = "SELECT o.id, o.quantity, o.item, i.id, i.name, i.description " +
* "FROM Order o, Item i " +
* "WHERE (o.quantity > 25) AND (o.item = i.id)",
* resultSetMapping = "OrderItemResults");
*
* @SqlResultSetMapping(name="OrderItemResults", entities={
* @EntityResult(entityClass=com.acme.Order.class),
* @EntityResult(entityClass=com.acme.Item.class)
* })
* }
* or using the elements of this annotation:
* {@snippet :
* @NamedNativeQuery(
* name = "OrderItems",
* query = "SELECT o.id, o.quantity, o.item, i.id, i.name, i.description " +
* "FROM Order o, Item i " +
* "WHERE (o.quantity > 25) AND (o.item = i.id)",
* resultSetMapping = "OrderItemResults");
* entities={
* @EntityResult(entityClass=com.acme.Order.class),
* @EntityResult(entityClass=com.acme.Item.class)
* }
* )
* }
*
* <p> The {@code NamedNativeQuery} annotation can be applied to
* an entity class or mapped superclass.
* @see SqlResultSetMapping
*
* @since 1.0
Expand All @@ -40,13 +85,13 @@
public @interface NamedNativeQuery {

/**
* The name used to refer to the query with the {@link EntityManager}
* methods that create query objects.
* The name used to identify the query in calls to
* {@link EntityManager#createNamedQuery}.
*/
String name();

/**
* The SQL query string.
* The native SQL query string.
*/
String query();

Expand All @@ -57,12 +102,26 @@
QueryHint[] hints() default {};

/**
* The class of the result.
* The class of each query result. If a {@link #resultSetMapping
* result set mapping} is specified, the specified result class
* must agree with the type inferred from the result set mapping.
* If a {@code resultClass} is not explicitly specified, then it
* is inferred from the result set mapping, if any, or defaults
* to {@code Object} or {@code Object[]}. The query result class
* may be overridden by explicitly passing a class object to
* {@link EntityManager#createNamedQuery(String, Class)}.
*/
Class<?> resultClass() default void.class;

/**
* The name of a {@link SqlResultSetMapping}, as defined in metadata.
* The named result set mapping is used to interpret the result set
* of the native SQL query.
*
* <p>Alternatively, the elements {@link #entities}, {@link #classes},
* and {@link #columns} may be used to specify a result set mapping.
* These elements may not be used in conjunction with
* {@code resultSetMapping}.
*/
String resultSetMapping() default "";

Expand Down
35 changes: 23 additions & 12 deletions api/src/main/java/jakarta/persistence/NamedQuery.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,31 +25,32 @@
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
* Declares a static, named query in the Jakarta Persistence query
* language. Query names are scoped to the persistence unit. The
* {@code NamedQuery} annotation can be applied to an entity or
* mapped superclass.
* Declares a named query written in the Jakarta Persistence
* query language. Query names are scoped to the persistence unit.
* A named query may be executed by calling
* {@link EntityManager#createNamedQuery(String, Class)}.
*
* <p> The following is an example of the definition of a named
* query in the Jakarta Persistence query language:
*
* query written in the Jakarta Persistence query language:
* {@snippet :
* @NamedQuery(
* name = "findAllCustomersWithName",
* query = "SELECT c FROM Customer c WHERE c.name LIKE :custName")
* }
*
* <p> The following is an example of the use of a named query:
*
* <p> The named query may be executed like this:
* {@snippet :
* @PersistenceContext
* public EntityManager em;
* ...
* customers = em.createNamedQuery("findAllCustomersWithName")
* customers = em.createNamedQuery("findAllCustomersWithName", Customer.class)
* .setParameter("custName", "Smith")
* .getResultList();
* }
*
* The {@code NamedQuery} annotation can be applied to an entity
* class or mapped superclass.
*
* @since 1.0
*/
@Repeatable(NamedQueries.class)
Expand All @@ -58,8 +59,8 @@
public @interface NamedQuery {

/**
* (Required) The name used to refer to the query with the
* {@link EntityManager} methods that create query objects.
* (Required) The name used to identify the query in calls to
* {@link EntityManager#createNamedQuery}.
*/
String name();

Expand All @@ -69,7 +70,17 @@
*/
String query();

/**
/**
* (Optional) The class of each query result. The result class
* may be overridden by explicitly passing a class object to
* {@link EntityManager#createNamedQuery(String, Class)}. If
* the result class of a named query is not specified, the
* persistence implementation is entitled to default the
* result class to {@code Object} or {@code Object[]}.
*/
Class<?> resultClass() default void.class;

/**
* (Optional) The lock mode type to use in query execution.
* If a {@code lockMode} other than {@link LockModeType#NONE}
* is specified, the query must be executed in a transaction
Expand Down
76 changes: 45 additions & 31 deletions spec/src/main/asciidoc/ch10-metadata-annotations.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -239,28 +239,35 @@ public @interface NamedSubgraph {

==== NamedQuery Annotation [[a13711]]

The `NamedQuery` annotation is used to
specify a named query in the Jakarta Persistence query language.
The `NamedQuery` annotation declared a named query written in the Jakarta
Persistence query language.

The `name` element is used to refer to the
query when using the `EntityManager` methods that create query objects.
The `name` element assigns a name to the query, which is used to identify
the query in calls to `EntityManager.createNamedQuery()`.

The `query` element must specify a query
string in the Jakarta Persistence query language.
The `query` element must specify a query string itself, written in the
Jakarta Persistence query language.

The `lockMode` element specifies a lock mode
for the results returned by the query. If a lock mode other than `NONE`
is specified, the query must be executed within a transaction and the
persistence context joined to the transaction.
The `resultClass` element specifies the Java class of each query result.
The query result class may be overridden by explicitly passing a `Class`
object to `EntityManager.createNamedQuery(String, Class)`. If the
`resultClass` element of a `NamedQuery` annotation is not specified, the
persistence implementation is entitled to default the result class to
`Object` or `Object[]`.

The `hints` elements may be used to specify
query properties and hints. Properties defined by this specification
must be observed by the provider; hints defined by this specification
should be observed by the provider when possible. Vendor-specific hints
that are not recognized by a provider must be ignored.
The `lockMode` element specifies a lock mode for the entity instances in
results returned by the query. If a lock mode other than `NONE` is
specified, the query may only be executed within a persistence context
with an associated active transaction.

The `hints` elements may be used to specify query properties and hints.
Properties defined by this specification must be observed by the provider;
hints defined by this specification should be observed by the provider
when possible. Vendor-specific hints that are not recognized by a provider
must be ignored.

The `NamedQuery` and `NamedQueries`
annotations can be applied to an entity or mapped superclass.
The `NamedQuery` and `NamedQueries` annotations can be applied to an entity
or mapped superclass.

[source,java]
----
Expand All @@ -270,6 +277,7 @@ annotations can be applied to an entity or mapped superclass.
public @interface NamedQuery {
String name();
String query();
Class<?> resultClass() default void.class;
LockModeType lockMode() default NONE;
QueryHint[] hints() default {};
}
Expand All @@ -292,20 +300,26 @@ public @interface NamedQueries {

The `NamedNativeQuery` annotation defines a named native SQL query.

The `name` element specifies the name used to identify the query when
calling methods of `EntityManager` which create query objects.

The `query` element specifies the query itself, written in the native SQL
dialect of the database.

The `resultClass` element specifies the class of the query result.

The `resultSetMapping` element specifies the name of a
`SqlResultSetMapping` specification defined elsewhere in metadata.
The named `SqlResultSetMapping` is used to interpret the result set of
the native SQL query. Alternatively, the elements `entities`, `classes`,
and `columns` may be used to specify a result set mapping. These elements
may not be used in conjunction with `resultSetMapping`.
The `name` element assigns a name to the query, which is used to identify
the query in calls to `EntityManager.createNamedQuery()`.

The `query` element must specify the query string itself, written in the
native SQL dialect of the database.

The `resultClass` element specifies the class of each query result. If a
result set mapping is specified, the specified result class must agree
with the type inferred from the result set mapping. If a `resultClass` is
not explicitly specified, then it is inferred from the result set mapping,
if any, or defaults to `Object` or `Object[]`. The query result class may
be overridden by explicitly passing a `Class` object to
`EntityManager.createNamedQuery(String, Class)`.

The `resultSetMapping` element specifies the name of a `SqlResultSetMapping`
specification defined elsewhere in metadata. The named `SqlResultSetMapping`
is used to interpret the result set of the native SQL query. Alternatively,
the elements `entities`, `classes`, and `columns` may be used to specify a
result set mapping. These elements may not be used in conjunction with
`resultSetMapping`.

The `hints` element may be used to specify query properties and hints.
Hints defined by this specification should be observed by the provider
Expand Down

0 comments on commit c8cbeae

Please sign in to comment.