parent
5ae55d7bfb
commit
c48be75d3b
|
@ -419,7 +419,7 @@ HQL allows Java `static` constants to be used in the same way, for example, `jav
|
|||
[[hql-entity-name-literals]]
|
||||
==== Literal entity names
|
||||
|
||||
Entity names may also occur as a literal value. They do not need to be qualified. See <<hql-entity-type-exp>>.
|
||||
Entity names may also occur as a literal value. They do not need to be qualified. See <<hql-treat-type>>.
|
||||
|
||||
[[hql-expressions]]
|
||||
=== Expressions
|
||||
|
@ -500,31 +500,13 @@ Please carefully note the difference between these two operations: `by` and `ext
|
|||
|
||||
Additional datetime operations, including the useful `format()` function, are defined below, in <<hql-exp-functions>>.
|
||||
|
||||
[[hql-identification-variable]]
|
||||
==== Identification variable
|
||||
[[hql-path-expressions]]
|
||||
==== Identification variables and path expressions
|
||||
|
||||
Identification variables, and path expressions beginning with an identification variable are legal expression in almost every context.
|
||||
|
||||
See <<hql-from-clause>>.
|
||||
|
||||
[[hql-path-expressions]]
|
||||
==== Path expressions
|
||||
|
||||
Again, see <<hql-from-clause>>.
|
||||
|
||||
[[hql-entity-type-exp]]
|
||||
==== Entity type
|
||||
|
||||
The special 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.
|
||||
|
||||
[[hql-entity-type-exp-example]]
|
||||
//.Entity type expression examples
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/HQLTest.java[tags=hql-entity-type-exp-example]
|
||||
----
|
||||
====
|
||||
|
||||
[[hql-case-expressions]]
|
||||
==== Case expressions
|
||||
|
||||
|
@ -602,9 +584,6 @@ include::{sourcedir}/HQLTest.java[tags=hql-case-arithmetic-expressions-example]
|
|||
If the arithmetic expression was not enclosed in parentheses, the parser would be unable to parse the expression.
|
||||
====
|
||||
|
||||
==== Typecasts
|
||||
|
||||
The `treat` operator may be used to downcast the type of an identification variable, for example, `treat(payment as CreditCardPayment)`.
|
||||
|
||||
[[hql-exp-functions]]
|
||||
=== Functions
|
||||
|
@ -613,6 +592,37 @@ Both HQL and JPQL define some standard functions that are portable between datab
|
|||
|
||||
In addition, there are several ways to use a database function that's not known to Hibernate.
|
||||
|
||||
[[hql-treat-type]]
|
||||
==== Types and typecasts
|
||||
|
||||
The special 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.
|
||||
|
||||
[[hql-entity-type-exp-example]]
|
||||
//.Entity type expression examples
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/HQLTest.java[tags=hql-entity-type-exp-example]
|
||||
----
|
||||
====
|
||||
|
||||
The special function `treat()` may be used to narrow the type of an identification variable.
|
||||
This is useful when dealing with entity inheritance hierarchies.
|
||||
|
||||
[[hql-treat-example]]
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/HQLTest.java[tags=hql-treat-example]
|
||||
----
|
||||
====
|
||||
|
||||
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 `treat()` function may even occur in a <<hql-join-treat,join>>.
|
||||
|
||||
[[jpql-standardized-functions]]
|
||||
==== JPQL standard functions
|
||||
|
||||
|
@ -1102,7 +1112,7 @@ The type of the expression on the left, and the types of all the values on the r
|
|||
JPQL limits the legal types to string, numeric, date/time, and enum types, and in JPQL the left expression must be either:
|
||||
|
||||
* a "state field", which means a simple attribute, excluding associations and embedded attributes, or
|
||||
* an entity type expression (see <<hql-entity-type-exp>>).
|
||||
* an entity type expression (see <<hql-treat-type>>).
|
||||
|
||||
HQL is far more permissive. HQL itself does not restrict the type 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.
|
||||
|
@ -1445,10 +1455,23 @@ Fetch joins should not be used in paged queries (`setFirstResult()` or `setMaxRe
|
|||
Nor should they be used with the `scroll()` or `stream()` methods.
|
||||
====
|
||||
|
||||
[[hql-treat-as]]
|
||||
==== Joins with `treat`
|
||||
[[hql-join-treat]]
|
||||
==== Joins with typecasts
|
||||
|
||||
A join may narrow the type of the joined entity using `treat()`, for example, `join treat(a.payments as CreditCardPayment)`.
|
||||
An explicit join may narrow the type of the joined entity using `treat()`.
|
||||
|
||||
[[hql-join-treat-example]]
|
||||
====
|
||||
[source, JAVA, indent=0]
|
||||
----
|
||||
include::{sourcedir}/HQLTest.java[tags=hql-join-treat-example]
|
||||
----
|
||||
====
|
||||
|
||||
Here, the identification variable `ccp` declared to the right of `treat()` has the narrowed type `CreditCardPayment`, instead of the declared type `Payment`.
|
||||
This allows the attribute `cardNumber` declared by the subtype `CreditCardPayment` to be referenced in the rest of the query.
|
||||
|
||||
See <<hql-treat-type>> for more information about `treat()`.
|
||||
|
||||
[[hql-implicit-join]]
|
||||
==== Implicit joins (path expressions)
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.userguide.model;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.OneToMany;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
public class Account {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
long id;
|
||||
|
||||
@ManyToOne
|
||||
Person owner;
|
||||
|
||||
@OneToMany(mappedBy = "account")
|
||||
List<Payment> payments = new ArrayList<>();
|
||||
|
||||
public List<Payment> getPayments() {
|
||||
return payments;
|
||||
}
|
||||
|
||||
public Person getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
public void setOwner(Person owner) {
|
||||
this.owner = owner;
|
||||
}
|
||||
}
|
|
@ -35,6 +35,9 @@ public class Call {
|
|||
|
||||
private int duration;
|
||||
|
||||
@ManyToOne
|
||||
private Payment payment;
|
||||
|
||||
//Getters and setters are omitted for brevity
|
||||
|
||||
//end::hql-examples-domain-model-example[]
|
||||
|
@ -71,6 +74,14 @@ public class Call {
|
|||
public void setDuration(int duration) {
|
||||
this.duration = duration;
|
||||
}
|
||||
//tag::hql-examples-domain-model-example[]
|
||||
|
||||
public Payment getPayment() {
|
||||
return payment;
|
||||
}
|
||||
|
||||
public void setPayment(Payment payment) {
|
||||
this.payment = payment;
|
||||
}
|
||||
//tag::hql-examples-domain-model-example[]
|
||||
}
|
||||
//end::hql-examples-domain-model-example[]
|
||||
|
|
|
@ -14,5 +14,14 @@ import jakarta.persistence.Entity;
|
|||
//tag::hql-examples-domain-model-example[]
|
||||
@Entity
|
||||
public class CreditCardPayment extends Payment {
|
||||
String cardNumber;
|
||||
|
||||
public void setCardNumber(String cardNumber) {
|
||||
this.cardNumber = cardNumber;
|
||||
}
|
||||
|
||||
public String getCardNumber() {
|
||||
return cardNumber;
|
||||
}
|
||||
}
|
||||
//end::hql-examples-domain-model-example[]
|
||||
|
|
|
@ -30,6 +30,9 @@ public class Payment {
|
|||
|
||||
private boolean completed;
|
||||
|
||||
@ManyToOne
|
||||
private Account account;
|
||||
|
||||
@ManyToOne
|
||||
private Person person;
|
||||
|
||||
|
@ -68,6 +71,14 @@ public class Payment {
|
|||
public void setPerson(Person person) {
|
||||
this.person = person;
|
||||
}
|
||||
//tag::hql-examples-domain-model-example[]
|
||||
|
||||
public Account getAccount() {
|
||||
return account;
|
||||
}
|
||||
|
||||
public void setAccount(Account account) {
|
||||
this.account = account;
|
||||
}
|
||||
//tag::hql-examples-domain-model-example[]
|
||||
}
|
||||
//end::hql-examples-domain-model-example[]
|
||||
|
|
|
@ -18,8 +18,10 @@ import org.hibernate.StatelessSession;
|
|||
import org.hibernate.Transaction;
|
||||
import org.hibernate.orm.test.jpa.BaseEntityManagerFunctionalTestCase;
|
||||
import org.hibernate.resource.transaction.spi.TransactionStatus;
|
||||
import org.hibernate.userguide.model.Account;
|
||||
import org.hibernate.userguide.model.Call;
|
||||
import org.hibernate.userguide.model.Partner;
|
||||
import org.hibernate.userguide.model.Payment;
|
||||
import org.hibernate.userguide.model.Person;
|
||||
import org.hibernate.userguide.model.Phone;
|
||||
|
||||
|
@ -39,6 +41,8 @@ public class BatchTest extends BaseEntityManagerFunctionalTestCase {
|
|||
Person.class,
|
||||
Phone.class,
|
||||
Call.class,
|
||||
Account.class,
|
||||
Payment.class,
|
||||
Partner.class
|
||||
};
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import jakarta.persistence.criteria.Predicate;
|
|||
import jakarta.persistence.criteria.Root;
|
||||
|
||||
import org.hibernate.orm.test.jpa.BaseEntityManagerFunctionalTestCase;
|
||||
import org.hibernate.userguide.model.Account;
|
||||
import org.hibernate.userguide.model.AddressType;
|
||||
import org.hibernate.userguide.model.Call;
|
||||
import org.hibernate.userguide.model.CreditCardPayment;
|
||||
|
@ -55,6 +56,7 @@ public class CriteriaTest extends BaseEntityManagerFunctionalTestCase {
|
|||
Call.class,
|
||||
CreditCardPayment.class,
|
||||
WireTransferPayment.class,
|
||||
Account.class,
|
||||
Event.class
|
||||
};
|
||||
}
|
||||
|
|
|
@ -33,7 +33,9 @@ import org.hibernate.dialect.SQLServerDialect;
|
|||
import org.hibernate.dialect.TiDBDialect;
|
||||
import org.hibernate.orm.test.jpa.BaseEntityManagerFunctionalTestCase;
|
||||
import org.hibernate.query.QueryProducer;
|
||||
import org.hibernate.testing.Skip;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
import org.hibernate.userguide.model.Account;
|
||||
import org.hibernate.userguide.model.AddressType;
|
||||
import org.hibernate.userguide.model.Call;
|
||||
import org.hibernate.userguide.model.CreditCardPayment;
|
||||
|
@ -67,6 +69,7 @@ public class HQLTest extends BaseEntityManagerFunctionalTestCase {
|
|||
Person.class,
|
||||
Phone.class,
|
||||
Call.class,
|
||||
Account.class,
|
||||
CreditCardPayment.class,
|
||||
WireTransferPayment.class
|
||||
};
|
||||
|
@ -120,15 +123,28 @@ public class HQLTest extends BaseEntityManagerFunctionalTestCase {
|
|||
person2.addPhone( phone2 );
|
||||
person2.addPhone( phone3 );
|
||||
|
||||
Account account1 = new Account();
|
||||
account1.setOwner( person1 );
|
||||
entityManager.persist( account1 );
|
||||
|
||||
Account account2 = new Account();
|
||||
account1.setOwner( person2 );
|
||||
entityManager.persist( account2 );
|
||||
|
||||
CreditCardPayment creditCardPayment = new CreditCardPayment();
|
||||
creditCardPayment.setCompleted( true );
|
||||
creditCardPayment.setAmount( BigDecimal.ZERO );
|
||||
creditCardPayment.setPerson( person1 );
|
||||
creditCardPayment.setCardNumber("1234-1234-1234-1234");
|
||||
creditCardPayment.setAccount( account1 );
|
||||
call11.setPayment( creditCardPayment );
|
||||
|
||||
WireTransferPayment wireTransferPayment = new WireTransferPayment();
|
||||
wireTransferPayment.setCompleted( true );
|
||||
wireTransferPayment.setAmount( BigDecimal.valueOf( 100 ) );
|
||||
wireTransferPayment.setPerson( person2 );
|
||||
wireTransferPayment.setAccount( account2 );
|
||||
call12.setPayment( wireTransferPayment );
|
||||
|
||||
entityManager.persist( creditCardPayment );
|
||||
entityManager.persist( wireTransferPayment );
|
||||
|
@ -1886,6 +1902,56 @@ public class HQLTest extends BaseEntityManagerFunctionalTestCase {
|
|||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_hql_treat_example() {
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
//tag::hql-treat-example[]
|
||||
List<Payment> payments = entityManager.createQuery(
|
||||
"select p " +
|
||||
"from Payment p " +
|
||||
"where length(treat(p as CreditCardPayment).cardNumber) between 16 and 20",
|
||||
Payment.class )
|
||||
.getResultList();
|
||||
//end::hql-treat-example[]
|
||||
assertEquals(1, payments.size());
|
||||
});
|
||||
}
|
||||
|
||||
@Test @Skip(condition = Skip.AlwaysSkip.class, message = "broken in H6")
|
||||
public void test_hql_join_many_treat_example() {
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
//tag::hql-join-treat-example[]
|
||||
// a to-many association
|
||||
List<Object[]> payments = entityManager.createQuery(
|
||||
"select a, ccp " +
|
||||
"from Account a " +
|
||||
"join treat(a.payments as CreditCardPayment) ccp " +
|
||||
"where length(ccp.cardNumber) between 16 and 20",
|
||||
Object[].class )
|
||||
.getResultList();
|
||||
//end::hql-join-treat-example[]
|
||||
assertEquals(1, payments.size());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_hql_join_one_treat_example() {
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
//tag::hql-join-treat-example[]
|
||||
|
||||
// a to-one association
|
||||
List<Object[]> payments = entityManager.createQuery(
|
||||
"select c, ccp " +
|
||||
"from Call c " +
|
||||
"join treat(c.payment as CreditCardPayment) ccp " +
|
||||
"where length(ccp.cardNumber) between 16 and 20",
|
||||
Object[].class )
|
||||
.getResultList();
|
||||
//end::hql-join-treat-example[]
|
||||
assertEquals(1, payments.size());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_hql_entity_type_exp_example_1() {
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
|
@ -1905,6 +1971,8 @@ public class HQLTest extends BaseEntityManagerFunctionalTestCase {
|
|||
public void test_hql_entity_type_exp_example_2() {
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
//tag::hql-entity-type-exp-example[]
|
||||
|
||||
// using a parameter instead of a literal entity type
|
||||
List<Payment> payments = entityManager.createQuery(
|
||||
"select p " +
|
||||
"from Payment p " +
|
||||
|
|
|
@ -20,6 +20,7 @@ import org.hibernate.loader.NonUniqueDiscoveredSqlAliasException;
|
|||
import org.hibernate.proxy.HibernateProxy;
|
||||
import org.hibernate.transform.Transformers;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
import org.hibernate.userguide.model.Account;
|
||||
import org.hibernate.userguide.model.AddressType;
|
||||
import org.hibernate.userguide.model.Call;
|
||||
import org.hibernate.userguide.model.CreditCardPayment;
|
||||
|
@ -55,6 +56,7 @@ public class SQLTest extends BaseEntityManagerFunctionalTestCase {
|
|||
Partner.class,
|
||||
Phone.class,
|
||||
Call.class,
|
||||
Account.class,
|
||||
CreditCardPayment.class,
|
||||
WireTransferPayment.class,
|
||||
SpaceShip.class,
|
||||
|
|
Loading…
Reference in New Issue