update the HQL chapter to acknowledge changes in JPA 3.1
This commit is contained in:
parent
a7bb19a2ea
commit
f70d09175a
|
@ -114,7 +114,7 @@ We don't necessarily _recommend_ leaving off the `select` list.
|
||||||
|
|
||||||
[NOTE]
|
[NOTE]
|
||||||
====
|
====
|
||||||
JPQL requires a `select` clause, whereas HQL does not.
|
HQL doesn't require a `select` clause, but JPQL _does_.
|
||||||
|
|
||||||
Naturally, the previous query may be written with a `select` clause:
|
Naturally, the previous query may be written with a `select` clause:
|
||||||
|
|
||||||
|
@ -429,11 +429,12 @@ Again there is some flexibility.
|
||||||
| Datetime | `java.sql.Timestamp` | `current_timestamp` | `current timestamp`
|
| Datetime | `java.sql.Timestamp` | `current_timestamp` | `current timestamp`
|
||||||
|===
|
|===
|
||||||
|
|
||||||
|
Of these, only `local date`, `local time`, `local datetime`, `current_date`, `current_time`, and `current_timestamp` are defined by the JPQL specification.
|
||||||
|
|
||||||
[IMPORTANT]
|
[IMPORTANT]
|
||||||
====
|
====
|
||||||
Of these, only `current_date`, `current_time`, and `current_timestamp` are defined by the JPQL specification.
|
The use of date and time types from the `java.sql` package is strongly discouraged!
|
||||||
|
Always use `java.time` types in new code.
|
||||||
However, the use of date and time types from the `java.sql` package is strongly discouraged, so we encourage the use of the HQL extensions.
|
|
||||||
====
|
====
|
||||||
|
|
||||||
[[hql-duration-literals]]
|
[[hql-duration-literals]]
|
||||||
|
@ -446,6 +447,8 @@ There are two sorts of duration in HQL:
|
||||||
|
|
||||||
Literal duration expressions are of form `n unit`, for example `1 day` or `10 year` or `100 nanosecond`.
|
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]
|
[NOTE]
|
||||||
====
|
====
|
||||||
A HQL duration is considered to map to a Java `java.time.Duration`, but semantically they're perhaps more similar to an ANSI SQL `INTERVAL` type.
|
A HQL duration is considered to map to a Java `java.time.Duration`, but semantically they're perhaps more similar to an ANSI SQL `INTERVAL` type.
|
||||||
|
@ -734,6 +737,20 @@ include::{sourcedir}/HQLTest.java[tags=hql-coalesce-example]
|
||||||
|
|
||||||
TIP: HQL allows `ifnull()` as a synonym for `coalesce()` in the case of exactly two arguments.
|
TIP: HQL allows `ifnull()` as a synonym for `coalesce()` in the case of exactly two arguments.
|
||||||
|
|
||||||
|
[[hql-function-extract]]
|
||||||
|
===== `extract()`
|
||||||
|
Extracts a field of a datetime.
|
||||||
|
|
||||||
|
Field types include: `day`, `month`, `year`, `second`, `minute`, `hour`, `day of week`, `day of month`, `week of year`, `date`, `time` and more.
|
||||||
|
For a full list of field types, see the Javadoc for https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/query/TemporalUnit.html[`TemporalUnit`].
|
||||||
|
|
||||||
|
====
|
||||||
|
[source, JAVA, indent=0]
|
||||||
|
----
|
||||||
|
include::{sourcedir}/HQLTest.java[tags=hql-extract-function-example]
|
||||||
|
----
|
||||||
|
====
|
||||||
|
|
||||||
===== `size()`
|
===== `size()`
|
||||||
|
|
||||||
The number of elements of a collection or to-many association.
|
The number of elements of a collection or to-many association.
|
||||||
|
@ -746,6 +763,11 @@ include::{sourcedir}/HQLTest.java[tags=hql-size-example]
|
||||||
----
|
----
|
||||||
====
|
====
|
||||||
|
|
||||||
|
[[jpql-string-functions]]
|
||||||
|
==== JPQL functions for working with strings
|
||||||
|
|
||||||
|
JPQL defines a number of functions for working with strings.
|
||||||
|
|
||||||
===== `concat()`
|
===== `concat()`
|
||||||
Produces a string by concatenating its arguments.
|
Produces a string by concatenating its arguments.
|
||||||
|
|
||||||
|
@ -758,6 +780,18 @@ include::{sourcedir}/HQLTest.java[tags=hql-concat-function-example]
|
||||||
----
|
----
|
||||||
====
|
====
|
||||||
|
|
||||||
|
===== `locate()`
|
||||||
|
Locates a string within another string.
|
||||||
|
|
||||||
|
The third argument (optional) is used to specify a position at which to start the search.
|
||||||
|
|
||||||
|
====
|
||||||
|
[source, JAVA, indent=0]
|
||||||
|
----
|
||||||
|
include::{sourcedir}/HQLTest.java[tags=hql-locate-function-example]
|
||||||
|
----
|
||||||
|
====
|
||||||
|
|
||||||
===== `substring()`
|
===== `substring()`
|
||||||
A substring of the given string.
|
A substring of the given string.
|
||||||
|
|
||||||
|
@ -771,28 +805,10 @@ include::{sourcedir}/HQLTest.java[tags=hql-substring-function-example]
|
||||||
----
|
----
|
||||||
====
|
====
|
||||||
|
|
||||||
===== `upper()`
|
|
||||||
The given string, with lowercase characters converted to uppercase.
|
|
||||||
|
|
||||||
====
|
|
||||||
[source, JAVA, indent=0]
|
|
||||||
----
|
|
||||||
include::{sourcedir}/HQLTest.java[tags=hql-upper-function-example]
|
|
||||||
----
|
|
||||||
====
|
|
||||||
|
|
||||||
===== `lower()`
|
|
||||||
The given string, with uppercase characters converted to lowercase.
|
|
||||||
|
|
||||||
====
|
|
||||||
[source, JAVA, indent=0]
|
|
||||||
----
|
|
||||||
include::{sourcedir}/HQLTest.java[tags=hql-lower-function-example]
|
|
||||||
----
|
|
||||||
====
|
|
||||||
|
|
||||||
===== `trim()`
|
===== `trim()`
|
||||||
Follows the semantics of the SQL `trim()` function.
|
Follows the syntax and semantics of the ANSI SQL `trim()` function.
|
||||||
|
|
||||||
|
May be used to trim `leading` characters, `trailing` characters, or both.
|
||||||
|
|
||||||
====
|
====
|
||||||
[source, JAVA, indent=0]
|
[source, JAVA, indent=0]
|
||||||
|
@ -801,87 +817,64 @@ include::{sourcedir}/HQLTest.java[tags=hql-trim-function-example]
|
||||||
----
|
----
|
||||||
====
|
====
|
||||||
|
|
||||||
===== `length()`
|
Finally, there's three more functions for working with strings that are easy to understand.
|
||||||
The length of a string.
|
|
||||||
|
|===
|
||||||
|
| JPQL Function | Purpose | Signature
|
||||||
|
|
||||||
|
| `length()` | The length of the string | `length(s)`
|
||||||
|
| `upper()` | The string, with lowercase characters converted to uppercase | `upper(s)`
|
||||||
|
| `lower()` | The string, with uppercase characters converted to lowercase | `lower(s)`
|
||||||
|
|===
|
||||||
|
|
||||||
====
|
====
|
||||||
[source, JAVA, indent=0]
|
[source, JAVA, indent=0]
|
||||||
----
|
----
|
||||||
include::{sourcedir}/HQLTest.java[tags=hql-length-function-example]
|
include::{sourcedir}/HQLTest.java[tags=hql-length-function-example]
|
||||||
----
|
----
|
||||||
====
|
|
||||||
|
|
||||||
===== `locate()`
|
|
||||||
Locates a string within another string.
|
|
||||||
|
|
||||||
The third argument (optional) is used to specify a position at which to start the search.
|
|
||||||
|
|
||||||
====
|
|
||||||
[source, JAVA, indent=0]
|
[source, JAVA, indent=0]
|
||||||
----
|
----
|
||||||
include::{sourcedir}/HQLTest.java[tags=hql-locate-function-example]
|
include::{sourcedir}/HQLTest.java[tags=hql-upper-function-example]
|
||||||
----
|
----
|
||||||
|
//[source, JAVA, indent=0]
|
||||||
|
//----
|
||||||
|
//include::{sourcedir}/HQLTest.java[tags=hql-lower-function-example]
|
||||||
|
//----
|
||||||
====
|
====
|
||||||
|
|
||||||
===== `abs()`
|
[[jpql-numeric-functions]]
|
||||||
The magnitude of a numeric value.
|
==== JPQL numeric functions
|
||||||
|
|
||||||
|
Of course, JPQL also defines a number of functions for working with numeric values.
|
||||||
|
|
||||||
|
|===
|
||||||
|
| JPQL Function | Purpose | Signature
|
||||||
|
|
||||||
|
| `abs()` | The magnitude of a number | `abs(x)`
|
||||||
|
| `sign()` | The sign of a number | `sign(x)`
|
||||||
|
| `mod()` | Remainder of integer division | `mod(n,d)`
|
||||||
|
| `sqrt()` | Square root of a number | `sqrt(x)`
|
||||||
|
| `exp()` | Exponential function | `exp(x)`
|
||||||
|
| `power()` | Exponentiation | `power(x,y)`
|
||||||
|
| `ln()` | Natural logarithm | `ln(x)`
|
||||||
|
| `round()` | Numeric rounding | `round(number, places)`
|
||||||
|
| `floor()` | Floor function | `floor(x)`
|
||||||
|
| `ceiling()` | Ceiling function | `ceiling(x)`
|
||||||
|
|===
|
||||||
|
|
||||||
====
|
====
|
||||||
[source, JAVA, indent=0]
|
[source, JAVA, indent=0]
|
||||||
----
|
----
|
||||||
include::{sourcedir}/HQLTest.java[tags=hql-abs-function-example]
|
include::{sourcedir}/HQLTest.java[tags=hql-abs-function-example]
|
||||||
----
|
----
|
||||||
====
|
|
||||||
|
|
||||||
===== `mod()`
|
|
||||||
Calculates the remainder of dividing the first argument by the second.
|
|
||||||
|
|
||||||
====
|
|
||||||
[source, JAVA, indent=0]
|
[source, JAVA, indent=0]
|
||||||
----
|
----
|
||||||
include::{sourcedir}/HQLTest.java[tags=hql-mod-function-example]
|
include::{sourcedir}/HQLTest.java[tags=hql-mod-function-example]
|
||||||
----
|
----
|
||||||
====
|
|
||||||
|
|
||||||
===== `sqrt()`
|
|
||||||
The square root of a numeric value.
|
|
||||||
|
|
||||||
====
|
|
||||||
[source, JAVA, indent=0]
|
|
||||||
----
|
----
|
||||||
include::{sourcedir}/HQLTest.java[tags=hql-sqrt-function-example]
|
include::{sourcedir}/HQLTest.java[tags=hql-sqrt-function-example]
|
||||||
----
|
----
|
||||||
====
|
====
|
||||||
//
|
|
||||||
//CURRENT_DATE::
|
|
||||||
//Returns the database current date.
|
|
||||||
//
|
|
||||||
//====
|
|
||||||
//[source, JAVA, indent=0]
|
|
||||||
//----
|
|
||||||
//include::{sourcedir}/HQLTest.java[tags=hql-current-date-function-example]
|
|
||||||
//----
|
|
||||||
//====
|
|
||||||
//
|
|
||||||
//CURRENT_TIME::
|
|
||||||
//Returns the database current time.
|
|
||||||
//
|
|
||||||
//====
|
|
||||||
//[source, JAVA, indent=0]
|
|
||||||
//----
|
|
||||||
//include::{sourcedir}/HQLTest.java[tags=hql-current-time-function-example]
|
|
||||||
//----
|
|
||||||
//====
|
|
||||||
//
|
|
||||||
//CURRENT_TIMESTAMP::
|
|
||||||
//Returns the database current timestamp.
|
|
||||||
//
|
|
||||||
//====
|
|
||||||
//[source, JAVA, indent=0]
|
|
||||||
//----
|
|
||||||
//include::{sourcedir}/HQLTest.java[tags=hql-current-timestamp-function-example]
|
|
||||||
//----
|
|
||||||
//====
|
|
||||||
|
|
||||||
We have not included <<hql-aggregate-functions,aggregate functions>> in this list, because their purpose is more specialized.
|
We have not included <<hql-aggregate-functions,aggregate functions>> in this list, because their purpose is more specialized.
|
||||||
|
|
||||||
|
@ -913,38 +906,6 @@ include::{sourcedir}/HQLTest.java[tags=hql-str-function-example]
|
||||||
----
|
----
|
||||||
====
|
====
|
||||||
|
|
||||||
[[hql-function-extract]]
|
|
||||||
===== `extract()`
|
|
||||||
Extracts a field of a datetime.
|
|
||||||
|
|
||||||
Field types include: `day`, `month`, `year`, `second`, `minute`, `hour`, `day of week`, `day of month`, `week of year`, `date`, `time` and more.
|
|
||||||
For a full list of field types, see the Javadoc for https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/query/TemporalUnit.html[`TemporalUnit`].
|
|
||||||
|
|
||||||
====
|
|
||||||
[source, JAVA, indent=0]
|
|
||||||
----
|
|
||||||
include::{sourcedir}/HQLTest.java[tags=hql-extract-function-example]
|
|
||||||
----
|
|
||||||
====
|
|
||||||
|
|
||||||
The following synonyms for `extract()` are also provided:
|
|
||||||
|
|
||||||
|===
|
|
||||||
| `year(x)` | `extract(year from x)`
|
|
||||||
| `month(x)` | `extract(month from x)`
|
|
||||||
| `day(x)` | `extract(day from x)`
|
|
||||||
| `hour(x)` | `hour(year from x)`
|
|
||||||
| `minute(x)` | `minute(year from x)`
|
|
||||||
| `second(x)` | `second(year from x)`
|
|
||||||
|===
|
|
||||||
|
|
||||||
====
|
|
||||||
[source, JAVA, indent=0]
|
|
||||||
----
|
|
||||||
include::{sourcedir}/HQLTest.java[tags=hql-year-function-example]
|
|
||||||
----
|
|
||||||
====
|
|
||||||
|
|
||||||
===== `collate()`
|
===== `collate()`
|
||||||
|
|
||||||
Selects a collation to be used for its string-valued argument.
|
Selects a collation to be used for its string-valued argument.
|
||||||
|
@ -963,28 +924,6 @@ The syntax is `format(datetime as pattern)`, and the pattern must be written in
|
||||||
|
|
||||||
For a full list of `format()` pattern elements, see the Javadoc for https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/dialect/Dialect.html#appendDatetimeFormat[`Dialect#appendDatetimeFormat`].
|
For a full list of `format()` pattern elements, see the Javadoc for https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/dialect/Dialect.html#appendDatetimeFormat[`Dialect#appendDatetimeFormat`].
|
||||||
|
|
||||||
[[hql-function-sql]]
|
|
||||||
===== `sql()`
|
|
||||||
|
|
||||||
Renders a SQL fragment by unquoting the pattern string literal arguments.
|
|
||||||
Use cases that require the use of SQL features that are unsupported in HQL,
|
|
||||||
e.g. functions with special syntax, would usually require a switch to native queries,
|
|
||||||
but the `sql` function provides a way to make use of certain SQL fragments within an HQL query.
|
|
||||||
|
|
||||||
The syntax is `sql(pattern[, argN]*)`, where pattern must be a string literal but other arguments may be of any type.
|
|
||||||
|
|
||||||
The pattern literal is unquoted and will be used for rendering the SQL fragment.
|
|
||||||
Occurrences of question marks `?` in the pattern are replaced with additional arguments passed to the function.
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
```sql
|
|
||||||
-- Cast to some native type
|
|
||||||
select c from Computer c where c.ipAddress = sql('?::inet', '127.0.0.1')
|
|
||||||
-- Use some native operator
|
|
||||||
select h from Human h order by sql('(? <-> ?)', h.workLocation, h.homeLocation)
|
|
||||||
```
|
|
||||||
|
|
||||||
[[hql-list-functions]]
|
[[hql-list-functions]]
|
||||||
===== `element()` and `index()`
|
===== `element()` and `index()`
|
||||||
|
|
||||||
|
@ -1028,21 +967,34 @@ Next, functions for working with numeric values:
|
||||||
|===
|
|===
|
||||||
| HQL Function | Purpose | Signature | Notes on naming
|
| HQL Function | Purpose | Signature | Notes on naming
|
||||||
|
|
||||||
| `sign()` | The sign of a number | `sign(x)` | Universal in SQL dialects
|
|
||||||
| `exp()` | Exponential function | `exp(x)` | Universal in SQL dialects
|
|
||||||
| `power()` | Exponentiation | `power(x,y)` | Universal in SQL dialects
|
|
||||||
| `ln()` | Natural logarithm | `ln(x)` | Very common in SQL dialects
|
|
||||||
| `log10()` | Base-10 logarithm | `log10(x)` | Very common in SQL dialects
|
| `log10()` | Base-10 logarithm | `log10(x)` | Very common in SQL dialects
|
||||||
| `log()` | Arbitrary-base logarithm | `log(b,x)` | Very common in SQL dialects
|
| `log()` | Arbitrary-base logarithm | `log(b,x)` | Very common in SQL dialects
|
||||||
| `pi` | π | `pi` | Very common in SQL dialects
|
| `pi` | π | `pi` | Very common in SQL dialects
|
||||||
| `sin()`, `cos()`, `tan()`, `asin()`, `acos()`, `atan()`, `atan2()` | Basic trigonometric functions | `sin(theta)`, `cos(theta)`, `atan2(opposite, adjacent)` | Very common in SQL dialects
|
| `sin()`, `cos()`, `tan()`, `asin()`, `acos()`, `atan()`, `atan2()` | Basic trigonometric functions | `sin(theta)`, `cos(theta)`, `atan2(opposite, adjacent)` | Very common in SQL dialects
|
||||||
| `round()` | Numeric rounding | As usual: `round(number, places)` | Very common in SQL dialects
|
|
||||||
| `floor()` | Floor function | `floor(x)` | Universal in SQL dialects
|
|
||||||
| `ceiling()` | Ceiling function | `ceiling(x)` | Very common in SQL dialects
|
|
||||||
| `least()` | Return the smallest of the given arguments | `least(x, y, z)` | Very common in SQL dialects
|
| `least()` | Return the smallest of the given arguments | `least(x, y, z)` | Very common in SQL dialects
|
||||||
| `greatest()` | Return the largest of the given arguments | `greatest(x, y, z)` | Very common in SQL dialects
|
| `greatest()` | Return the largest of the given arguments | `greatest(x, y, z)` | Very common in SQL dialects
|
||||||
|===
|
|===
|
||||||
|
|
||||||
|
Next, the following functions are abbreviations for `extract()`:
|
||||||
|
|
||||||
|
|===
|
||||||
|
| HQL Function | Long form using `extract()`
|
||||||
|
|
||||||
|
| `year(x)` | `extract(year from x)`
|
||||||
|
| `month(x)` | `extract(month from x)`
|
||||||
|
| `day(x)` | `extract(day from x)`
|
||||||
|
| `hour(x)` | `extract(year from x)`
|
||||||
|
| `minute(x)` | `extract(year from x)`
|
||||||
|
| `second(x)` | `extract(year from x)`
|
||||||
|
|===
|
||||||
|
|
||||||
|
====
|
||||||
|
[source, JAVA, indent=0]
|
||||||
|
----
|
||||||
|
include::{sourcedir}/HQLTest.java[tags=hql-year-function-example]
|
||||||
|
----
|
||||||
|
====
|
||||||
|
|
||||||
Finally, functions that evaluate the id, version, or natural id of an entity, or the foreign key of a to-one association:
|
Finally, functions that evaluate the id, version, or natural id of an entity, or the foreign key of a to-one association:
|
||||||
|
|
||||||
[[hql-model-functions]]
|
[[hql-model-functions]]
|
||||||
|
@ -1092,6 +1044,25 @@ include::{sourcedir}/HQLTest.java[tags=hql-native-function-example]
|
||||||
----
|
----
|
||||||
====
|
====
|
||||||
|
|
||||||
|
[[hql-function-sql]]
|
||||||
|
==== Embedding native SQL in HQL
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
====
|
||||||
|
[source, SQL, indent=0]
|
||||||
|
----
|
||||||
|
-- Cast to some native type
|
||||||
|
select c from Computer c where c.ipAddress = sql('?::inet', '127.0.0.1')
|
||||||
|
-- Use some native operator
|
||||||
|
select h from Human h order by sql('(? <-> ?)', h.workLocation, h.homeLocation)
|
||||||
|
----
|
||||||
|
====
|
||||||
|
|
||||||
[[hql-conditional-expressions]]
|
[[hql-conditional-expressions]]
|
||||||
=== Predicates
|
=== Predicates
|
||||||
|
|
||||||
|
|
|
@ -255,11 +255,11 @@ public class HQLTest extends BaseEntityManagerFunctionalTestCase {
|
||||||
doInJPA(this::entityManagerFactory, entityManager -> {
|
doInJPA(this::entityManagerFactory, entityManager -> {
|
||||||
//tag::hql-insert-example[]
|
//tag::hql-insert-example[]
|
||||||
entityManager.createQuery(
|
entityManager.createQuery(
|
||||||
"insert Person (id, name) " +
|
"insert Person (id, name) " +
|
||||||
"values (101L, 'J A Doe III'), " +
|
"values (101L, 'J A Doe III'), " +
|
||||||
"(102L, 'J X Doe'), " +
|
"(102L, 'J X Doe'), " +
|
||||||
"(103L, 'John Doe, Jr')")
|
"(103L, 'John Doe, Jr')")
|
||||||
.executeUpdate();
|
.executeUpdate();
|
||||||
//end::hql-insert-example[]
|
//end::hql-insert-example[]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -268,8 +268,8 @@ public class HQLTest extends BaseEntityManagerFunctionalTestCase {
|
||||||
public void hql_insert_with_sequence_example() {
|
public void hql_insert_with_sequence_example() {
|
||||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||||
entityManager.createQuery(
|
entityManager.createQuery(
|
||||||
"insert Person (name) values ('Jane Doe2')" )
|
"insert Person (name) values ('Jane Doe2')" )
|
||||||
.executeUpdate();
|
.executeUpdate();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue