miércoles, enero 05, 2011

JPA2 is present in major ORM vendors (EclipseLink, Hibernate, OpenJPA). Main features are present like multiple levels of embedded objects, ordered lists, support for validation, new criteria query API.

Now it time to talk (with an example) about new criteria query API. For this example I will use Hibernate and its Hibernate Metamodel Generator.

New Criteria API allows criteria queries to be constructed in a strongly-typed manner, using metamodel objects to provide type safety. As is mentioned in Hibernate site: "For developers it is important that the task of the metamodel generation can be automated".

And that's is what Hibernate Metamodel Generator does. This metamodel generator is an annotation processor that is run each time an annotated @Entity bean is compiled, and generates its metamodel class.

Easy to understand, each persistent attribute has its type and which entity belongs. For example field "name" belongs to Pizza and is a "String", and thats so important because precisely that will allow Criteria API to be typesafely.

Ok, now we know that new Criteria API is typesafely and this is acquired with metamodel programming. How about starting from the start?

First of all is configuring Eclipse for compiling using Annotation Processor (in Hibernate site is explained for using in other IDEs or Maven).

Only configure annotations processor output directory and which annotation processor is required, in our case hibernate-jpamodelgen and hibernate-jpa-2.0.

Nothing different here. Same is applied for Ingredient entity (not showed here).

But wait go to target/metamodel, refresh the directory and what you see there? The metamodel classes. Ok if you have arrived successful here, then no problem you have done the complicated thing. Now let's write our first new Criteria query.

This method returns all pizzas that are produced with given ingredient. If you analyze line per line, first of all is created the query about pizza, then is created the join relationship ingredientsNode and "woop" metamodel class starts the game, we are making a join with Pizza_.ingredients, this is the representation of ingredients class. Also we are telling to filter ingredients where the name is the given one criteriaBuilder.equal(ingredientsNode.get(Ingredient_.name), ingredient), and you see that Ingredient_.name is used. This information is crucial because we are telling to Criteria API that the field is the one defined as Ingredient.name. If name attribute is deleted, metamodel class is modified too and our code does not compile.

Take a look the same criteria query but in Hibernate Criteria:

Criteria criteria = session.createCriteria(Pizza.class);

criteria.createAlias("ingredients", "i")

.add(Restrictions.eqProperty("id", "i.pizza"))

.add(Restrictions.eq("i.name", ingredient));

return (List)criteria.list();

For me it is easy to understand first one than second one, it is like more natural, and does not required any cast.

In Hibernate site more examples of new Criteria API can be found. I encourage you to start using JPA2, not only for new Criteria API but for using all new features.