08 Queries


Published on

Published in: Technology
  • Be the first to comment

  • Be the first to like this

No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide

08 Queries

  1. 1. Queries The Hibernate object-oriented query facilities
  2. 2. Hibernate query options <ul><li>The Hibernate Query Language (HQL): </li></ul><ul><li>The Criteria API for type-safe queries: </li></ul><ul><li>Direct SQL with Hibernate mapping: </li></ul>session. createQuery (&quot; from Category cat where cat.name like '%Flights' &quot;).list(); session. createCriteria (Category.class) .add( Expression.like(&quot;name&quot;, &quot;%Flights&quot;) ) .list(); session. createSQLQuery ( &quot; select {cat.*} from CATEGORY {cat} where NAME like '%Flights' &quot;, &quot;cat&quot;, Category.class) .list();
  3. 3. Executing queries <ul><li>We execute queries with the </li></ul><ul><ul><li>Query object from createQuery() and createSQLQuery() </li></ul></ul><ul><ul><li>Criteria object from createCriteria() </li></ul></ul><ul><li>Pagination: </li></ul><ul><li>Getting a list or results, or a single result: </li></ul><ul><li>Iterating: </li></ul>Query q = session.createQuery(&quot;from User user order by user.name asc&quot;) .setFirstResult(30) .setMaxResults(10) .list(); List result = q. list (); Object o = q.setMaxResults(1). uniqueResult (); Iterator it = q. iterate ();
  4. 4. Executing queries <ul><li>A ScrollableResults let’s us step through the query results, just like a JDBC scrollable ResultSet : </li></ul>ScrollableResults users = session.createQuery( &quot;from User user order by user.name asc&quot;) .scroll(); while ( users.next() ) { User user = results.get(0); … } users.close();
  5. 5. Binding parameters <ul><li>We should never use String manipulation: </li></ul><ul><li>We use named parameter binding : </li></ul><ul><li>Positional parameters are not recommended: </li></ul>String queryString = &quot;from Item i where i.description like '&quot; + string + &quot;'&quot;; List result = session.createQuery(queryString).list(); String queryString = &quot;from Item item &quot; + &quot;where item.description like :searchString &quot; + &quot;and item.date > :minDate &quot;; List result = session.createQuery(queryString) . setString (&quot;searchString&quot;, searchString ) . setDate (&quot;minDate&quot;, minDate ) .list(); String queryString = &quot;from Item item where item.description like ? &quot;; Query q = session.createQuery(queryString). setString ( 0 , searchString);
  6. 6. More parameter binding techniques <ul><li>Use setEntity() to bind a persistent entity: </li></ul><ul><li>Use setProperties() to bind properties of a JavaBean to several named parameters simultaneously: </li></ul><ul><li>Use setParameterList() to bind multiple values: </li></ul>session.createQuery(&quot;from Item item where item.seller = :seller&quot;) .setEntity(&quot;seller&quot;, seller) ; Item item = new Item(); item. setSeller (seller); item. setDescription (description); String queryString = &quot;from Item item &quot; + &quot;where item.seller = :seller and &quot; + &quot;item.description like :description &quot;; session.createQuery(queryString). setProperties (item).list(); session.createQuery(&quot;from Item item where item.id in (:idList)&quot;) .setParameterList(“idList&quot;, idList) ;
  7. 7. Externalizing named queries <ul><li>We can execute a named query : </li></ul><ul><li>The query is defined in the mapping metadata: </li></ul><ul><li>We can also name SQL queries: </li></ul>Query q = session.getNamedQuery(&quot; findItemsByDescription &quot;) .setString(&quot;description&quot;, description); <query name=&quot; findItemsByDescription &quot;><![CDATA[ from Item item where item.description like :description ]]></query> <sql-query name=&quot; findItemsByDescription &quot;><![CDATA[ select {item.*} from item where description like :description ]]> <return alias=&quot;item&quot; class=&quot;Item&quot;/> </sql-query>
  8. 8. Basic queries in HQL and with Criteria <ul><li>The simplest query: </li></ul><ul><li>Using an alias: </li></ul><ul><li>Polymorphic queries: </li></ul>from Bid from BillingDetails from CreditCard from java.lang.Object // Returns all persistent objects! from Bid as bid session.createCriteria(Bid.class) session.createCriteria(BillingDetails.class)
  9. 9. Restriction <ul><li>Restriction with a where clause in HQL: </li></ul><ul><li>Using a Criterion : </li></ul><ul><li>All regular SQL operators are supported in expressions: </li></ul>from User user where user.email = 'foo@hibernate.org' Criterion emailEq = Expression.eq(&quot;email&quot;, &quot;foo@hibernate.org); Criteria crit = session.createCriteria(User.class); crit.add( emailEq ); User user = (User) crit.uniqueResult(); from User user where user.email = 'foo@hibernate.org' and user.firstname like 'Max%' and user.lastname is not null or user.signupDate < :mondayLastWeek
  10. 10. String matching <ul><li>We can use wildcards for string pattern matching: </li></ul><ul><li>The Criteria API allows string matching without string manipulation: </li></ul><ul><li>We can also call arbitrary SQL functions in the where clause: </li></ul>from User user where user.firstname not like &quot; %Foo B% &quot; session.createCriteria(User.class) .add( Expression.like(&quot;firstname&quot;, &quot;G&quot;, MatchMode.START ) ); from User user where lower(user.email) = 'foo@hibernate.org' session.createCriteria(User.class) .add( Expression.eq(&quot;email&quot;, &quot;foo@hibernate.org&quot;). ignoreCase() ) );
  11. 11. Ordering results <ul><li>The order by clause is used in HQL: </li></ul><ul><li>The Criteria API also supports ordering of results: </li></ul><ul><li>HQL and the Criteria API give you all the power of SQL </li></ul><ul><li>without falling back to table and column names. </li></ul>from User user order by user.username desc List results = session.createCriteria(User.class) .addOrder( Order.asc (&quot;lastname&quot;) ) .addOrder( Order.asc (&quot;firstname&quot;) ) .list(); from Item item order by item.successfulBid.amount desc, item.id asc
  12. 12. Joining associations <ul><li>The join SQL operation combines the data from two tables: </li></ul>PRICE PRICE 3 Baz 1.00 NAME ITEM_ID 1 1 2 Foo Foo Bar 2.00 2.00 50.00 from ITEM I inner join BID B on I.ITEM_ID = B.ITEM_ID AMOUNT ITEM_ID BID_ID 1 2 3 1 1 2 10.00 20.00 55.00 NAME ITEM_ID 1 1 2 Foo Foo Bar 2.00 2.00 50.00 from ITEM I left outer join BID B on I.ITEM_ID = B.ITEM_ID AMOUNT ITEM_ID BID_ID 1 2 3 1 1 2 10.00 20.00 55.00 null null null
  13. 13. Fetching associations in Hibernate <ul><li>We can fetch associated objects in HQL: </li></ul><ul><li>For all Item s returned, the item.bids collection is fully initialized, </li></ul><ul><li>all with a single SQL outer join query. We may only fetch one collection in one HQL query, preserving performance in SQL. </li></ul><ul><li>We can also use a Criteria: </li></ul>from Item item left join fetch item.bids where item.description like '%gc%' session.createCriteria(Item.class) .setFetchMode(&quot;bids&quot;, FetchMode.EAGER) .add( Expression.like(&quot;description&quot;, &quot;gc&quot;, MatchMode.ANYWHERE) )
  14. 14. Fetching single-ended associations <ul><li>We can also initialize (fetch) single-ended associations: </li></ul><ul><li>IMPORTANT: HQL always ignores the outer-join setting in the mapping metadata, we have to use an explicit fetch join. The Criteria will not ignore the metadata, disable it with FetchMode.LAZY ! </li></ul>from Bid bid left join fetch bid.item left join fetch bid.bidder where bid.amount > 100 session.createCriteria(Bid.class) .setFetchMode(&quot;item&quot;, FetchMode.EAGER) .setFetchMode(&quot;bidder&quot;, FetchMode.EAGER) .add( Expression.gt(&quot;amount&quot;, new Float(100) ) )
  15. 15. Using aliases with joins <ul><li>We need an alias to express restrictions on joined objects: </li></ul><ul><li>This query returns ordered pairs of Items and Bids: </li></ul><ul><li>The select clause is optional: </li></ul>from Item item join item.bids bid where item.description like '%gc%' and bid .amount > 100 Query q = session.createQuery(&quot; from Item item join item.bids bid &quot;); Iterator pairs = q.list().iterator(); while ( pairs.hasNext() ) { Object[] pair = (Object[]) pairs.next(); Item item = (Item) pair[0]; Bid bid = (Bid) pair[1]; } select item from Item item join item.bids bid where bid.amount > 100
  16. 16. Using implicit association joins <ul><li>We can query components (dereference with a dot): </li></ul><ul><li>We can join single-ended associations implicitly: </li></ul><ul><li>We have to be careful (how many SQL joins is this?): </li></ul>from User user where user . address . city = 'Bangkok' from Bid bid where bid . item . description like '%gc%' from Bid bid where bid.item.category.name like 'Laptop%' from Bid bid where bid.item.category.name like 'Laptop%' and bid.item.successfulBid.amount > 100
  17. 17. Theta-style joins <ul><li>First, we create a Cartesian Product: </li></ul><ul><li>Then, we add a join condition in the where clause: </li></ul><ul><li>Theta-style (inner) joins are used when related tables (classes) are not referenced with a foreign key relationship (no automatic joining). </li></ul>from User, LogRecord from User user, LogRecord log where user.username = log.username
  18. 18. Report queries in HQL <ul><li>The select clause is used for projection: </li></ul><ul><li>The result may be an Object[] of non-transactional objects: </li></ul><ul><li>Dynamic instantiation is much easier to handle: </li></ul>select item from Item item join item.bids bid where bid.amount > 100 select item.id, item.description, bid.amount from Item item join item.bids bid where bid.amount > 100 select new ItemRow ( item.id, item.description, bid.amount ) from Item item join item.bids bid where bid.amount > 100
  19. 19. Aggregation in HQL <ul><li>The aggregation functions are </li></ul><ul><ul><li>count() , min() , max() , sum() and avg() </li></ul></ul><ul><li>Count all items with a successful bid: </li></ul><ul><li>The total of all successful bids: </li></ul><ul><li>The result is an ordered pair of Float s: </li></ul>select count (item.successfulBid) from Item item select sum (item.successfulBid.amount) from Item item select min (bid.amount), max (bid.amount) from Bid bid where bid.item.id = 1
  20. 20. Grouping in HQL <ul><li>If we aggregate, we have to group every property in the select : </li></ul><ul><li>We can further restrict the result on the group: </li></ul><ul><li>Use report queries (projection, aggregation, grouping, dynamic instantiation) to optimize performance, only retrieve required data. </li></ul>select bid.item.id , avg(bid.amount) from Bid bid group by bid.item.id select item.id , count(bid) ), avg(bid.amount) from Item item join item.bids bid where item.successfulBid is null group by item.id having count(bid) > 10
  21. 21. Dynamic queries with Query By Example <ul><li>Complex searches are best expressed with a QBE query: </li></ul><ul><li>QBE can be combined with QBC: </li></ul>User exampleUser = new User(); exampleUser.setFirstname (&quot;Max&quot;); exampleUser.setEmail (&quot;@hibernate.org&quot;); List result = findUsers( exampleUser ); public List findUsers(User user) throws HibernateException { return getSession().createCriteria(User.class) .add( Example.create(user) .ignoreCase().enableLik (MatchMode.ANYWHERE) ) .list(); } createCriteria(User.class) .add( Example.create(user) .ignoreCase().enableLike(MatchMode.ANYWHERE) ) . createCriteria(&quot;items&quot;) .add( Expression.isNull(&quot;successfulBid&quot;) );
  22. 22. Filtering persistent collections <ul><li>We can filter the collection of bids of an already loaded Item : </li></ul><ul><li>HQL filter queries have an implicit from and where clause: </li></ul><ul><li>A filter doesn't have to return objects from the collection: </li></ul>Query q = session.createFilter ( item.getBids() , &quot;order by this .amount asc&quot; ); Query q = session.createFilter( item.getBids(), &quot;&quot; ); // This is valid... List result = q.setFirstResult(50).setMaxResults(100).list() // and useful! List results = session.createFilter( item.getBids(), &quot;select elements (this.bidder.bids)&quot; ).list()
  23. 23. Subqueries in HQL <ul><li>Correlated subquery, total items sold by users, if more than 10: </li></ul><ul><li>Uncorrelated subquery, all bids that are 1 within the maximum: </li></ul><ul><li>We can use SQL quantifiers, ANY / ALL / SOME / IN: </li></ul>from User user where 10 < ( select count(item) from user.items where item.successfulBid is not null ) from Bid bid where bid.amount + 1 >= ( select max(b.amount) from Bid b ) from Item item where 100 > all ( select b.amount from item.bids b ) from Item item where 100 < any ( select b.amount from item.bids b ) from Item item where 100 = some ( select b.amount from item.bids b ) from Item item where 100 in ( select b.amount from item.bids b )
  24. 24. Native SQL queries <ul><li>Direct native SQL queries use Hibernate shortcuts: </li></ul><ul><li>We can return Object[] s (tuples): </li></ul><ul><li>We can externalize SQL queries to the mapping file: </li></ul>List results = session.createSQLQuery(&quot;select {uzer.*} from user uzer&quot;, &quot; uzer &quot;, User.class ).list(); List tuples = session.createSQLQuery( &quot;select {u.*}, {b.*} from user u inner join bid b where u.id = b.bidder_id&quot;, new String[] { &quot;u&quot;, &quot;b&quot; }, new Class[] {User.class, Bid.class} ).list(); <sql-query name=&quot;findUsersAndBids&quot;><![CDATA[ select {u.*}, {b.*} from user u inner join bid b where u.id = b.bidder_id ]]> <return alias=&quot;u&quot; class=&quot;User&quot;/> <return alias=&quot;b&quot; class=&quot;Bid&quot;/> </sql-query>