Friday, January 8, 2010

Section 8.6. Property-Oriented Criteria Factories








8.6. Property-Oriented Criteria Factories


We've already seen that there is often more than one way to
express what you want using the criteria API,
depending on your stylistic preferences, or the way you think about
things. The Property class offers another bunch of
alternatives of which you should be aware. We will not explore this class
in depth because it is just another way of setting up criteria, but it is
important to explain how it works, so you won't be confused if you run
across examples, or feel baffled while scanning Hibernate's dense JavaDoc.
(And, frankly, after one or two examples, you'll undoubtedly get the idea
well enough that you may decide to adopt this approach yourself.)


Property is another factory for
criteria, much like Restrictions, which we've
been using in this chapter (and Order and
Projection, for that matter). You can create
essentially all the query refinements available with those other factories
by using Property instead. Rather than starting
with the kind of constraint in which you're interested, and then naming
the property to which you want to apply it, you instead start with the
property and pick a constraint.


NOTE


Enough abstraction! Show some examples!



As before, you start by creating Criteria on
the object you want to query. But instead of saying, for example:


criteria.add(Restrictions.le("playTime", length));



you can say:


criteria.add(Property.forName("playTime").le(length));



It's really very similar—just a slightly different emphasis—as when
you have more than one way to phrase the same concept in English. There
are a bunch of methods in Property that give you
criteria, orderings, and projections. You can't construct a Property instance using
new⁠⁠(⁠ ⁠)—you need to either start with
the forName⁠⁠(⁠ ⁠) static factory, or
use an existing Property instance and call
getProperty⁠⁠(⁠ ⁠) on it to traverse to one of its
component properties.


Here are a few more examples to show how this approach fits in.
Where we had used statements like:


criteria.addOrder(Order.asc("name").ignoreCase());



we could instead have used:


criteria.addOrder(Property.forName("name").asc().ignoreCase());



And with projections, the approach we'd followed, such as:


criteria.setProjection(Projections.max("playTime"));



could equally well have been expressed as:


criteria.setProjection(Property.forName("playTime").max());



NOTE


This is almost an embarrassment of riches!



So, take your pick. Sometimes the kind of problem you're solving, or
the thrust of the rest of the code, will evoke one style or the other. Or
perhaps you'll just like one better and stick with it. But at least you're
now aware you might run into both, and should be able to understand any
criteria expression. These factory methods are all summarized in Appendix B.


Overwhelmed with options yet? No? Well, when criteria queries don't
quite do the job, or you want an even more extreme alternative to all the
choices you've seen in this chapter—especially if you're comfortable with
the concision of SQL—you can turn to the full power of
HQL. We investigate that in the next chapter.



8.6.1. What about…


…sneaking a little SQL in with your other
criteria to take advantage of database-specific features or your mad
DBA skillz? Using subqueries, or detached criteria
that can be set up before you have a Hibernate session? Plugging in your
own Java code to filter the results as the query is performed? All of
these things and more are possible, but beyond the scope of this book.
If you're ready for them, the Advanced query
options
chapter in Java
Persistence with Hibernate
is a good overview,
and the Hibernate JavaDoc and source code are the definitive
references.










No comments: