From c1ad059074ec7a906ae6d5f3c43f08ff6f84d1f9 Mon Sep 17 00:00:00 2001 From: Gavin King Date: Fri, 15 Mar 2024 13:20:09 +0100 Subject: [PATCH] move some additional sections from 4.8 to 4.9, and two later sections *into* 4.8 (#585) * move some additional sections from 4.8 to 4.9, and two later sections *into* 4.8 * move section on static metamodel from the criteria API chapter to the metamodel chapter * fix the example static metamodel class it was (a) wrong, and (b) out of date --- .../main/asciidoc/ch04-query-language.adoc | 762 +++++++++--------- .../src/main/asciidoc/ch05-metamodel-api.adoc | 252 +++++- spec/src/main/asciidoc/ch06-criteria-api.adoc | 250 +----- 3 files changed, 639 insertions(+), 625 deletions(-) diff --git a/spec/src/main/asciidoc/ch04-query-language.adoc b/spec/src/main/asciidoc/ch04-query-language.adoc index e3c0695b..78b651e0 100644 --- a/spec/src/main/asciidoc/ch04-query-language.adoc +++ b/spec/src/main/asciidoc/ch04-query-language.adoc @@ -1169,144 +1169,6 @@ footnote:[The implementation is not expected to perform such query operations involving such fields in memory rather than in the database.]. -==== Literals - -A string literal is enclosed in single -quotes—for example: 'literal'. A string literal that includes a single -quote is represented by two single quotes—for example: 'literal''s'. -String literals in queries, like Java `String` literals, use unicode -character encoding. The use of Java escape notation is not supported in -query string literals. - -A numeric literal may be either: - -- a decimal Java integer (int or long) literal -- a Java floating point (float or double) literal, or -- a literal `BigInteger` or `BigDecimal`. - -A suffix `L`, `D`, or `F` may be used to indicate the specific numeric -type, in accordance with the Java Language Specification. The suffix is -not case-sensitive. The literal numeric value preceding the suffix must -conform to the rules for Java numeric literals established by the Java -Language Specification. - -A suffix `BI` or `BD` may be used to indicate a literal `BigInteger` or -`BigDecimal`, respectively. The literal numeric value preceding the suffix -must be an exact or approximate SQL numeric literal. For a `BigInteger` -literal, the numeric value must be an exact integer literal. - -Just as in Java, when a numeric literal has no suffix: - -- an integer literal is interpreted as a Java int, and -- a floating point literal is interpreted as a Java double. - -Support for hexadecimal and octal numeric literals is not required by -this specification. - -Enum literals support the use of Java enum -literal syntax. The fully qualified enum class name must be specified. - -The JDBC escape syntax may be used for the -specification of date, time, and timestamp literals. For example: - -[source,sql] ----- -SELECT o -FROM Customer c JOIN c.orders o -WHERE c.name = 'Smith' - AND o.submissionDate < {d '2008-12-31'} ----- - -The portability of this syntax for date, -time, and timestamp literals is dependent upon the JDBC driver in use. -Persistence providers are not required to translate from this syntax -into the native syntax of the database or driver. - -The boolean literals are `TRUE` and `FALSE`. - -Entity type literals are specified by entity names—for example: `Customer`. - -Although reserved literals appear in upper case, they are case-insensitive. - -==== Identification Variables - -All identification variables used in the -WHERE or HAVING clause of a SELECT or DELETE statement must be declared -in the FROM clause, as described in <>. The identification variables used in the -WHERE clause of an UPDATE statement must be declared in the UPDATE -clause. - -Identification variables are existentially -quantified in the WHERE and HAVING clause. -This means that an identification variable represents a member of a -collection or an instance of an entity's abstract schema type. An -identification variable never designates a collection in its entirety. - -==== Path Expressions - -It is illegal to use a -`collection_valued_path_expression` within a WHERE or HAVING clause as -part of a conditional expression except in an -`empty_collection_comparison_expression`, in a -`collection_member_expression`, or as an argument to the SIZE operator. - -==== Input Parameters [[a5065]] - -An input parameter allows a value in the Java program to be safely -interpolated into the text of the parameterized query. - -In a given query, either positional or named parameters may be used. -Positional and named parameters must not be mixed in a single query. - -The persistence provider is required to support input parameters which -occur in the `WHERE` clause or `HAVING` clause of a query, or as the -new value for an update item in the `SET` clause of an update statement. - -[NOTE] -==== -Note that if an input parameter value is null, comparison operations or -arithmetic operations involving the input parameter will result in an -unknown value. See <>. -==== - -An input parameter might be _single-valued_ or _collection-valued_. -An input parameter which occurs directly to the right of the `IN` keyword -in an `IN` predicate, as defined in <>, is collection-valued. Every -other input parameter is single-valued - -The API for the binding concrete arguments to query parameters is described -in <>. - -===== Positional Parameters - -The following rules apply to positional input parameters. - -* A positional parameter is designated by an integer, and prefixed with a - _?_ symbol (question mark) in the text of the query string. - For example: _?1_. -* Input parameters are numbered starting from 1. -* A given positional parameter may occur more than once in the query string. -* The ordering of the use of parameters within the text of the query string - need not match the numbering of the positional parameters. - -===== Named Parameters - -A named parameter is denoted by an identifier, and prefixed by the _:_ symbol -(colon) in the text of the query string. The identifier name must follow the -usual rules for identifiers specified in <>. Named parameters are -case-sensitive. - -Example: - -[source,sql] ----- -SELECT c -FROM Customer c -WHERE c.status = :stat ----- - -A given named parameter may occur more than once in the query string. - ==== Conditional Expression Composition Conditional expressions are composed of other @@ -1753,55 +1615,396 @@ derived_collection_member_declaration ::= IN superquery_identification_variable.{single_valued_object_field.}*collection_valued_field ---- -Examples: +Examples: + +[source,sql] +---- +SELECT DISTINCT emp +FROM Employee emp +WHERE EXISTS ( + SELECT spouseEmp + FROM Employee spouseEmp + WHERE spouseEmp = emp.spouse) +---- + +Note that some contexts in which a subquery +can be used require that the subquery be a scalar subquery (i.e., +produce a single result). This is illustrated in the following examples +using numeric comparisons. + +[source,sql] +---- +SELECT c +FROM Customer c +WHERE (SELECT AVG(o.price) FROM c.orders o) > 100 + +SELECT goodCustomer +FROM Customer goodCustomer +WHERE goodCustomer.balanceOwed < ( + SELECT AVG(c.balanceOwed)/2.0 FROM Customer c) +---- + +==== Null Values [[a5676]] + +When the target of a reference does not exist +in the database, its value is regarded as `NULL`. SQL `NULL` semantics +<> defines the evaluation of +conditional expressions containing `NULL` values. + +The following is a brief description of these semantics: + +* Comparison or arithmetic operations with a +NULL value always yield an unknown value. +* Two NULL values are not considered to be +equal, the comparison yields an unknown value. +* Comparison or arithmetic operations with an +unknown value always yield an unknown value. +* The IS NULL and IS NOT NULL operators convert +a `NULL` state field or single-valued object field value into the +respective TRUE or FALSE value. +* Boolean operators use three valued logic, +defined by <>, <>, and <>. + +[[a5686]] +[options="header"] +.Definition of the AND Operator +|=== +|AND|T|F|U +|T|T|F|U +|F|F|F|F +|U|U|F|U +|=== + +[[a5705]] +[options="header"] +.Definition of the OR Operator +|=== +|OR|T|F|U +|T|T|T|T +|F|T|F|U +|U|T|U|U +|=== + +[[a5724]] +[options="header"] +.Definition of the NOT Operator +|=== +|NOT| +|T|F +|F|T +|U|U +|=== + +[NOTE] +==== +The Jakarta Persistence query language +defines the empty string, '', as a string +with 0 length, which is not equal to a NULL value. However, NULL values +and empty strings may not always be distinguished when queries are +mapped to some databases. Application developers should therefore not +rely on the semantics of query comparisons involving the empty string +and NULL value. +==== + +==== Equality and Comparison Semantics [[a5735]] + +Only the values of _like_ types are permitted +to be compared. A type is _like_ another type if they correspond to the +same Java language type, or if one is a primitive Java language type and +the other is the wrapped Java class type equivalent (e.g., `int` and +`Integer` are like types in this sense). There is one exception to this +rule: it is valid to compare numeric values for which the rules of +numeric promotion apply. Conditional expressions attempting to compare +non-like type values are disallowed except for this numeric case. + +[NOTE] +==== +Note that the arithmetic operators, the string concatenation operator, +and comparison operators are permitted to be applied to state fields and +input parameters of the wrapped Java class equivalents to the primitive +numeric Java types. +==== + +Two entities of the same abstract schema type +are equal if and only if they have the same primary key value. + +Only equality/inequality comparisons over +enums are required to be supported. + +Comparisons over instances of embeddable +class or map entry types are not supported. + +The following examples illustrate the syntax +and semantics of the Jakarta Persistence query language. These examples are +based on the example presented in <>. + +Find all orders: + +[source,sql] +---- +SELECT o +FROM Order o +---- + +Find all orders that need to be shipped to California: + +[source,sql] +---- +SELECT o +FROM Order o +WHERE o.shippingAddress.state = 'CA' +---- + +Find all states for which there are orders: + +[source,sql] +---- +SELECT DISTINCT o.shippingAddress.state +FROM Order o +---- + +Find all orders that have line items: + +[source,sql] +---- +SELECT DISTINCT o +FROM Order o JOIN o.lineItems l +---- + +Note that the result of this query does not +include orders with no associated line items. This query can also be +written as: + +[source,sql] +---- +SELECT o +FROM Order o +WHERE o.lineItems IS NOT EMPTY +---- + +Find all orders that have no line items: + +[source,sql] +---- +SELECT o +FROM Order o +WHERE o.lineItems IS EMPTY +---- + +Find all pending orders: + +[source,sql] +---- +SELECT DISTINCT o +FROM Order o JOIN o.lineItems l +WHERE l.shipped = FALSE +---- + +Find all orders in which the shipping address +differs from the billing address. This example assumes that the +application developer uses two distinct `entity` types to designate +shipping and billing addresses. + +[source,sql] +---- +SELECT o +FROM Order o +WHERE + NOT (o.shippingAddress.state = o.billingAddress.state AND + o.shippingAddress.city = o.billingAddress.city AND + o.shippingAddress.street = o.billingAddress.street) +---- + +If the application developer uses a single +`entity` type in two different relationships for both the shipping +address and the billing address, the above expression can be simplified +based on the equality rules defined in <>. The +query can then be written as: + +[source,sql] +---- +SELECT o +FROM Order o +WHERE o.shippingAddress <> o.billingAddress +---- + +The query checks whether the same entity +abstract schema type instance (identified by its primary key) is related +to an order through two distinct relationships. + +===== Queries Using Input Parameters + +The following query finds the orders for a +product whose name is designated by an input parameter: + +[source,sql] +---- +SELECT DISTINCT o +FROM Order o JOIN o.lineItems l +WHERE l.product.name = ?1 +---- + +For this query, the input parameter must be +of the type of the state field name, i.e., a string. + +=== Scalar Expressions [[a5243]] + +Numeric, string, datetime, case, and entity +type expressions result in scalar values. + +Scalar expressions may be used in the SELECT +clause of a query as well as in the WHEREfootnote:[Note that expressions +involving aggregate operators must not be used in the WHERE clause.] and +HAVING clauses. + +---- +scalar_expression::= + arithmetic_expression | + string_expression | + enum_expression | + datetime_expression | + boolean_expression | + case_expression | + entity_type_expression +---- + +==== Literals + +A string literal is enclosed in single +quotes—for example: 'literal'. A string literal that includes a single +quote is represented by two single quotes—for example: 'literal''s'. +String literals in queries, like Java `String` literals, use unicode +character encoding. The use of Java escape notation is not supported in +query string literals. + +A numeric literal may be either: + +- a decimal Java integer (int or long) literal +- a Java floating point (float or double) literal, or +- a literal `BigInteger` or `BigDecimal`. + +A suffix `L`, `D`, or `F` may be used to indicate the specific numeric +type, in accordance with the Java Language Specification. The suffix is +not case-sensitive. The literal numeric value preceding the suffix must +conform to the rules for Java numeric literals established by the Java +Language Specification. + +A suffix `BI` or `BD` may be used to indicate a literal `BigInteger` or +`BigDecimal`, respectively. The literal numeric value preceding the suffix +must be an exact or approximate SQL numeric literal. For a `BigInteger` +literal, the numeric value must be an exact integer literal. + +Just as in Java, when a numeric literal has no suffix: + +- an integer literal is interpreted as a Java int, and +- a floating point literal is interpreted as a Java double. + +Support for hexadecimal and octal numeric literals is not required by +this specification. + +Enum literals support the use of Java enum +literal syntax. The fully qualified enum class name must be specified. + +The JDBC escape syntax may be used for the +specification of date, time, and timestamp literals. For example: + +[source,sql] +---- +SELECT o +FROM Customer c JOIN c.orders o +WHERE c.name = 'Smith' + AND o.submissionDate < {d '2008-12-31'} +---- + +The portability of this syntax for date, +time, and timestamp literals is dependent upon the JDBC driver in use. +Persistence providers are not required to translate from this syntax +into the native syntax of the database or driver. + +The boolean literals are `TRUE` and `FALSE`. + +Entity type literals are specified by entity names—for example: `Customer`. + +Although reserved literals appear in upper case, they are case-insensitive. + +==== Identification Variables + +All identification variables used in the +WHERE or HAVING clause of a SELECT or DELETE statement must be declared +in the FROM clause, as described in <>. The identification variables used in the +WHERE clause of an UPDATE statement must be declared in the UPDATE +clause. + +Identification variables are existentially +quantified in the WHERE and HAVING clause. +This means that an identification variable represents a member of a +collection or an instance of an entity's abstract schema type. An +identification variable never designates a collection in its entirety. + +==== Path Expressions + +It is illegal to use a +`collection_valued_path_expression` within a WHERE or HAVING clause as +part of a conditional expression except in an +`empty_collection_comparison_expression`, in a +`collection_member_expression`, or as an argument to the SIZE operator. + +==== Input Parameters [[a5065]] + +An input parameter allows a value in the Java program to be safely +interpolated into the text of the parameterized query. + +In a given query, either positional or named parameters may be used. +Positional and named parameters must not be mixed in a single query. + +The persistence provider is required to support input parameters which +occur in the `WHERE` clause or `HAVING` clause of a query, or as the +new value for an update item in the `SET` clause of an update statement. + +[NOTE] +==== +Note that if an input parameter value is null, comparison operations or +arithmetic operations involving the input parameter will result in an +unknown value. See <>. +==== + +An input parameter might be _single-valued_ or _collection-valued_. +An input parameter which occurs directly to the right of the `IN` keyword +in an `IN` predicate, as defined in <>, is collection-valued. Every +other input parameter is single-valued + +The API for the binding concrete arguments to query parameters is described +in <>. + +===== Positional Parameters + +The following rules apply to positional input parameters. -[source,sql] ----- -SELECT DISTINCT emp -FROM Employee emp -WHERE EXISTS ( - SELECT spouseEmp - FROM Employee spouseEmp - WHERE spouseEmp = emp.spouse) ----- +* A positional parameter is designated by an integer, and prefixed with a +_?_ symbol (question mark) in the text of the query string. +For example: _?1_. +* Input parameters are numbered starting from 1. +* A given positional parameter may occur more than once in the query string. +* The ordering of the use of parameters within the text of the query string +need not match the numbering of the positional parameters. -Note that some contexts in which a subquery -can be used require that the subquery be a scalar subquery (i.e., -produce a single result). This is illustrated in the following examples -using numeric comparisons. +===== Named Parameters + +A named parameter is denoted by an identifier, and prefixed by the _:_ symbol +(colon) in the text of the query string. The identifier name must follow the +usual rules for identifiers specified in <>. Named parameters are +case-sensitive. + +Example: [source,sql] ---- SELECT c FROM Customer c -WHERE (SELECT AVG(o.price) FROM c.orders o) > 100 - -SELECT goodCustomer -FROM Customer goodCustomer -WHERE goodCustomer.balanceOwed < ( - SELECT AVG(c.balanceOwed)/2.0 FROM Customer c) +WHERE c.status = :stat ---- -=== Scalar Expressions [[a5243]] - -Numeric, string, datetime, case, and entity -type expressions result in scalar values. - -Scalar expressions may be used in the SELECT -clause of a query as well as in the WHEREfootnote:[Note that expressions -involving aggregate operators must not be used in the WHERE clause.] and -HAVING clauses. - ----- -scalar_expression::= - arithmetic_expression | - string_expression | - enum_expression | - datetime_expression | - boolean_expression | - case_expression | - entity_type_expression ----- +A given named parameter may occur more than once in the query string. ==== Arithmetic Expressions @@ -2867,209 +3070,6 @@ WHERE e.address.building = 14 AND e.project = 'Jakarta EE' ---- -=== Null Values [[a5676]] - -When the target of a reference does not exist -in the database, its value is regarded as `NULL`. SQL `NULL` semantics -<> defines the evaluation of -conditional expressions containing `NULL` values. - -The following is a brief description of these semantics: - -* Comparison or arithmetic operations with a -NULL value always yield an unknown value. -* Two NULL values are not considered to be -equal, the comparison yields an unknown value. -* Comparison or arithmetic operations with an -unknown value always yield an unknown value. -* The IS NULL and IS NOT NULL operators convert -a `NULL` state field or single-valued object field value into the -respective TRUE or FALSE value. -* Boolean operators use three valued logic, -defined by <>, <>, and <>. - -[[a5686]] -[options="header"] -.Definition of the AND Operator -|=== -|AND|T|F|U -|T|T|F|U -|F|F|F|F -|U|U|F|U -|=== - -[[a5705]] -[options="header"] -.Definition of the OR Operator -|=== -|OR|T|F|U -|T|T|T|T -|F|T|F|U -|U|T|U|U -|=== - -[[a5724]] -[options="header"] -.Definition of the NOT Operator -|=== -|NOT| -|T|F -|F|T -|U|U -|=== - -[NOTE] -==== -The Jakarta Persistence query language -defines the empty string, '', as a string -with 0 length, which is not equal to a NULL value. However, NULL values -and empty strings may not always be distinguished when queries are -mapped to some databases. Application developers should therefore not -rely on the semantics of query comparisons involving the empty string -and NULL value. -==== - -=== Equality and Comparison Semantics [[a5735]] - -Only the values of _like_ types are permitted -to be compared. A type is _like_ another type if they correspond to the -same Java language type, or if one is a primitive Java language type and -the other is the wrapped Java class type equivalent (e.g., `int` and -`Integer` are like types in this sense). There is one exception to this -rule: it is valid to compare numeric values for which the rules of -numeric promotion apply. Conditional expressions attempting to compare -non-like type values are disallowed except for this numeric case. - -[NOTE] -==== -Note that the arithmetic operators, the string concatenation operator, -and comparison operators are permitted to be applied to state fields and -input parameters of the wrapped Java class equivalents to the primitive -numeric Java types. -==== - -Two entities of the same abstract schema type -are equal if and only if they have the same primary key value. - -Only equality/inequality comparisons over -enums are required to be supported. - -Comparisons over instances of embeddable -class or map entry types are not supported. - -The following examples illustrate the syntax -and semantics of the Jakarta Persistence query language. These examples are -based on the example presented in <>. - -Find all orders: - -[source,sql] ----- -SELECT o -FROM Order o ----- - -Find all orders that need to be shipped to California: - -[source,sql] ----- -SELECT o -FROM Order o -WHERE o.shippingAddress.state = 'CA' ----- - -Find all states for which there are orders: - -[source,sql] ----- -SELECT DISTINCT o.shippingAddress.state -FROM Order o ----- - -Find all orders that have line items: - -[source,sql] ----- -SELECT DISTINCT o -FROM Order o JOIN o.lineItems l ----- - -Note that the result of this query does not -include orders with no associated line items. This query can also be -written as: - -[source,sql] ----- -SELECT o -FROM Order o -WHERE o.lineItems IS NOT EMPTY ----- - -Find all orders that have no line items: - -[source,sql] ----- -SELECT o -FROM Order o -WHERE o.lineItems IS EMPTY ----- - -Find all pending orders: - -[source,sql] ----- -SELECT DISTINCT o -FROM Order o JOIN o.lineItems l -WHERE l.shipped = FALSE ----- - -Find all orders in which the shipping address -differs from the billing address. This example assumes that the -application developer uses two distinct `entity` types to designate -shipping and billing addresses. - -[source,sql] ----- -SELECT o -FROM Order o -WHERE - NOT (o.shippingAddress.state = o.billingAddress.state AND - o.shippingAddress.city = o.billingAddress.city AND - o.shippingAddress.street = o.billingAddress.street) ----- - -If the application developer uses a single -`entity` type in two different relationships for both the shipping -address and the billing address, the above expression can be simplified -based on the equality rules defined in <>. The -query can then be written as: - -[source,sql] ----- -SELECT o -FROM Order o -WHERE o.shippingAddress <> o.billingAddress ----- - -The query checks whether the same entity -abstract schema type instance (identified by its primary key) is related -to an order through two distinct relationships. - -==== Queries Using Input Parameters - -The following query finds the orders for a -product whose name is designated by an input parameter: - -[source,sql] ----- -SELECT DISTINCT o -FROM Order o JOIN o.lineItems l -WHERE l.product.name = ?1 ----- - -For this query, the input parameter must be -of the type of the state field name, i.e., a string. - === BNF BNF notation summary: diff --git a/spec/src/main/asciidoc/ch05-metamodel-api.adoc b/spec/src/main/asciidoc/ch05-metamodel-api.adoc index 3bd80bd7..be94a976 100644 --- a/spec/src/main/asciidoc/ch05-metamodel-api.adoc +++ b/spec/src/main/asciidoc/ch05-metamodel-api.adoc @@ -4,9 +4,255 @@ == Metamodel API [[a6072]] -This specification provides a set of -interfaces for dynamically accessing the metamodel corresponding to the -managed classes of a persistence unit. +This specification provides a set of interfaces for dynamically accessing +a metamodel representing the managed classes of a persistence unit. +Instances of metamodel types may be obtained either: + +- via programmatic lookup using an instance of the interface + `jakarta.persistence.metamodel.Metamodel` obtained from the + `EntityManagerFactory` or `EntityManager` by calling + `getMetamodel()`, or +- in a typesafe way, using _static metamodel classes_. + +A static metamodel class is a class with static members providing direct +typesafe access to metamodel objects representing the persistent members +of a given managed class. + +=== Static Metamodel Classes [[a6933]] + +A set of static metamodel classes corresponding to the managed classes of +a persistence unit can be generated using an annotation processor or may +be created by the application developer. + +In the typical case, an annotation processor is used to generate static +metamodel classes corresponding to the entities, mapped superclasses, +and embeddable classes in the persistence unit. A static metamodel class +models the persistent state and relationships of the corresponding managed +class. For portability, an annotation processor should generate a _canonical +metamodel_ as specified in the next section. + +==== Canonical Metamodel + +This specification defines as follows a +canonical metamodel and the structure of canonical metamodel classes. + +For every managed class in the persistence +unit, a corresponding metamodel class is produced as follows: + +* For each managed class `X` in package `p`, a metamodel class +`X_` in package `p` is created.footnote:[We expect that the +option of different packages will be provided in a future release of +this specification.] + +* The name of the metamodel class is derived from the name of the +managed class by appending "`_`" to the name of the managed class. + +* The metamodel class `X_` must be annotated with the +`jakarta.persistence.StaticMetamodel` annotationfootnote:[If the class +was generated, the `javax.annotation.processing.Generated` or `jakarta.annotation.Generated` +annotation should be used to annotate the class. The use of any other annotations on static +metamodel classes is undefined.]. + +* If the managed class `X` extends another class `S`, where `S` is the +most derived managed class (i.e., entity or mapped superclass) extended +by `X`, then the metamodel class `X_` must extend the metamodel +class `S_` created for `S`. + +* The metamodel class must contain a field declaration as follows: ++ +[source,java] +---- +public static volatile jakarta.persistence.metamodel.T class_; +---- ++ +where `T` is `EntityType`, `EmbeddableType`, or `MappedSuperclassType` +depending on whether `X` is an entity, embeddable, or mapped superclass. +* For every persistent attribute `y` declared by class `X`, the +metamodel class must contain a field declaration as follows: ++ +[source,java] +---- +public static final String Y = "y"; +---- ++ +where the field name `Y` is obtained by transforming each lowercase +character in the attribute name `y` to uppercase, and inserting an +underscore if the character following the transformed character +is uppercase. + +* For every persistent non-collection-valued +attribute `y` declared by class `X`, where the type of `y` is `Y`, the +metamodel class must contain a declaration as follows: ++ +[source,java] +---- +public static volatile SingularAttribute y; +---- ++ + +* For every persistent collection-valued +attribute `z` declared by class `X`, where the element type of `z` is +`Z`, the metamodel class must contain a declaration as follows: +** if the collection type of `z` is `java.util.Collection`, then ++ +[source,java] +---- +public static volatile CollectionAttribute z; +---- ++ +** if the collection type of `z` is `java.util.Set`, then ++ +[source,java] +---- +public static volatile SetAttribute z; +---- ++ +** if the collection type of `z` is `java.util.List`, then ++ +[source,java] +---- +public static volatile ListAttribute z; +---- ++ +** if the collection type of `z` is `java.util.Map`, then ++ +[source,java] +---- +public static volatile MapAttribute z; +---- ++ +where `K` is the type of the key of the map in class `X` + +* For every named query, named entity graph, or SQL result set +mapping with name `"n"` declared by annotations of the class `X`, +the metamodel class must contain a declaration as follows: ++ +[source,java] +---- +public static final String T_N = "n"; +---- ++ +where The prefix `T` is the string `QUERY`, `GRAPH`, or `MAPPING`, +as appropriate, depending on the annotation type, and the suffix +`N` is obtained by transforming each lowercase character in the +name `n` to uppercase, inserting an underscore if the character +following the transformed character is uppercase, and then +replacing each character which is not a legal Java identifier +character with an underscore. + +* For every named query with name `"n"` and query result class +`R` declared by annotations of the class `X`, the metamodel class +must contain a declaration as follows: ++ +[source,java] +---- +public static volatile TypedQueryReference _n_; +---- ++ + +* For every named entity graph with name `"n"` declared by +annotations of the class `X`, the metamodel class must contain +a declaration as follows: ++ +[source,java] +---- +public static volatile EntityGraph _n; +---- ++ + +Import statements must be included for the +needed `jakarta.persistence.metamodel` types as appropriate (e.g., +`jakarta.persistence.metamodel.SingularAttribute`, +`jakarta.persistence.metamodel.CollectionAttribute`, +`jakarta.persistence.metamodel.SetAttribute`, +`jakarta.persistence.metamodel.ListAttribute`, +`jakarta.persistence.metamodel.MapAttribute`) and all classes `X`, `Y`, +`Z`, `R`, and `K`. + +[NOTE] +==== +Implementations of this specification are +not required to support the use of non-canonical metamodel classes. +Applications that use non-canonical metamodel classes will not be +portable. +==== + +===== Example Canonical Metamodel [[a6961]] + +Assume the `Order` entity below. + +[source,java] +---- +package com.example; + +import java.util.Set; +import java.math.BigDecimal; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; + + +@Entity +public class Order { + @Id + Integer orderId; + + @ManyToOne + Customer customer; + + @OneToMany + Set lineItems; + + Address shippingAddress; + + BigDecimal totalCost; + + // ... +} +---- + +The corresponding canonical metamodel class, `Order_`, is as follows: + +[source,java] +---- +package com.example; + +import java.math.BigDecimal; +import jakarta.persistence.metamodel.SingularAttribute; +import jakarta.persistence.metamodel.SetAttribute; +import jakarta.persistence.metamodel.StaticMetamodel; + +@StaticMetamodel(Order.class) +public class Order_ { + public static volatile EntityType class_; + + public static volatile SingularAttribute orderId; + public static volatile SingularAttribute customer; + public static volatile SetAttribute lineItems; + public static volatile SingularAttribute shippingAddress; + public static volatile SingularAttribute totalCost; + + public static final String LINE_ITEMS = "lineItems"; + public static final String ORDER_ID = "orderId"; + public static final String SHIPPING_ADDRESS = "shippingAddress"; + public static final String TOTAL_COST = "totalCost"; + public static final String CUSTOMER = "customer"; +} +---- + +==== Bootstrapping the Static Metamodel + +When the entity manager factory for a persistence unit is created, it is +the responsibility of the persistence provider to initialize the state of +the static metamodel classes representing managed classes belonging to the +persistence unit. Any generated metamodel classes must be accessible on the +classpath. + +Persistence providers must support the use of canonical metamodel classes. +Persistence providers may, but are not required to, support the use of +non-canonical metamodel classes. + === Metamodel API Interfaces diff --git a/spec/src/main/asciidoc/ch06-criteria-api.adoc b/spec/src/main/asciidoc/ch06-criteria-api.adoc index c3954a89..dbb71937 100644 --- a/spec/src/main/asciidoc/ch06-criteria-api.adoc +++ b/spec/src/main/asciidoc/ch06-criteria-api.adoc @@ -32,247 +32,15 @@ entities and embeddable types that constitute the query domain, play a role analogous to that of the identification variables of the Jakarta Persistence query language. -These concepts are further described in the -sections that follow. The metamodel on which criteria queries are based -is presented in <>. -The static metamodel classes that can be used in constructing -strongly-typed criteria queries are described in <>. The -`jakarta.persistence.criteria` interfaces are presented in <>. Sections -<> through <> describe the -construction and modification of criteria query objects. Additional -requirements on the persistence provider are described in <>. - -=== Metamodel [[a6933]] - -Jakarta Persistence criteria queries are based -on a metamodel of the managed classes of the persistence unit. Static -metamodel classes corresponding to the managed classes of the -persistence unit can be generated by means of an annotation processor or -can be created by the application developer, or the metamodel can be -accessed dynamically by use of the -`jakarta.persistence.metamodel.Metamodel` interface. The `getMetamodel` -method of the `EntityManagerFactory` or `EntityManager` interface can be -used to obtain a `Metamodel` instance. - -==== Static Metamodel Classes - -In the typical case, an annotation processor -is expected to be used to produce static metamodel classes corresponding -to the entities, mapped superclasses, and embeddable classes in the -persistence unit. A static metamodel class models the persistent state -and relationships of the corresponding managed class. For portability, -an annotation processor should generate a canonical metamodel as defined -below. - -===== Canonical Metamodel - -This specification defines as follows a -canonical metamodel and the structure of canonical metamodel classes. - -For every managed class in the persistence -unit, a corresponding metamodel class is produced as follows: - -* For each managed class `X` in package `p`, a metamodel class -`X_` in package `p` is created.footnote:[We expect that the -option of different packages will be provided in a future release of -this specification.] - -* The name of the metamodel class is derived from the name of the -managed class by appending "`_`" to the name of the managed class. - -* The metamodel class `X_` must be annotated with the -`jakarta.persistence.StaticMetamodel` annotationfootnote:[If the class -was generated, the `javax.annotation.processing.Generated` or `jakarta.annotation.Generated` -annotation should be used to annotate the class. The use of any other annotations on static -metamodel classes is undefined.]. - -* If the managed class `X` extends another class `S`, where `S` is the -most derived managed class (i.e., entity or mapped superclass) extended -by `X`, then the metamodel class `X_` must extend the metamodel -class `S_` created for `S`. - -* The metamodel class must contain a field declaration as follows: -+ -[source,java] ----- -public static volatile jakarta.persistence.metamodel.T class_; ----- -+ -where `T` is `EntityType`, `EmbeddableType`, or `MappedSuperclassType` -depending on whether `X` is an entity, embeddable, or mapped superclass. -* For every persistent attribute `y` declared by class `X`, the -metamodel class must contain a field declaration as follows: -+ -[source,java] ----- -public static final String Y = "y"; ----- -+ -where the field name `Y` is obtained by transforming each lowercase -character in the attribute name `y` to uppercase, and inserting an -underscore if the character following the transformed character -is uppercase. - -* For every persistent non-collection-valued -attribute `y` declared by class `X`, where the type of `y` is `Y`, the -metamodel class must contain a declaration as follows: -+ -[source,java] ----- -public static volatile SingularAttribute y; ----- -+ - -* For every persistent collection-valued -attribute `z` declared by class `X`, where the element type of `z` is -`Z`, the metamodel class must contain a declaration as follows: -** if the collection type of `z` is `java.util.Collection`, then -+ -[source,java] ----- -public static volatile CollectionAttribute z; ----- -+ -** if the collection type of `z` is `java.util.Set`, then -+ -[source,java] ----- -public static volatile SetAttribute z; ----- -+ -** if the collection type of `z` is `java.util.List`, then -+ -[source,java] ----- -public static volatile ListAttribute z; ----- -+ -** if the collection type of `z` is `java.util.Map`, then -+ -[source,java] ----- -public static volatile MapAttribute z; ----- -+ -where `K` is the type of the key of the map in class `X` - -* For every named query, named entity graph, or SQL result set -mapping with name `"n"` declared by annotations of the class `X`, -the metamodel class must contain a declaration as follows: -+ -[source,java] ----- -public static final String T_N = "n"; ----- -+ -where The prefix `T` is the string `QUERY`, `GRAPH`, or `MAPPING`, -as appropriate, depending on the annotation type, and the suffix -`N` is obtained by transforming each lowercase character in the -name `n` to uppercase, inserting an underscore if the character -following the transformed character is uppercase, and then -replacing each character which is not a legal Java identifier -character with an underscore. - -* For every named query with name `"n"` and query result class -`R` declared by annotations of the class `X`, the metamodel class -must contain a declaration as follows: -+ -[source,java] ----- -public static volatile TypedQueryReference _n_; ----- -+ - -* For every named entity graph with name `"n"` declared by -annotations of the class `X`, the metamodel class must contain -a declaration as follows: -+ -[source,java] ----- -public static volatile EntityGraph _n; ----- -+ - -Import statements must be included for the -needed `jakarta.persistence.metamodel` types as appropriate (e.g., -`jakarta.persistence.metamodel.SingularAttribute`, -`jakarta.persistence.metamodel.CollectionAttribute`, -`jakarta.persistence.metamodel.SetAttribute`, -`jakarta.persistence.metamodel.ListAttribute`, -`jakarta.persistence.metamodel.MapAttribute`) and all classes `X`, `Y`, -`Z`, `R`, and `K`. - -[NOTE] -==== -Implementations of this specification are -not required to support the use of non-canonical metamodel classes. -Applications that use non-canonical metamodel classes will not be -portable. -==== - -===== Example [[a6961]] - -Assume the `Order` entity below. - -[source,java] ----- -package com.example; - -import java.util.Set; -import java.math.BigDecimal; - -@Entity -public class Order { - @Id - Integer orderId; - - @ManyToOne - Customer customer; - - @OneToMany - Set lineItems; - - Address shippingAddress; - - BigDecimal totalCost; - - // ... -} ----- - -The corresponding canonical metamodel class, -`Order`, is as follows: - -[source,java] ----- -package com.example; - -import java.math.BigDecimal; -import jakarta.persistence.metamodel.SingularAttribute; -import jakarta.persistence.metamodel.SetAttribute; -import jakarta.persistence.metamodel.StaticMetamodel; - -@StaticMetamodel(Order.class) -public class Order { - public static volatile SingularAttribute orderId; - public static volatile SingularAttribute customer; - public static volatile SetAttribute lineItems; - public static volatile SingularAttribute shippingAddress; - public static volatile SingularAttribute totalCost; -} ----- - -==== Bootstrapping - -When the entity manager factory for a -persistence unit is created, it is the responsibility of the persistence -provider to initialize the state of the metamodel classes of the -persistence unit. Any generated metamodel classes must be accessible on -the classpath. - -Persistence providers must support the use of -canonical metamodel classes. Persistence providers may, but are not -required to, support the use of non-canonical metamodel classes. +These concepts are further described in the sections that follow. The +`jakarta.persistence.criteria` interfaces are presented in <>. +Sections <> through <> describe the construction and +modification of criteria query objects. Additional requirements on the +persistence provider are described in <>. + +The metamodel on which criteria queries are based was already presented +in <>. The static metamodel classes which are used to construct +strongly-typed criteria queries are described in <>. === Criteria API Interfaces [[a6997]]