We now switch gears, and begin describing the language from the bottom up. The very bottom of a programming language is its syntax for literal values.
The most important literal value in this language is null
. It’s assignable to any other type.
String literals are enclosed in single quotes.
select 'hello world'
To escape a single quote within a string literal, use a doubled single quote: ''
.
from Book where title like 'Ender''s'
Alternatively, Java-style double-quoted strings are also allowed, with the usual Java character escape syntax.
select "hello\tworld"
This option is not much used.
Numeric literals come in several different forms:
Kind | Type | Example |
---|---|---|
Integer literals |
|
|
Decimal literals |
|
|
Hexadecimal literals |
|
|
Scientific notation |
|
|
For example:
from Book where price < 100.0
select author, count(book)
from Author as author
join author.books as book
group by author
having count(book) > 10
The type of a numeric literal may be specified using a Java-style postfix:
Postfix | Type | Java type |
---|---|---|
|
long integer |
|
|
double precision |
|
|
single precision |
|
|
large integer |
|
|
exact decimal |
|
It’s not usually necessary to specify the precision explicitly.
Note
|
In a literal with an exponent, the |
According to the JPQL specification, date and time literals may be specified using the JDBC escape syntax. Since this syntax is rather unpleasant to look at, HQL provides not one, but two alternatives.
Date/time type | Recommended Java type | JDBC escape syntax 💀 | Braced literal syntax | Explicitly typed literal syntax |
---|---|---|---|---|
Date |
|
|
|
|
Time |
|
|
|
|
Time with seconds |
|
|
|
|
Datetime |
|
|
|
|
Datetime with milliseconds |
|
|
|
|
Datetime with an offset |
|
|
|
|
Datetime with a time zone |
|
|
|
|
Literals referring to the current date and time are also provided. Again there is some flexibility.
Date/time type | Java type | Underscored syntax | Spaced syntax |
---|---|---|---|
Date |
|
|
|
Time |
|
|
|
Datetime |
|
|
|
Offset datetime |
|
|
|
Instant |
|
|
|
Date |
|
|
|
Time |
|
|
|
Datetime |
|
|
|
Of these, only local date
, local time
, local datetime
, current_date
, current_time
, and current_timestamp
are defined by the JPQL specification.
Important
|
The use of date and time types from the |
There are two sorts of duration in HQL:
-
year-day durations, that is, the length of an interval between two dates, and
-
week-nanosecond durations, that is, the length of an interval between two datetimes.
For conceptual reasons, the two kinds of duration cannot be cleanly composed.
Literal duration expressions are of form n unit
, for example 1 day
or 10 year
or 100 nanosecond
.
The unit may be: day
, month
, quarter
, year
, second
, minute
, hour
, or nanosecond
.
Note
|
A HQL duration is considered to map to a Java |
HQL also provides a choice of formats for binary strings:
-
the braced syntax
{0xDE, 0xAD, 0xBE, 0xEF}
, a list of Java-style hexadecimal byte literals, or -
the quoted syntax
X’DEADBEEF'
orx’deadbeef'
, similar to SQL.
Literal values of a Java enumerated type may be written without needing to specify the enum class name:
from Book where status <> OUT_OF_PRINT
Here, the enum class is inferred from the type of the expression on the left of the comparison operator.
HQL allows any Java static
constant to be used in HQL, but it must be referenced by its fully-qualified name:
select java.lang.Math.PI
Entity names may also occur as a literal value. They do not need to be qualified.
from Payment as payment
where type(payment) = CreditCardPayment
See Types and typecasts.
A path expression is either:
-
a reference to an identification variable, or
-
a compound path, beginning with a reference to an identification variable, and followed by a period-separated list of references to entity attributes.
As an extension to the JPA spec, HQL, just like SQL, allows a compound path expression where the identification variable at the beginning of the path is missing.
That is, instead of var.foo.bar
, it’s legal to write just foo.bar
.
But this is only allowed when the identification variable may be unambiguously inferred from the first element, foo
of the compound path.
The query must have exactly one identification variable var
for which the path var.foo
refers to an entity attribute.
Note that we will continue to call these paths "compound", even if they only have one element.
Tip
|
This streamlines the query rather nicely when there’s just one root entity and no joins. But when the query has multiple identification variables it makes the query much harder to understand. |
If an element of a compound path refers to an association, the path expression produces an implicit join.
select book.publisher.name from Book book
An element of a compound path referring to a many-to-one or on-to-one association may have the treat function applied to it.
select treat(order.payment as CreditCardPayment).creditCardNumber from Order order
If an element of a compound path refers to a collection or many-valued association, it must have one of these special functions applied to it.
select element(book.authors).name from Book book
No other function may be applied to a non-terminal element of a path expression.
Alternatively, if the element of the compound path refers to a list or map, it may have the indexing operator applied to it:
select book.editions[0].date from Book book
No other operator may be applied to a non-terminal element of a path expression.
HQL has operators for working with strings, numeric values, and date/time types.
The operator precedence is given by this table, from highest to lowest precedence:
Precedence class | Type | Operators |
---|---|---|
Grouping and tuple instantiation |
|
|
Case lists |
|
|
Member reference |
Binary infix |
|
Function application |
Postfix |
|
Indexing |
Postfix |
|
Unary numeric |
Unary prefix |
|
Duration conversions |
Unary postfix |
|
Binary multiplicative |
Binary infix |
|
Binary additive |
Binary infix |
|
Concatenation |
Binary infix |
|
Nullness |
Unary postfix |
|
Containment |
Binary infix |
|
Between |
Ternary infix |
|
Pattern matching |
Binary infix |
|
Comparison operators |
Binary infix |
|
Nullsafe comparison |
Binary infix |
|
Existence |
Unary prefix |
|
Membership |
Binary infix |
|
Logical negation |
Unary prefix |
|
Logical conjunction |
Binary infix |
|
Logical disjunction |
Binary infix |
|
HQL defines two ways to concatenate strings:
-
the SQL-style concatenation operator,
||
, and -
the JPQL-standard
concat()
function.
See below for details of the concat()
function.
select book.title || ' by ' || listagg(author.name, ' & ')
from Book as book
join book.authors as author
group by book
Many more operations on strings are defined below, in Functions.
The basic SQL arithmetic operators, +
,-
,*
, and /
are joined by the remainder operator %
.
select (1.0 + :taxRate) * sum(item.book.price * item.quantity)
from Order as ord
join ord.items as item
where ord.id = :oid
When both operands of a binary numeric operator have the same type, the result type of the whole expression is the same as the operands.
Warning
|
Thus, |
When the operands are of different type, one of the operands is implicitly converted to wider type, with wideness given, in decreasing order, by the list below:
-
Double
(widest) -
Float
-
BigDecimal
-
BigInteger
-
Long
-
Integer
-
Short
-
Byte
Many more numeric operations are defined below, in Functions.
Arithmetic involving dates, datetimes, and durations is quite subtle. Among the issues to consider are:
-
There’s two kinds of duration: year-day, and week-nanosecond durations. The first is a difference between dates; the second is a difference between datetimes.
-
We can subtract dates and datetimes, but we can’t add them.
-
A Java-style duration has much too much precision, and so in order to use it for anything useful, we must somehow truncate it to something coarser-grained.
Here we list the basic operations.
Operator | Expression type | Example | Resulting type |
---|---|---|---|
|
Difference between two dates |
|
year-day duration |
|
Difference between two datetimes |
|
week-nanosecond duration |
|
Sum of a date and a year-day duration |
|
date |
|
Sum of a datetime and a week-nanosecond duration |
|
datetime |
|
Product of an integer and a duration |
|
duration |
|
Convert a duration to an integer |
|
integer |
The by unit
operator converts a duration to an integer, for example: (local date - your.birthday) by day
evaluates to the number of days you still have to wait.
The function extract(unit from …)
extracts a field from a date, time, or datetime type, for example, extract(year from your.birthday)
produces the year in which you were born, and throws away important information about your birthday.
Important
|
Please carefully note the difference between these two operations: |
Additional datetime operations, including the useful format()
function, are defined below, in Functions.
Just like in standard SQL, there are two forms of case expression:
-
the simple case expression, and
-
the so-called searched case expression.
Tip
|
Case expressions are verbose.
It’s often simpler to use the |
The syntax of the simple form is defined by:
link:{extrasdir}/simple_case_bnf.txt[role=include]
For example:
select
case author.nomDePlume
when '' then person.name
else author.nomDePlume end
from Author as author
join author.person as person
The searched form has the following syntax:
link:{extrasdir}/searched_case_bnf.txt[role=include]
For example:
select
case
when author.nomDePlume is null then person.name
else author.nomDePlume end
from Author as author
join author.person as person
A case
expression may contain complex expression, including operator expressions.
Both HQL and JPQL define some standard functions and make them portable between databases.
Tip
|
A program that wishes to remain portable between Jakarta Persistence providers should in principle limit itself to the use of the functions which are blessed by the specification. Unfortunately, there’s not so many of them. |
In some cases, the syntax of these functions looks a bit funny at first, for example, cast(number as String)
, or extract(year from date)
, or even trim(leading '.' from string)
.
This syntax is inspired by standard ANSI SQL, and we promise you’ll get used to it.
Important
|
HQL abstracts away from the actual database-native SQL functions, letting you write queries which are portable between databases. For some functions, and always depending on the database, a HQL function invocation translates to a quite complicated SQL expression! |
In addition, there are several ways to use a database function that’s not known to Hibernate.
The following special functions make it possible to discover or narrow expression types:
Special function | Purpose | Signature | JPA standard |
---|---|---|---|
|
The (concrete) entity name |
|
✔ |
|
Narrow an entity type |
|
✔ |
|
Narrow a basic type |
|
✖ |
|
Cast to a string |
|
✖ |
Let’s see what these functions do.
The function type()
, applied to an identification variable, evaluates to the entity name of the referenced entity.
This is mainly useful when dealing with entity inheritance hierarchies.
select payment
from Payment as payment
where type(payment) = CreditCardPayment
The function treat()
may be used to narrow the type of an identification variable.
This is useful when dealing with entity inheritance hierarchies.
select payment
from Payment as payment
where length(treat(payment as CreditCardPayment).cardNumber)
between 16 and 20
The type of the expression treat(p as CreditCardPayment)
is the narrowed type, CreditCardPayment
, instead of the declared type Payment
of p
.
This allows the attribute cardNumber
declared by the subtype CreditCardPayment
to be referenced.
-
The first argument is usually an identification variable.
-
The second argument is the target type given as an unqualified entity name.
The treat()
function may even occur in a join.
The function cast()
has a similar syntax, but is used to narrow basic types.
-
Its first argument is usually an attribute of an entity, or a more complex expression involving entity attributes.
-
Its second argument is the target type given as an unqualified Java class name:
String
,Long
,Integer
,Double
,Float
,Character
,Byte
,BigInteger
,BigDecimal
,LocalDate
,LocalTime
,LocalDateTime
, etc.
select cast(id as String) from Order
The function str(x)
is a synonym for cast(x as String)
.
select str(id) from Order
The following functions make it easy to deal with null values:
Function | Purpose | Signature | JPA standard |
---|---|---|---|
|
First non-null argument |
|
✔ |
|
Second argument if first is null |
|
✖ |
|
|
|
✔ |
The coalesce()
function is a sort of abbreviated case
expression that returns the first non-null operand.
select coalesce(author.nomDePlume, person.name)
from Author as author
join author.person as person
HQL allows ifnull()
as a synonym for coalesce()
in the case of exactly two arguments.
select ifnull(author.nomDePlume, person.name)
from Author as author
join author.person as person
On the other hand, nullif()
evaluates to null if its operands are equal, or to its first argument otherwise.
select ifnull(nullif(author.nomDePlume, person.name), 'Real name')
from Author as author
join author.person as person
There are some very important functions for working with dates and times.
Special function | Purpose | Signature | JPA standard |
---|---|---|---|
|
Extract a datetime field |
|
✔ |
|
Format a datetime as a string |
|
✖ |
|
Datetime truncation |
|
✖ |
The special function extract()
obtains a single field of a date, time, or datetime.
-
Its first argument is an expression that evaluates to a date, time, or datetime.
-
Its second argument is a date/time field type.
Field types include: day
, month
, year
, second
, minute
, hour
, day of week
, day of month
, week of year
, date
, time
, epoch
and more.
For a full list of field types, see the Javadoc for TemporalUnit
.
from Order where extract(date from created) = local date
select extract(year from created), extract(month from created) from Order
The following functions are abbreviations for extract()
:
Function | Long form using extract() |
JPA standard |
---|---|---|
|
|
✖ |
|
|
✖ |
|
|
✖ |
|
|
✖ |
|
|
✖ |
|
|
✖ |
Tip
|
These abbreviations aren’t part of the JPQL standard, but on the other hand they’re a lot less verbose. |
select year(created), month(created) from Order
The format()
function formats a date, time, or datetime according to a pattern.
-
Its first argument is an expression that evaluates to a date, time, or datetime.
-
Its second argument is a formatting pattern, given as a string.
The pattern must be written in a subset of the pattern language defined by Java’s java.time.format.DateTimeFormatter
.
For a full list of format()
pattern elements, see the Javadoc for Dialect.appendDatetimeFormat
.
The truncate()
function truncates the precision of a date, time, or datetime to the temporal unit specified by field type.
-
Its first argument is an expression that evaluates to a date, time, or datetime.
-
Its second argument is a date/time field type, specifying the precision of the truncated value.
Supported temporal units are: year
, month
, day
, hour
, minute
or second
.
Truncating a date, time or datetime value means obtaining a value of the same type in which all temporal units smaller than field
have been pruned.
For hours, minutes and second this means setting them to 00
. For months and days, this means setting them to 01
.
Naturally, there are a good number of functions for working with strings.
Function | Purpose | Syntax | JPA standard / ANSI SQL Standard |
---|---|---|---|
|
The string, with lowercase characters converted to uppercase |
|
✔ / ✔ |
|
The string, with uppercase characters converted to lowercase |
|
✔ / ✔ |
|
The length of the string |
|
✔ / ✖ |
|
Concatenate strings |
|
✔ / ✖ |
|
Location of string within a string |
|
✔ / ✖ |
|
Similar to |
|
✖ / ✔ |
|
Substring of a string (JPQL-style) |
|
✔ / ✖ |
|
Substring of a string (ANSI SQL-style) |
|
✖ / ✔ |
|
Trim characters from string |
See below |
✔ / ✔ |
|
For replacing a substring |
|
✖ / ✔ |
|
Pads a string with whitespace, or with a specified character |
|
✖ / ✖ |
|
The leftmost characters of a string |
|
✖ / ✖ |
|
The rightmost characters of a string |
|
✖ / ✖ |
|
Replace every occurrence of a pattern in a string |
|
✖ / ✖ |
|
Concatenate a string with itself multiple times |
|
✖ / ✖ |
|
Select a collation |
|
✖ / ✖ |
Let’s take a closer look at just some of these.
Important
|
Contrary to Java, positions of characters within strings are indexed from 1 instead of 0! |
The JPQL-standard and ANSI SQL-standard concat()
function accepts a variable number of arguments, and produces a string by concatenating them.
select concat(book.title, ' by ', listagg(author.name, ' & '))
from Book as book
join book.authors as author
group by book
The JPQL function locate()
determines the position of a substring within another string.
-
The first argument is the pattern to search for within the second string.
-
The second argument is the string to search in.
-
The optional third argument is used to specify a position at which to start the search.
select locate('Hibernate', title) from Book
The position()
function has a similar purpose, but follows the ANSI SQL syntax.
select position('Hibernate' in title) from Book
Unsurprisingly, substring()
returns a substring of the given string.
-
The second argument specifies the position of the first character of the substring.
-
The optional third argument specifies the maximum length of the substring.
select substring(title, 0, position(' for Dummies')) from Book
The trim()
function follows the syntax and semantics of ANSI SQL.
It may be used to trim leading
characters, trailing
characters, or both.
select trim(title) from Book
select trim(trailing ' ' from text) from Book
Its BNF is funky:
trimFunction
: "TRIM" "(" trimSpecification? trimCharacter? "FROM"? expression ")" ;
trimSpecification
: "LEADING" | "TRAILING" | "BOTH" ;
Selects a collation to be used for its string-valued argument.
Collations are useful for binary comparisons with <
or >
, and in the order by clause.
For example, collate(p.name as ucs_basic)
specifies the SQL standard collation ucs_basic
.
Important
|
Collations aren’t very portable between databases. |
Of course, we also have a number of functions for working with numeric values.
Function | Purpose | Signature | JPA standard |
---|---|---|---|
|
The magnitude of a number |
|
✔ |
|
The sign of a number |
|
✔ |
|
Remainder of integer division |
|
✔ |
|
Square root of a number |
|
✔ |
|
Exponential function |
|
✔ |
|
Exponentiation |
|
✔ |
|
Natural logarithm |
|
✔ |
|
Numeric rounding |
|
✔ |
|
Numeric truncation |
|
✖ |
|
Floor function |
|
✔ |
|
Ceiling function |
|
✔ |
|
Base-10 logarithm |
|
✖ |
|
Arbitrary-base logarithm |
|
✖ |
|
π |
|
✖ |
|
Basic trigonometric functions |
|
✖ |
|
Two-argument arctangent (range |
|
✖ |
|
Hyperbolic functions |
|
✖ |
|
Convert radians to degrees |
|
✖ |
|
Convert degrees to radians |
|
✖ |
|
Return the smallest of the given arguments |
|
✖ |
|
Return the largest of the given arguments |
|
✖ |
We haven’t included aggregate functions, ordered set aggregate functions, or window functions in this list, because their purpose is more specialized, and because they come with extra special syntax.
The functions described in this section are especially useful when dealing with @ElementCollection
mappings, or with collection mappings involving an @OrderColumn
or @MapKeyColumn
.
The following functions accept either:
-
an identification variable that refers to a joined collection or many-valued association, or
-
a compound path that refers to a collection or many-valued association of an entity.
In case 2, application of the function produces an implicit join.
Function | Applies to | Purpose | JPA standard |
---|---|---|---|
|
Any collection |
The size of a collection |
✔ |
|
Any collection |
The element of a set or list |
✖ |
|
Lists |
The index of a list element |
✔ |
|
Maps |
The key of a map entry |
✔ |
|
Maps |
The value of a map entry |
✔ |
|
Maps |
The whole entry in a map |
✔ |
The next group of functions always accept a compound path referring to a collection or many-valued association of an entity. They’re interpreted as referring to the collection as a whole.
Application of one of these function produces implicit subquery.
Function | Applies to | Purpose | JPA standard |
---|---|---|---|
|
Any collection |
The elements of a set or list, collectively |
✖ |
|
Lists |
The indexes of a list, collectively |
✖ |
|
Maps |
The keys of a map, collectively |
✖ |
|
Maps |
The values of a map, collectively |
✖ |
This query has an implicit join:
select title, element(tags) from Book
This query has an implicit subquery:
select title from Book where 'hibernate' in elements(tags)
The size()
function returns the number of elements of a collection or to-many association.
select name, size(books) from Author
The element()
function returns a reference to an element of a joined set or list.
For an identification variable (case 1 above), this function is optional.
For a compound path (case 2), it’s required.
The index()
function returns a reference to the index of a joined list.
In this example, element()
is optional, but index()
is required:
select id(book), index(ed), element(ed)
from Book book as book
join book.editions as ed
The key()
function returns a reference to a key of a joined map.
The value()
function returns a reference to its value.
select key(entry), value(entry)
from Thing as thing
join thing.entries as entry
The functions elements()
, indices()
, keys()
, and values()
are used to quantify over collections.
We may use them with:
-
a relational comparison, or
Shortcut | Equivalent subquery |
---|---|
|
|
|
|
|
|
|
|
For example:
select title from Book where 'hibernate' in elements(tags)
Don’t confuse the elements()
function with element()
, the indices()
function with index()
, the keys()
function with key()
, or the values()
function with value()
.
The functions named in singular deal with elements of "flattened" collections.
If not already joined, they add an implicit join to the query.
The functions with plural naming do not flatten a collection by joining it.
Important
|
The following queries are different: select title, max(index(revisions)) from Book /* implicit join */ select title, max(indices(revisions)) from Book /* implicit subquery */ The first query produces a single row, with |
Finally, the following functions evaluate the id, version, or natural id of an entity, or the foreign key of a to-one association:
Function | Purpose | JPA standard |
---|---|---|
|
The value of the entity |
✖ |
|
The value of the entity |
✖ |
|
The value of the entity |
✖ |
|
The value of the foreign key column mapped by a |
✖ |
The functions we’ve described above are the functions abstracted by HQL and made portable across databases. But, of course, HQL can’t abstract every function in your database.
There are several ways to call native or user-defined SQL functions.
-
A native or user-defined function may be called using JPQL’s
function
syntax, for example,function('sinh', phi)
. (This is the easiest way, but not the best way.) -
A user-written
FunctionContributor
may register user-defined functions. -
A custom
Dialect
may register additional native functions by overridinginitializeFunctionRegistry()
.
Tip
|
Registering a function isn’t hard, but is beyond the scope of this guide. (It’s even possible to use the APIs Hibernate provides to make your own portable functions!) |
Fortunately, every built-in Dialect
already registers many native functions for the database it supports.
Tip
|
Try setting the log category |
The special function sql()
allows the use of native SQL fragments inside an HQL query.
The signature of this function is sql(pattern[, argN]*)
, where pattern
must be a string literal but the remaining arguments may be of any type.
The pattern literal is unquoted and embedded in the generated SQL.
Occurrences of ?
in the pattern are replaced with the remaining arguments of the function.
We may use this, for example, to perform a native PostgreSQL typecast:
from Computer c where c.ipAddress = sql('?::inet', '127.0.0.1')
This results in SQL logically equivalent to:
select * from Computer c where c.ipAddress = '127.0.0.1'::inet
Or we can use a native SQL operator:
from Human h order by sql('(? <-> ?)', h.workLocation, h.homeLocation)
And this time the SQL is logically equivalent to:
select * from Human h where (h.workLocation <-> h.homeLocation)
A predicate is an operator which, when applied to some argument, evaluates to true
or false
.
In the world of SQL-style ternary logic, we must expand this definition to encompass the possibility that the predicate evaluates to null
.
Typically, a predicate evaluates to null
when one of its arguments is null
.
Predicates occur in the where
clause, the having
clause and in searched case expressions.
The binary comparison operators are borrowed from SQL: =
, >
, >=
, <
, <=
, <>
.
Tip
|
If you prefer, HQL treats != as a synonym for <> .
|
The operands should be of the same type.
from Book where price < 1.0
from Author as author where author.nomDePlume <> author.person.name
select id, total
from (
select ord.id as id, sum(item.book.price * item.quantity) as total
from Order as ord
join Item as item
group by ord
)
where total > 100.0
The ternary between
operator, and its negation, not between
, determine if a value falls within a range.
Of course, all three operands must be of compatible type.
from Book where price between 1.0 and 100.0
The following operators make it easier to deal with null values.
Operator | Negation | Type | Semantics |
---|---|---|---|
|
|
Unary postfix |
|
|
|
Binary |
|
from Author where nomDePlume is not null
The following operators apply to collection-valued attributes and to-many associations.
Operator | Negation | Type | Semantics |
---|---|---|---|
|
|
Unary postfix |
|
|
|
Binary |
|
from Author where books is empty
select author, book
from Author as author, Book as book
where author member of book.authors
The like
operator performs pattern matching on strings.
Its friend ilike
performs case-insensitive matching.
Their syntax is defined by:
link:{extrasdir}/predicate_like_bnf.txt[role=include]
The expression on the right is a pattern, where:
-
_
matches any single character, -
%
matches any number of characters, and -
if an escape character is specified, it may be used to escape either of these wildcards.
from Book where title not like '% for Dummies'
The optional escape
character allows a pattern to include a literal _
or %
character.
As you can guess, not like
and not ilike
are the enemies of like
and ilike
, and evaluate to the exact opposite boolean values.
The in
predicates evaluates to true if the value to its left is in … well, whatever it finds to its right.
Its syntax is unexpectedly complicated:
link:{extrasdir}/predicate_in_bnf.txt[role=include]
This less-than-lovely fragment of the HQL ANTLR grammar tells us that the thing to the right might be:
-
a list of values enclosed in parentheses,
-
a subquery,
-
one of the collection-handling functions defined above, or
-
a query parameter,
The type of the expression on the left, and the types of all the values on the right must be compatible.
Note
|
JPQL limits the legal types to string, numeric, date/time, and enum types, and in JPQL the left expression must be either:
HQL is far more permissive. HQL itself does not restrict the type in any way, though the database itself might. Even embedded attributes are allowed, although that feature depends on the level of support for tuple or "row value" constructors in the underlying database. |
from Payment as payment
where type(payment) in (CreditCardPayment, WireTransferPayment)
from Author as author
where author.person.name in (select name from OldAuthorData)
from Book as book
where :edition in elements(book.editions)
The next example doesn’t work on every database:
from Author as author
where (author.person.name, author.person.birthdate)
in (select name, birthdate from OldAuthorData)
Here we used a "row value" constructor, a seemingly pretty basic feature which is surprisingly-poorly supported.
Tip
|
Here’s a very useful idiom: List<Book> books =
session.createSelectionQuery("from Book where isbn in :isbns", Book.class)
.setParameterList("isbns", listOfIsbns)
.getResultList(); |
The binary comparisons we met above may involve a quantifier, either:
-
a quantified subquery, or
-
a quantifier applied to one of the functions defined above.
The quantifiers are unary prefix operators: all
, every
, any
, and some
.
Subquery operator | Synonym | Semantics |
---|---|---|
|
|
Evaluates to true of the comparison is true for every value in the result set of the subquery |
|
|
Evaluates to true of the comparison is true for at least one value in the result set of the subquery |
from Publisher pub where 100.0 < all(select price from pub.books)
from Publisher pub where :title = some(select title from pub.books)
The unary prefix exists
operator evaluates to true if the thing to its right is nonempty.
The thing to its right might be:
-
a subquery, or
-
one of the functions defined above.
As you can surely guess, not exists
evaluates to true if the thing to the right is empty.
from Author where exists element(books)
from Author as author
where exists (
from Order join items
where book in elements(author.books)
)