10.5. Querying
10.5.1. About Querying Copy linkLink copied to clipboard!
Copy linkLink copied to clipboard!
If you do not know the identifiers of the objects you are looking for, you need a query. Hibernate supports an easy-to-use but powerful object oriented query language (HQL). For programmatic query creation, Hibernate supports a sophisticated Criteria and Example query feature (QBC and QBE). You can also express your query in the native SQL of your database, with optional support from Hibernate for result set conversion into objects.
10.5.2. Executing Queries Copy linkLink copied to clipboard!
Copy linkLink copied to clipboard!
HQL and native SQL queries are represented with an instance of
org.hibernate.Query
. This interface offers methods for parameter binding, result set handling, and for the execution of the actual query. You always obtain a Query
using the current Session
:
A query is usually executed by invoking
list()
. The result of the query will be loaded completely into a collection in memory. Entity instances retrieved by a query are in a persistent state. The uniqueResult()
method offers a shortcut if you know your query will only return a single object. Queries that make use of eager fetching of collections usually return duplicates of the root objects, but with their collections initialized. You can filter these duplicates through a Set
.
10.5.3. Iterating Results Copy linkLink copied to clipboard!
Copy linkLink copied to clipboard!
Occasionally, you might be able to achieve better performance by executing the query using the
iterate()
method. This will usually be the case if you expect that the actual entity instances returned by the query will already be in the session or second-level cache. If they are not already cached, iterate()
will be slower than list()
and might require many database hits for a simple query, usually 1 for the initial select which only returns identifiers, and n additional selects to initialize the actual instances.
10.5.4. Queries that Return Tuples Copy linkLink copied to clipboard!
Copy linkLink copied to clipboard!
Hibernate queries sometimes return tuples of objects. Each tuple is returned as an array:
10.5.5. Scalar Results Copy linkLink copied to clipboard!
Copy linkLink copied to clipboard!
Queries can specify a property of a class in the
select
clause. They can even call SQL aggregate functions. Properties or aggregates are considered "scalar" results and not entities in persistent state.
10.5.6. Bind Parameters Copy linkLink copied to clipboard!
Copy linkLink copied to clipboard!
Methods on
Query
are provided for binding values to named parameters or JDBC-style ?
parameters. Contrary to JDBC, Hibernate numbers parameters from zero. Named parameters are identifiers of the form :name
in the query string. The advantages of named parameters are as follows:
- named parameters are insensitive to the order they occur in the query string
- they can occur multiple times in the same query
- they are self-documenting
//named parameter (preferred) Query q = sess.createQuery("from DomesticCat cat where cat.name = :name"); q.setString("name", "Fritz"); Iterator cats = q.iterate();
//named parameter (preferred)
Query q = sess.createQuery("from DomesticCat cat where cat.name = :name");
q.setString("name", "Fritz");
Iterator cats = q.iterate();
//positional parameter Query q = sess.createQuery("from DomesticCat cat where cat.name = ?"); q.setString(0, "Izi"); Iterator cats = q.iterate();
//positional parameter
Query q = sess.createQuery("from DomesticCat cat where cat.name = ?");
q.setString(0, "Izi");
Iterator cats = q.iterate();
10.5.7. Pagination Copy linkLink copied to clipboard!
Copy linkLink copied to clipboard!
If you need to specify bounds upon your result set, that is, the maximum number of rows you want to retrieve and/or the first row you want to retrieve, you can use methods of the
Query
interface:
Query q = sess.createQuery("from DomesticCat cat"); q.setFirstResult(20); q.setMaxResults(10); List cats = q.list();
Query q = sess.createQuery("from DomesticCat cat");
q.setFirstResult(20);
q.setMaxResults(10);
List cats = q.list();
Hibernate knows how to translate this limit query into the native SQL of your DBMS.
10.5.8. Scrollable Iteration Copy linkLink copied to clipboard!
Copy linkLink copied to clipboard!
If your JDBC driver supports scrollable
ResultSet
s, the Query
interface can be used to obtain a ScrollableResults
object that allows flexible navigation of the query results.
Note that an open database connection and cursor is required for this functionality. Use
setMaxResult()
/setFirstResult()
if you need offline pagination functionality.
10.5.9. Externalizing Named Queries Copy linkLink copied to clipboard!
Copy linkLink copied to clipboard!
You can also define named queries in the mapping document. Remember to use a
CDATA
section if your query contains characters that could be interpreted as markup.
<query name="ByNameAndMaximumWeight"><![CDATA[ from eg.DomesticCat as cat where cat.name = ? and cat.weight > ? ] ]></query>
<query name="ByNameAndMaximumWeight"><![CDATA[
from eg.DomesticCat as cat
where cat.name = ?
and cat.weight > ?
] ]></query>
Parameter binding and executing is done programatically:
Query q = sess.getNamedQuery("ByNameAndMaximumWeight"); q.setString(0, name); q.setInteger(1, minWeight); List cats = q.list();
Query q = sess.getNamedQuery("ByNameAndMaximumWeight");
q.setString(0, name);
q.setInteger(1, minWeight);
List cats = q.list();
The actual program code is independent of the query language that is used. You can also define native SQL queries in metadata, or migrate existing queries to Hibernate by placing them in mapping files.
Also note that a query declaration inside a
<hibernate-mapping>
element requires a global unique name for the query, while a query declaration inside a <class>
element is made unique automatically by prepending the fully qualified name of the class. For example eg.Cat.ByNameAndMaximumWeight
.
10.5.10. Filtering Collections Copy linkLink copied to clipboard!
Copy linkLink copied to clipboard!
A collection filter is a special type of query that can be applied to a persistent collection or array. The query string can refer to
this
, meaning the current collection element.
The returned collection is considered a bag that is a copy of the given collection. The original collection is not modified. This is contrary to the implication of the name "filter", but consistent with expected behavior.
Observe that filters do not require a
from
clause, although they can have one if required. Filters are not limited to returning the collection elements themselves.
Collection blackKittenMates = session.createFilter( pk.getKittens(), "select this.mate where this.color = eg.Color.BLACK.intValue") .list();
Collection blackKittenMates = session.createFilter(
pk.getKittens(),
"select this.mate where this.color = eg.Color.BLACK.intValue")
.list();
Even an empty filter query is useful, e.g. to load a subset of elements in a large collection:
Collection tenKittens = session.createFilter( mother.getKittens(), "") .setFirstResult(0).setMaxResults(10) .list();
Collection tenKittens = session.createFilter(
mother.getKittens(), "")
.setFirstResult(0).setMaxResults(10)
.list();
10.5.11. Criteria Queries Copy linkLink copied to clipboard!
Copy linkLink copied to clipboard!
HQL is extremely powerful, but some developers prefer to build queries dynamically using an object-oriented API, rather than building query strings. Hibernate provides an intuitive
Criteria
query API for these cases:
Criteria crit = session.createCriteria(Cat.class); crit.add( Restrictions.eq( "color", eg.Color.BLACK ) ); crit.setMaxResults(10); List cats = crit.list();
Criteria crit = session.createCriteria(Cat.class);
crit.add( Restrictions.eq( "color", eg.Color.BLACK ) );
crit.setMaxResults(10);
List cats = crit.list();
10.5.12. Queries in Native SQL Copy linkLink copied to clipboard!
Copy linkLink copied to clipboard!
You can express a query in SQL, using
createSQLQuery()
and let Hibernate manage the mapping from result sets to objects. You can at any time call session.connection()
and use the JDBC Connection
directly. If you choose to use the Hibernate API, you must enclose SQL aliases in braces:
List cats = session.createSQLQuery("SELECT {cat.*} FROM CAT {cat} WHERE ROWNUM<10") .addEntity("cat", Cat.class) .list();
List cats = session.createSQLQuery("SELECT {cat.*} FROM CAT {cat} WHERE ROWNUM<10")
.addEntity("cat", Cat.class)
.list();
SQL queries can contain named and positional parameters, just like Hibernate queries. .