Hibernate.orgCommunity Documentation
Table of Contents
Hibernate uses a powerful query language (HQL) that is similar in appearance to SQL. Compared with SQL, however, HQL is fully object-oriented and understands notions like inheritance, polymorphism and association.
With the exception of names of Java classes and properties, queries are case-insensitive. SoSeLeCT is the same assELEct is the same asSELECT, butorg.hibernate.eg.FOO is notorg.hibernate.eg.Foo, andfoo.barSet is notfoo.BARSET.
This manual uses lowercase HQL keywords. Some users find queries with uppercase keywords more readable, but this convention is unsuitable for queries embedded in Java code.
The simplest possible Hibernate query is of the form:
from eg.Cat
This returns all instances of the classeg.Cat. You do not usually need to qualify the class name, sinceauto-import is the default. For example:
from Cat
In order to refer to theCat in other parts of the query, you will need to assign analias. For example:
from Cat as cat
This query assigns the aliascat toCat instances, so you can use that alias later in the query. Theas keyword is optional. You could also write:
from Cat cat
Multiple classes can appear, resulting in a cartesian product or "cross" join.
from Formula, Parameter
from Formula as form, Parameter as param
It is good practice to name query aliases using an initial lowercase as this is consistent with Java naming standards for local variables (e.g.domesticCat).
You can also assign aliases to associated entities or to elements of a collection of values using ajoin. For example:
from Cat as cat inner join cat.mate as mate left outer join cat.kittens as kitten
from Cat as cat left join cat.mate.kittens as kittens
from Formula form full join form.parameter param
The supported join types are borrowed from ANSI SQL:
inner join
left outer join
right outer join
full join (not usually useful)
Theinner join,left outer join andright outer join constructs may be abbreviated.
from Cat as cat join cat.mate as mate left join cat.kittens as kitten
You may supply extra join conditions using the HQLwith keyword.
from Cat as cat left join cat.kittens as kitten with kitten.bodyWeight > 10.0
A "fetch" join allows associations or collections of values to be initialized along with their parent objects using a single select. This is particularly useful in the case of a collection. It effectively overrides the outer join and lazy declarations of the mapping file for associations and collections. SeeSection 20.1, “Fetching strategies” for more information.
from Cat as cat inner join fetch cat.mate left join fetch cat.kittens
A fetch join does not usually need to assign an alias, because the associated objects should not be used in thewhere clause (or any other clause). The associated objects are also not returned directly in the query results. Instead, they may be accessed via the parent object. The only reason you might need an alias is if you are recursively join fetching a further collection:
from Cat as cat inner join fetch cat.mate left join fetch cat.kittens child left join fetch child.kittens
Thefetch construct cannot be used in queries called usingiterate() (thoughscroll() can be used).Fetch should be used together withsetMaxResults() orsetFirstResult(), as these operations are based on the result rows which usually contain duplicates for eager collection fetching, hence, the number of rows is not what you would expect.Fetch should also not be used together with impromptuwith condition. It is possible to create a cartesian product by join fetching more than one collection in a query, so take care in this case. Join fetching multiple collection roles can produce unexpected results for bag mappings, so user discretion is advised when formulating queries in this case. Finally, note thatfull join fetch andright join fetch are not meaningful.
If you are using property-level lazy fetching (with bytecode instrumentation), it is possible to force Hibernate to fetch the lazy properties in the first query immediately usingfetch all properties.
from Document fetch all properties order by name
from Document doc fetch all properties where lower(doc.name) like '%cats%'
HQL supports two forms of association joining:implicit andexplicit.
The queries shown in the previous section all use theexplicit form, that is, where the join keyword is explicitly used in the from clause. This is the recommended form.
Theimplicit form does not use the join keyword. Instead, the associations are "dereferenced" using dot-notation.implicit joins can appear in any of the HQL clauses.implicit join result in inner joins in the resulting SQL statement.
from Cat as cat where cat.mate.name like '%s%'
There are 2 ways to refer to an entity's identifier property:
The special property (lowercase)id may be used to reference the identifier property of an entityprovided that the entity does not define a non-identifier property named id.
If the entity defines a named identifier property, you can use that property name.
References to composite identifier properties follow the same naming rules. If the entity has a non-identifier property named id, the composite identifier property can only be referenced by its defined named. Otherwise, the specialid property can be used to reference the identifier property.
Please note that, starting in version 3.2.2, this has changed significantly. In previous versions,idalways referred to the identifier property regardless of its actual name. A ramification of that decision was that non-identifier properties namedid could never be referenced in Hibernate queries.
Theselect clause picks which objects and properties to return in the query result set. Consider the following:
select matefrom Cat as cat inner join cat.mate as mate
The query will selectmates of otherCats. You can express this query more compactly as:
select cat.mate from Cat cat
Queries can return properties of any value type including properties of component type:
select cat.name from DomesticCat catwhere cat.name like 'fri%'
select cust.name.firstName from Customer as cust
Queries can return multiple objects and/or properties as an array of typeObject[]:
select mother, offspr, mate.namefrom DomesticCat as mother inner join mother.mate as mate left outer join mother.kittens as offspr
Or as aList:
select new list(mother, offspr, mate.name)from DomesticCat as mother inner join mother.mate as mate left outer join mother.kittens as offspr
Or - assuming that the classFamily has an appropriate constructor - as an actual typesafe Java object:
select new Family(mother, mate, offspr)from DomesticCat as mother join mother.mate as mate left join mother.kittens as offspr
You can assign aliases to selected expressions usingas:
select max(bodyWeight) as max, min(bodyWeight) as min, count(*) as nfrom Cat cat
This is most useful when used together withselect new map:
select new map( max(bodyWeight) as max, min(bodyWeight) as min, count(*) as n )from Cat cat
This query returns aMap from aliases to selected values.
HQL queries can even return the results of aggregate functions on properties:
select avg(cat.weight), sum(cat.weight), max(cat.weight), count(cat)from Cat cat
The supported aggregate functions are:
avg(...), sum(...), min(...), max(...)
count(*)
count(...), count(distinct ...), count(all...)
You can use arithmetic operators, concatenation, and recognized SQL functions in the select clause:
select cat.weight + sum(kitten.weight)from Cat cat join cat.kittens kittengroup by cat.id, cat.weight
select firstName||' '||initial||' '||upper(lastName) from Person
Thedistinct andall keywords can be used and have the same semantics as in SQL.
select distinct cat.name from Cat catselect count(distinct cat.name), count(cat) from Cat cat
A query like:
from Cat as cat
returns instances not only ofCat, but also of subclasses likeDomesticCat. Hibernate queries can nameany Java class or interface in thefrom clause. The query will return instances of all persistent classes that extend that class or implement the interface. The following query would return all persistent objects:
from java.lang.Object o
The interfaceNamed might be implemented by various persistent classes:
from Named n, Named m where n.name = m.name
These last two queries will require more than one SQLSELECT. This means that theorder by clause does not correctly order the whole result set. It also means you cannot call these queries usingQuery.scroll().
Thewhere clause allows you to refine the list of instances returned. If no alias exists, you can refer to properties by name:
from Cat where name='Fritz'
If there is an alias, use a qualified property name:
from Cat as cat where cat.name='Fritz'
This returns instances ofCat named 'Fritz'.
The following query:
select foofrom Foo foo, Bar barwhere foo.startDate = bar.date
returns all instances ofFoo with an instance ofbar with adate property equal to thestartDate property of theFoo. Compound path expressions make thewhere clause extremely powerful. Consider the following:
from Cat cat where cat.mate.name is not null
This query translates to an SQL query with a table (inner) join. For example:
from Foo foowhere foo.bar.baz.customer.address.city is not null
would result in a query that would require four table joins in SQL.
The= operator can be used to compare not only properties, but also instances:
from Cat cat, Cat rival where cat.mate = rival.mate
select cat, matefrom Cat cat, Cat matewhere cat.mate = mate
The special property (lowercase)id can be used to reference the unique identifier of an object. SeeSection 16.5, “Referring to identifier property” for more information.
from Cat as cat where cat.id = 123from Cat as cat where cat.mate.id = 69
The second query is efficient and does not require a table join.
Properties of composite identifiers can also be used. Consider the following example wherePerson has composite identifiers consisting ofcountry andmedicareNumber:
from bank.Person personwhere person.id.country = 'AU' and person.id.medicareNumber = 123456
from bank.Account accountwhere account.owner.id.country = 'AU' and account.owner.id.medicareNumber = 123456
Once again, the second query does not require a table join.
SeeSection 16.5, “Referring to identifier property” for more information regarding referencing identifier properties)
The special propertyclass accesses the discriminator value of an instance in the case of polymorphic persistence. A Java class name embedded in the where clause will be translated to its discriminator value.
from Cat cat where cat.class = DomesticCat
You can also use components or composite user types, or properties of said component types. SeeSection 16.17, “Components” for more information.
An "any" type has the special propertiesid andclass that allows you to express a join in the following way (whereAuditLog.item is a property mapped with<any>):
from AuditLog log, Payment paymentwhere log.item.class = 'Payment' and log.item.id = payment.id
Thelog.item.class andpayment.class would refer to the values of completely different database columns in the above query.
Expressions used in thewhere clause include the following:
mathematical operators:+, -, *, /
binary comparison operators:=, >=, <=, <>, !=, like
logical operationsand, or, not
Parentheses( ) that indicates grouping
in,not in,between,is null,is not null,is empty,is not empty,member of andnot member of
"Simple" case,case ... when ... then ... else ... end, and "searched" case,case when ... then ... else ... end
string concatenation...||... orconcat(...,...)
current_date(),current_time(), andcurrent_timestamp()
second(...),minute(...),hour(...),day(...),month(...), andyear(...)
Any function or operator defined by EJB-QL 3.0:substring(), trim(), lower(), upper(), length(), locate(), abs(), sqrt(), bit_length(), mod()
coalesce() andnullif()
str() for converting numeric or temporal values to a readable string
cast(... as ...), where the second argument is the name of a Hibernate type, andextract(... from ...) if ANSIcast() andextract() is supported by the underlying database
the HQLindex() function, that applies to aliases of a joined indexed collection
HQL functions that take collection-valued path expressions:size(), minelement(), maxelement(), minindex(), maxindex(), along with the specialelements() andindices functions that can be quantified usingsome, all, exists, any, in.
Any database-supported SQL scalar function likesign(),trunc(),rtrim(), andsin()
JDBC-style positional parameters?
named parameters:name,:start_date, and:x1
SQL literals'foo',69,6.66E+2,'1970-01-01 10:00:01.0'
Javapublic static final constantseg.Color.TABBY
in andbetween can be used as follows:
from DomesticCat cat where cat.name between 'A' and 'B'
from DomesticCat cat where cat.name in ( 'Foo', 'Bar', 'Baz' )
The negated forms can be written as follows:
from DomesticCat cat where cat.name not between 'A' and 'B'
from DomesticCat cat where cat.name not in ( 'Foo', 'Bar', 'Baz' )
Similarly,is null andis not null can be used to test for null values.
Booleans can be easily used in expressions by declaring HQL query substitutions in Hibernate configuration:
<property name="hibernate.query.substitutions">true 1, false 0</property>
This will replace the keywordstrue andfalse with the literals1 and0 in the translated SQL from this HQL:
from Cat cat where cat.alive = true
You can test the size of a collection with the special propertysize or the specialsize() function.
from Cat cat where cat.kittens.size > 0
from Cat cat where size(cat.kittens) > 0
For indexed collections, you can refer to the minimum and maximum indices usingminindex andmaxindex functions. Similarly, you can refer to the minimum and maximum elements of a collection of basic type using theminelement andmaxelement functions. For example:
from Calendar cal where maxelement(cal.holidays) > current_date
from Order order where maxindex(order.items) > 100
from Order order where minelement(order.items) > 10000
The SQL functionsany, some, all, exists, in are supported when passed the element or index set of a collection (elements andindices functions) or the result of a subquery (see below):
select mother from Cat as mother, Cat as kitwhere kit in elements(foo.kittens)
select p from NameList list, Person pwhere p.name = some elements(list.names)
from Cat cat where exists elements(cat.kittens)
from Player p where 3 > all elements(p.scores)
from Show show where 'fizard' in indices(show.acts)
Note that these constructs -size,elements,indices,minindex,maxindex,minelement,maxelement - can only be used in the where clause in Hibernate3.
Elements of indexed collections (arrays, lists, and maps) can be referred to by index in a where clause only:
from Order order where order.items[0].id = 1234
select person from Person person, Calendar calendarwhere calendar.holidays['national day'] = person.birthDay and person.nationality.calendar = calendar
select item from Item item, Order orderwhere order.items[ order.deliveredItemIndices[0] ] = item and order.id = 11
select item from Item item, Order orderwhere order.items[ maxindex(order.items) ] = item and order.id = 11
The expression inside[] can even be an arithmetic expression:
select item from Item item, Order orderwhere order.items[ size(order.items) - 1 ] = item
HQL also provides the built-inindex() function for elements of a one-to-many association or collection of values.
select item, index(item) from Order order join order.items itemwhere index(item) < 5
Scalar SQL functions supported by the underlying database can be used:
from DomesticCat cat where upper(cat.name) like 'FRI%'
Consider how much longer and less readable the following query would be in SQL:
select custfrom Product prod, Store store inner join store.customers custwhere prod.name = 'widget' and store.location.name in ( 'Melbourne', 'Sydney' ) and prod = all elements(cust.currentOrder.lineItems)
Hint: something like
SELECT cust.name, cust.address, cust.phone, cust.id, cust.current_orderFROM customers cust, stores store, locations loc, store_customers sc, product prodWHERE prod.name = 'widget' AND store.loc_id = loc.id AND loc.name IN ( 'Melbourne', 'Sydney' ) AND sc.store_id = store.id AND sc.cust_id = cust.id AND prod.id = ALL( SELECT item.prod_id FROM line_items item, orders o WHERE item.order_id = o.id AND cust.current_order = o.id )
The list returned by a query can be ordered by any property of a returned class or components:
from DomesticCat catorder by cat.name asc, cat.weight desc, cat.birthdate
The optionalasc ordesc indicate ascending or descending order respectively.
A query that returns aggregate values can be grouped by any property of a returned class or components:
select cat.color, sum(cat.weight), count(cat)from Cat catgroup by cat.color
select foo.id, avg(name), max(name)from Foo foo join foo.names namegroup by foo.id
Ahaving clause is also allowed.
select cat.color, sum(cat.weight), count(cat)from Cat catgroup by cat.colorhaving cat.color in (eg.Color.TABBY, eg.Color.BLACK)
SQL functions and aggregate functions are allowed in thehaving andorder by clauses if they are supported by the underlying database (i.e., not in MySQL).
select catfrom Cat cat join cat.kittens kittengroup by cat.id, cat.name, cat.other, cat.propertieshaving avg(kitten.weight) > 100order by count(kitten) asc, sum(kitten.weight) desc
Neither thegroup by clause nor theorder by clause can contain arithmetic expressions. Hibernate also does not currently expand a grouped entity, so you cannot writegroup by cat if all properties ofcat are non-aggregated. You have to list all non-aggregated properties explicitly.
For databases that support subselects, Hibernate supports subqueries within queries. A subquery must be surrounded by parentheses (often by an SQL aggregate function call). Even correlated subqueries (subqueries that refer to an alias in the outer query) are allowed.
from Cat as fatcatwhere fatcat.weight > ( select avg(cat.weight) from DomesticCat cat)
from DomesticCat as catwhere cat.name = some ( select name.nickName from Name as name)
from Cat as catwhere not exists ( from Cat as mate where mate.mate = cat)
from DomesticCat as catwhere cat.name not in ( select name.nickName from Name as name)
select cat.id, (select max(kit.weight) from cat.kitten kit)from Cat as cat
Note that HQL subqueries can occur only in the select or where clauses.
Note that subqueries can also utilizerow value constructor syntax. SeeSection 16.18, “Row value constructor syntax” for more information.
Hibernate queries can be quite powerful and complex. In fact, the power of the query language is one of Hibernate's main strengths. The following example queries are similar to queries that have been used on recent projects. Please note that most queries you will write will be much simpler than the following examples.
The following query returns the order id, number of items, the given minimum total value and the total value of the order for all unpaid orders for a particular customer. The results are ordered by total value. In determining the prices, it uses the current catalog. The resulting SQL query, against theORDER,ORDER_LINE,PRODUCT,CATALOG andPRICE tables has four inner joins and an (uncorrelated) subselect.
select order.id, sum(price.amount), count(item)from Order as order join order.lineItems as item join item.product as product, Catalog as catalog join catalog.prices as pricewhere order.paid = false and order.customer = :customer and price.product = product and catalog.effectiveDate < sysdate and catalog.effectiveDate >= all ( select cat.effectiveDate from Catalog as cat where cat.effectiveDate < sysdate )group by orderhaving sum(price.amount) > :minAmountorder by sum(price.amount) desc
What a monster! Actually, in real life, I'm not very keen on subqueries, so my query was really more like this:
select order.id, sum(price.amount), count(item)from Order as order join order.lineItems as item join item.product as product, Catalog as catalog join catalog.prices as pricewhere order.paid = false and order.customer = :customer and price.product = product and catalog = :currentCataloggroup by orderhaving sum(price.amount) > :minAmountorder by sum(price.amount) desc
The next query counts the number of payments in each status, excluding all payments in theAWAITING_APPROVAL status where the most recent status change was made by the current user. It translates to an SQL query with two inner joins and a correlated subselect against thePAYMENT,PAYMENT_STATUS andPAYMENT_STATUS_CHANGE tables.
select count(payment), status.namefrom Payment as payment join payment.currentStatus as status join payment.statusChanges as statusChangewhere payment.status.name <> PaymentStatus.AWAITING_APPROVAL or ( statusChange.timeStamp = ( select max(change.timeStamp) from PaymentStatusChange change where change.payment = payment ) and statusChange.user <> :currentUser )group by status.name, status.sortOrderorder by status.sortOrder
If thestatusChanges collection was mapped as a list, instead of a set, the query would have been much simpler to write.
select count(payment), status.namefrom Payment as payment join payment.currentStatus as statuswhere payment.status.name <> PaymentStatus.AWAITING_APPROVAL or payment.statusChanges[ maxIndex(payment.statusChanges) ].user <> :currentUsergroup by status.name, status.sortOrderorder by status.sortOrder
The next query uses the MS SQL ServerisNull() function to return all the accounts and unpaid payments for the organization to which the current user belongs. It translates to an SQL query with three inner joins, an outer join and a subselect against theACCOUNT,PAYMENT,PAYMENT_STATUS,ACCOUNT_TYPE,ORGANIZATION andORG_USER tables.
select account, paymentfrom Account as account left outer join account.payments as paymentwhere :currentUser in elements(account.holder.users) and PaymentStatus.UNPAID = isNull(payment.currentStatus.name, PaymentStatus.UNPAID)order by account.type.sortOrder, account.accountNumber, payment.dueDate
For some databases, we would need to do away with the (correlated) subselect.
select account, paymentfrom Account as account join account.holder.users as user left outer join account.payments as paymentwhere :currentUser = user and PaymentStatus.UNPAID = isNull(payment.currentStatus.name, PaymentStatus.UNPAID)order by account.type.sortOrder, account.accountNumber, payment.dueDate
HQL now supportsupdate,delete andinsert ... select ... statements. SeeSection 15.4, “DML-style operations” for more information.
You can count the number of query results without returning them:
( (Integer) session.createQuery("select count(*) from ....").iterate().next() ).intValue()To order a result by the size of a collection, use the following query:
select usr.id, usr.namefrom User as usr left join usr.messages as msggroup by usr.id, usr.nameorder by count(msg)
If your database supports subselects, you can place a condition upon selection size in the where clause of your query:
from User usr where size(usr.messages) >= 1
If your database does not support subselects, use the following query:
select usr.id, usr.namefrom User usr join usr.messages msggroup by usr.id, usr.namehaving count(msg) >= 1
As this solution cannot return aUser with zero messages because of the inner join, the following form is also useful:
select usr.id, usr.namefrom User as usr left join usr.messages as msggroup by usr.id, usr.namehaving count(msg) = 0
Properties of a JavaBean can be bound to named query parameters:
Query q = s.createQuery("from foo Foo as foo where foo.name=:name and foo.size=:size");q.setProperties(fooBean); // fooBean has getName() and getSize()List foos = q.list(); Collections are pageable by using theQuery interface with a filter:
Query q = s.createFilter( collection, "" ); // the trivial filterq.setMaxResults(PAGE_SIZE);q.setFirstResult(PAGE_SIZE * pageNumber);List page = q.list();
Collection elements can be ordered or grouped using a query filter:
Collection orderedCollection = s.filter( collection, "order by this.amount" );Collection counts = s.filter( collection, "select this.type, count(this) group by this.type" );
You can find the size of a collection without initializing it:
( (Integer) session.createQuery("select count(*) from ....").iterate().next() ).intValue(); Components can be used similarly to the simple value types that are used in HQL queries. They can appear in theselect clause as follows:
select p.name from Person p
select p.name.first from Person p
where the Person's name property is a component. Components can also be used in thewhere clause:
from Person p where p.name = :name
from Person p where p.name.first = :firstName
Components can also be used in theorder by clause:
from Person p order by p.name
from Person p order by p.name.first
Another common use of components is inSection 16.18, “Row value constructor syntax”.
HQL supports the use of ANSI SQLrow value constructor syntax, sometimes referred to AStuple syntax, even though the underlying database may not support that notion. Here, we are generally referring to multi-valued comparisons, typically associated with components. Consider an entity Person which defines a name component:
from Person p where p.name.first='John' and p.name.last='Jingleheimer-Schmidt'
That is valid syntax although it is a little verbose. You can make this more concise by usingrow value constructor syntax:
from Person p where p.name=('John', 'Jingleheimer-Schmidt') It can also be useful to specify this in theselect clause:
select p.name from Person p
Usingrow value constructor syntax can also be beneficial when using subqueries that need to compare against multiple values:
from Cat as catwhere not ( cat.name, cat.color ) in ( select cat.name, cat.color from DomesticCat cat)
One thing to consider when deciding if you want to use this syntax, is that the query will be dependent upon the ordering of the component sub-properties in the metadata.