Full Syntax
This section discusses the EJB QL syntax, as defined in the Enterprise JavaBeans specification. Much of the following material paraphrases or directly quotes the specification.
BNF Symbols
Table 29-1 describes the BNF symbols used in this chapter.
BNF Grammar of EJB QL
Here is the entire BNF diagram for EJB QL:
EJB QL ::= select_clause from_clause [where_clause] [orderby_clause] from_clause ::=FROMidentification_variable_declaration [, identification_variable_declaration]* identification_variable_declaration ::= collection_member_declaration | range_variable_declaration collection_member_declaration ::=IN( collection_valued_path_expression) [AS] identifier range_variable_declaration ::= abstract_schema_name [AS] identifier cmp_path_expression ::= {identification_variable | single_valued_cmr_path_expression}.cmp_field single_valued_cmr_path_expression ::= identification_variable.[single_valued_cmr_field.]* single_valued_cmr_field single_valued_path_expression ::= cmp_path_expression | single_valued_cmr_path_expression collection_valued_path_expression ::= identification_variable.[single_valued_cmr_field.] *collection_valued_cmr_field select_clause ::=SELECT[DISTINCT] {select_expression |OBJECT( identification_variable) } select_expression ::= single_valued_path_expression | aggregate_select_expression aggregate_select_expression ::= {AVG|MAX|MIN|SUM|COUNT}( [DISTINCT] cmp_path_expression) |COUNT( [DISTINCT] identification_variable | single_valued_cmr_path_expression) where_clause ::=WHEREconditional_expression conditional_expression ::= conditional_term | conditional_expressionORconditional_term conditional_term ::= conditional_factor | conditional_termANDconditional_factor conditional_factor ::= [NOT] conditional_primary conditional_primary ::= simple_cond_expression | (conditional_expression) simple_cond_expression ::= comparison_expression | between_expression | like_expression | in_expression | null_comparison_expression | empty_collection_comparison_expression | collection_member_expression between_expression ::= arithmetic_expression [NOT]BETWEENarithmetic_expressionANDarithmetic_expression in_expression ::= cmp_path_expression [NOT]IN( {literal | input_parameter} [, { literal | input_parameter} ]*) like_expression ::= cmp_path_expression [NOT]LIKEpattern_value [ESCAPEescape_character] null_comparison_expression ::= {single_valued_path_expression | input_parameter}IS[NOT]NULLempty_collection_comparison_expression ::= collection_valued_path_expressionIS[NOT]EMPTYcollection_member_expression ::= {single_valued_cmr_path_expression | identification_variable | input_parameter} [NOT]MEMBER[OF] collection_valued_path_expression comparison_expression ::= string_value comparison_operator string_expression | boolean_value {= |<> } boolean_expression} | datetime_value comparison_operator datetime_expression | entity_bean_value {= |<> } entity_bean_expression | arithmetic_value comparison_operator arithmetic_expression arithmetic_value ::= cmp_path_expression | functions_returning_numerics comparison_operator ::= = |> |>= |< |<= |<> arithmetic_expression ::= arithmetic_term | arithmetic_expression {+ |- } arithmetic_term arithmetic_term ::= arithmetic_factor | arithmetic_term {* |/ } arithmetic_factor arithmetic_factor ::= [{+ |- }] arithmetic_primary arithmetic_primary ::= cmp_path_expression | literal | (arithmetic_expression) | input_parameter | functions_returning_numerics string_value ::= cmp_path_expression | functions_returning_strings string_expression ::= string_primary | input_parameter string_primary ::= cmp_path_expression | literal | (string_expression) | functions_returning_strings datetime_value ::= cmp_path_expression datetime_expression ::= datetime_value | input_parameter boolean_value ::= cmp_path_expression boolean_expression ::= cmp_path_expression | literal | input_parameter entity_bean_value ::= single_valued_cmr_path_expression | identification_variable entity_bean_expression ::= entity_bean_value | input_parameter functions_returning_strings ::=CONCAT( string_expression, string_expression) |SUBSTRING( string_expression, arithmetic_expression, arithmetic_expression) functions_returning_numerics ::=LENGTH( string_expression) |LOCATE( string_expression, string_expression [, arithmetic_expression]) |ABS( arithmetic_expression) |SQRT( arithmetic_expression) |MOD( arithmetic_expression, arithmetic_expression) orderby_clause ::=ORDERBYorderby_item [, orderby_item]* orderby_item ::= cmp_path_expression [ASC|DESC]FROM Clause
The
FROMclause defines the domain of the query by declaring identification variables. Here is the syntax of theFROMclause:from_clause ::=FROMidentification_variable_declaration [, identification_variable_declaration]* identification_variable_declaration ::= collection_member_declaration | range_variable_declaration collection_member_declaration ::=IN(collection_valued_path_expression) [AS] identifier range_variable_declaration ::= abstract_schema_name [AS] identifierIdentifiers
An identifier is a sequence of one or more characters. The first character must be a valid first character (letter,
$,_) in an identifier of the Java programming language (hereafter in this chapter called simply "Java"). Each subsequent character in the sequence must be a valid nonfirst character (letter, digit,$,_) in a Java identifier. (For details, see the J2SE API documentation of theisJavaIdentifierStartandisJavaIdentifierPartmethods of theCharacterclass.) The question mark (?) is a reserved character in EJB QL and cannot be used in an identifier. Unlike a Java variable, an EJB QL identifier is not case-sensitive.An identifier cannot be the same as an EJB QL keyword:
ANDASASCAVGBETWEENBYCOUNTDESCDISTINCTEMPTYFALSEFROMINISLIKEMAXMEMBERMINMODNOTNULLOBJECTOFORORDERSELECTSUMTRUEUNKNOWNWHERE
EJB QL keywords are also reserved words in SQL. In the future, the list of EJB QL keywords may expand to include other reserved SQL words. The Enterprise JavaBeans specification recommends that you not use other reserved SQL words for EJB QL identifiers.
Identification Variables
An identification variable is an identifier declared in the
FROMclause. Although theSELECTandWHEREclauses can reference identification variables, they cannot declare them. All identification variables must be declared in theFROMclause.Because an identification variable is an identifier, it has the same naming conventions and restrictions as an identifier. For example, an identification variable is not case-sensitive, and it cannot be the same as an EJB QL keyword. (See the preceding section for more naming rules.) Also, within a given EJB JAR file, an identifier name must not match the name of any entity bean or abstract schema.
The
FROMclause can contain multiple declarations, separated by commas. A declaration can reference another identification variable that has been previously declared (to the left). In the followingFROMclause, the variabletreferences the previously declared variablep:Even if an identification variable is not used in the
WHEREclause, its declaration can affect the results of the query. For an example, compare the next two queries. The following query returns all players, whether or not they belong to a team:In contrast, because the next query declares the
tidentification variable, it fetches all players that belong to a team:The following query returns the same results as the preceding query, but the
WHEREclause makes it easier to read:An identification variable always designates a reference to a single value whose type is that of the expression used in the declaration. There are two kinds of declarations: range variable and collection member.
Range Variable Declarations
To declare an identification variable as an abstract schema type, you specify a range variable declaration. In other words, an identification variable can range over the abstract schema type of an entity bean. In the following example, an identification variable named
prepresents the abstract schema namedPlayer:A range variable declaration can include the optional
ASoperator:In most cases, to obtain objects a query uses path expressions to navigate through the relationships. But for those objects that cannot be obtained by navigation, you can use a range variable declaration to designate a starting point (or root).
If the query compares multiple values of the same abstract schema type, then the
FROMclause must declare multiple identification variables for the abstract schema:For a sample of such a query, see Example 9 .
Collection Member Declarations
In a one-to-many relationship, the multiple side consists of a collection of entity beans. An identification variable can represent a member of this collection. To access a collection member, the path expression in the variable's declaration navigates through the relationships in the abstract schema. (For more information on path expressions, see the following section.) Because a path expression can be based on another path expression, the navigation can traverse several relationships. See Example 6 .
A collection member declaration must include the
INoperator, but it can omit the optionalASoperator.In the following example, the entity bean represented by the abstract schema named
Playerhas a relationship field calledteams. The identification variable calledtrepresents a single member of theteamscollection.Path Expressions
Path expressions are important constructs in the syntax of EJB QL, for several reasons. First, they define navigation paths through the relationships in the abstract schema. These path definitions affect both the scope and the results of a query. Second, they can appear in any of the three main clauses of an EJB QL query (
SELECT,WHERE,FROM). Finally, although much of EJB QL is a subset of SQL, path expressions are extensions not found in SQL.Syntax
Here is the syntax for path expressions:
cmp_path_expression ::=
{identification_variable |
single_valued_cmr_path_expression}.cmp_field
single_valued_cmr_path_expression ::=
identification_variable.[single_valued_cmr_field.]*
single_valued_cmr_field
single_valued_path_expression ::=
cmp_path_expression | single_valued_cmr_path_expression
collection_valued_path_expression ::=
identification_variable.[single_valued_cmr_field.]
*collection_valued_cmr_fieldIn the preceding diagram, the
cmp_fieldelement represents a persistent field, and thecmr_fieldelement designates a relationship field. The termsingle_valuedqualifies the relationship field as the single side of a one-to-one or one-to-many relationship; the termcollection_valueddesignates it as the multiple (collection) side of a relationship. Thesingle_valued_cmr_path_expressionis the abstract schema type of the related entity bean.The period (.) in a path expression serves two functions. If a period precedes a persistent field, it is a delimiter between the field and the identification variable. If a period precedes a relationship field, it is a navigation operator.
Examples
In the following query, the
WHEREclause contains acmp_path_expression. Thepis an identification variable, andsalaryis a persistent field ofPlayer.The
WHEREclause of the next example also contains acmp_path_expression. Thetis an identification variable,leagueis a single-valued relationship field, andsportis a persistent field ofleague.In the next query, the
WHEREclause contains acollection_valued_path_expression. Thepis an identification variable, andteamsdesignates a collection-valued relationship field.Expression Types
The type of an expression is the type of the object represented by the ending element, which can be one of the following:
For example, the type of the expression
p.salaryisdoublebecause the terminating persistent field (salary) is adouble.In the expression
p.teams, the terminating element is a collection-valued relationship field (teams). This expression's type is a collection of the abstract schema type namedTeam. BecauseTeamis the abstract schema name for theTeamBeanentity bean, this type maps to the bean's local interface,LocalTeam. For more information on the type mapping of abstract schemas, see the section Return Types.Navigation
A path expression enables the query to navigate to related entity beans. The terminating elements of an expression determine whether navigation is allowed. If an expression contains a single-valued relationship field, the navigation can continue to an object that is related to the field. However, an expression cannot navigate beyond a persistent field or a collection-valued relationship field. For example, the expression
p.teams.league.sportis illegal, becauseteamsis a collection-valued relationship field. To reach thesportfield, theFROMclause could define an identification variable namedtfor theteamsfield:WHERE Clause
The
WHEREclause specifies a conditional expression that limits the values returned by the query. The query returns all corresponding values in the data store for which the conditional expression isTRUE. Although usually specified, theWHEREclause is optional. If theWHEREclause is omitted, then the query returns all values. The high-level syntax for theWHEREclause follows:Literals
There are three kinds of literals: string, numeric, and Boolean.
String Literals
A string literal is enclosed in single quotes:
If a string literal contains a single quote, you indicate the quote by using two single quotes:
Like a Java
String, a string literal in EJB QL uses the Unicode character encoding.Numeric Literals
There are two types of numeric literals: exact and approximate.
An exact numeric literal is a numeric value without a decimal point, such as 65, -233, and +12. Using the Java integer syntax, exact numeric literals support numbers in the range of a Java
long.An approximate numeric literal is a numeric value in scientific notation, such as 57., -85.7, and +2.1. Using the syntax of the Java floating-point literal, approximate numeric literals support numbers in the range of a Java
double.Boolean Literals
A Boolean literal is either
TRUEorFALSE. These keywords are not case-sensitive.Input Parameters
An input parameter is designated by a question mark (
?) followed by an integer. For example, the first input parameter is?1, the second is?2, and so forth.The following rules apply to input parameters:
- They can be used only in a
WHEREclause.- Their use is restricted to a single-valued path expression within a conditional expression.
- They must be numbered, starting with the integer 1.
- The number of input parameters in the
WHEREclause must not exceed the number of input parameters in the corresponding finder or select method.- The type of an input parameter in the
WHEREclause must match the type of the corresponding argument in the finder or select method.Conditional Expressions
A
WHEREclause consists of a conditional expression, which is evaluated from left to right within a precedence level. You can change the order of evaluation by using parentheses.Here is the syntax of a conditional expression:
conditional_expression ::= conditional_term | conditional_expressionORconditional_term conditional_term ::= conditional_factor | conditional_termANDconditional_factor conditional_factor ::= [NOT] conditional_primary conditional_primary ::= simple_cond_expression | (conditional_expression) simple_cond_expression ::= comparison_expression | between_expression | like_expression | in_expression | null_comparison_expression | empty_collection_comparison_expression | collection_member_expressionOperators and Their Precedence
Table 29-2 lists the EJB QL operators in order of decreasing precedence.
BETWEEN Expressions
A
BETWEENexpression determines whether an arithmetic expression falls within a range of values. The syntax of theBETWEENexpression follows:between_expression ::= arithmetic_expression [NOT]BETWEENarithmetic_expressionANDarithmetic_expressionThese two expressions are equivalent:
The following two expressions are also equivalent:
If an arithmetic expression has a
NULLvalue, then the value of theBETWEENexpression is unknown.IN Expressions
An
INexpression determines whether or not a string belongs to a set of string literals. Here is the syntax of theINexpression:in_expression ::= cmp_path_expression [NOT]IN( {literal | input_parameter} [, { literal | input_parameter} ]*)The path expression must have a string or numeric value. If the path expression has a
NULLvalue, then the value of theINexpression is unknown.In the following example, if the country is
UKthe expression isTRUE. If the country isPeruit isFALSE.LIKE Expressions
A
LIKEexpression determines whether a wildcard pattern matches a string. Here is the syntax:The path expression must have a string or numeric value. If this value is
NULL, then the value of theLIKEexpression is unknown. The pattern value is a string literal that can contain wildcard characters. The underscore (_) wildcard character represents any single character. The percent (%) wildcard character represents zero or more characters. TheESCAPEclause specifies an escape character for the wildcard characters in the pattern value. Table 29-3 shows some sampleLIKEexpressions.
NULL Comparison Expressions
A
NULLcomparison expression tests whether a single-valued path expression or an input parameter has aNULLvalue. Usually, theNULLcomparison expression is used to test whether or not a single-valued relationship has been set. Here is the syntax of aNULLcomparison expression:Empty Collection Comparison Expressions
An empty collection comparison expression tests whether a collection-valued path expression has no elements. In other words, it tests whether or not a collection-valued relationship has been set. Here is the syntax:
If the collection-valued path expression is
NULL, then the empty collection comparison expression has aNULLvalue.Collection Member Expressions
The collection member expression determines whether a value is a member of a collection. The value and the collection members must have the same type. The expression syntax follows:
collection_member_expression ::= {single_valued_cmr_path_expression | identification_variable | input_parameter} [NOT]MEMBER[OF] collection_valued_path_expressionIf either the collection-valued or single-valued path expression is unknown, then the collection member expression is unknown. If the collection-valued path expression designates an empty collection, then the collection member expression is
FALSE.Functional Expressions
EJB QL includes several string and arithmetic functions, which are listed in the following tables. In Table 29-4, the
startandlengtharguments are of typeint. They designate positions in theStringargument. The first position in a string is designated by 1. In Table 29-5, thenumberargument can be either anint, afloat, or adouble.
Table 29-4 String Expressions Function Syntax Return TypeCONCAT(String, String)StringLENGTH(String)intLOCATE(String, String [, start])intSUBSTRING(String, start, length)String
Table 29-5 Arithmetic Expressions Function Syntax Return TypeABS(number)int,float, ordoubleMOD(int, int)intSQRT(double)double
NULL Values
If the target of a reference is not in the persistent store, then the target is
NULL. For conditional expressions containingNULL, EJB QL uses the semantics defined by SQL92. Briefly, these semantics are as follows:
- If a comparison or arithmetic operation has an unknown value, it yields a
NULLvalue.- Two
NULLvalues are not equal. Comparing twoNULLvalues yields an unknown value.- The
IS NULLtest converts aNULLpersistent field or a single-valued relationship field toTRUE. TheIS NOT NULLtest converts them toFALSE.- Boolean operators and conditional tests use the three-valued logic defined by Table 29-6 and Table 29-7. (In these tables, T stands for
TRUE, F forFALSE, and U for unknown.)Equality Semantics
In EJB QL, only values of the same type can be compared. However, this rule has one exception: Exact and approximate numeric values can be compared. In such a comparison, the required type conversion adheres to the rules of Java numeric promotion.
EJB QL treats compared values as if they were Java types and not as if they represented types in the underlying data store. For example, if a persistent field could be either an integer or a
NULL, then it must be designated as anIntegerobject and not as anintprimitive. This designation is required because a Java object can beNULLbut a primitive cannot.Two strings are equal only if they contain the same sequence of characters. Trailing blanks are significant; for example, the strings
'abc'and'abc 'are not equal.Two entity beans of the same abstract schema type are equal only if their primary keys have the same value. Table 29-8 shows the operator logic of a negation, and Table 29-9 shows the truth values of conditional tests.
Table 29-9 Conditional Test Conditional Test T F U ExpressionIS TRUE T F F ExpressionIS FALSE F T F Expression is unknown F F T
SELECT Clause
The
SELECTclause defines the types of the objects or values returned by the query. TheSELECTclause has the following syntax:select_clause ::=SELECT[DISTINCT] {select_expression |OBJECT( identification_variable) } select_expression ::= single_valued_path_expression | aggregate_select_expression aggregate_select_expression ::= {AVG|MAX|MIN|SUM|COUNT}( [DISTINCT] cmp_path_expression) |COUNT( [DISTINCT] identification_variable | single_valued_cmr_path_expression)Return Types
The return type defined by the
SELECTclause must match that of the finder or select method for which the query is defined.For finder method queries, the return type of the
SELECTclause is the abstract schema type of the entity bean that defines the finder method. This abstract schema type maps to either a remote or a local interface. If the bean's remote home interface defines the finder method, then the return type is the remote interface (or a collection of remote interfaces). Similarly, if the local home interface defines the finder method, the return type is the local interface (or a collection). For example, theLocalPlayerHomeinterface of thePlayerBeanentity bean defines thefindallmethod:The EJB QL query of the
findallmethod returns a collection ofLocalPlayerinterface types:For select method queries (except for aggregate function queries), the return type of the
SELECTclause can be one of the following:
- The abstract schema of the entity bean that contains the select method.
- The abstract schema of a related entity bean. (By default, each of these abstract schema types maps to the local interface of the entity bean. Although it is uncommon, in the deployment descriptor you can override the default mapping by specifying a remote interface.)
- A persistent field.
The
PlayerBeanentity bean, for example, implements theejbSelectSportsmethod, which returns a collection ofStringobjects forsport. Thesportis a persistent field of theLeagueBeanentity bean. See Example 11 .A
SELECTclause cannot specify a collection-valued expression. For example, theSELECTclausep.teamsis invalid becauseteamsis a collection. However, the clause in the following query is valid because thetis a single element of theteamscollection:For select method queries with an aggregate function (
AVG,COUNT,MAX,MIN, orSUM) in theSELECTclause, the following rules apply:
- The select method must return a single object, primitive, or wrapper type that is compatible with the standard JDBC conversion mappings for the persistent field type.
- For the
AVG,MAX,MIN, andSUMfunctions, if the select method return type is an object and the function returns no values, then the select method returnsnull. In this case, if the select method return type is a primitive, then the container throws theObjectNotFoundException.- For the
COUNTfunction, the result of the select method must be an exact numeric type. If the function returns no values, the select method returns 0.DISTINCT and OBJECT Keywords
The
DISTINCTkeyword eliminates duplicate return values. If the method of the query returns ajava.util.Collection--which allows duplicates--then you must specify theDISTINCTkeyword to eliminate duplicates. However, if the method returns ajava.util.Set, theDISTINCTkeyword is redundant because ajava.util.Setcannot contain duplicates.The
OBJECTkeyword must precede a stand-alone identification variable, but it must not precede a single-valued path expression. If an identification variable is part of a single-valued path expression, it is not stand-alone.Aggregate Functions
The
SELECTclause can contain an aggregate function with the following syntax:aggregate_select_expression ::= {AVG|MAX|MIN|SUM|COUNT}( [DISTINCT] cmp_path_expression) |COUNT( [DISTINCT] identification_variable | single_valued_cmr_path_expression)Except for the
COUNTfunction, the path expression argument for an aggregate function must terminate in a persistent field. For theCOUNTfunction, the path expression argument can terminate in a persistent field, a relationship field, or an identification variable.The arguments of the
SUMandAVGfunctions must be numeric. The arguments of theMAXandMINfunctions must be orderable: numeric, string, character, or date.If the argument is empty, the
COUNTfunction returns 0 and the other aggregate functions returnNULL.If the
DISTINCTkeyword is specified, duplicate values are eliminated before the aggregate function is applied.NULLvalues are always eliminated before the function is applied, whether or not theDISTINCTkeyword is used.ORDER BY Clause
As its name suggests, the
ORDER BYclause orders the values or objects returned by the query. The syntax of the clause follows:orderby_clause ::=ORDERBYorderby_item [, orderby_item]* orderby_item ::= cmp_path_expression [ASC|DESC]If the
ORDER BYclause contains multipleorderby_itemelements, the left-to-right sequence of the elements determines the high-to-low precedence.The
ASCkeyword specifies ascending order (the default), and theDESCkeyword indicates descending order.If the
ORDER BYclause is used, then theSELECTclause must be one of the following:If the
SELECTclause is an identification variable or asingle_valued_cmr_path_expression, then theorderby_itemmust be an orderable persistent field of the entity bean returned by theSELECTclause. If theSELECTclause is acmp_path_expression, then thecmp_path_expressionand theorderby_itemmust evaluate to the same persistent field of the same entity bean.