12.07.2015 Views

Beginning Java EE 6 with GlassFish 3, Second Edition

Beginning Java EE 6 with GlassFish 3, Second Edition

Beginning Java EE 6 with GlassFish 3, Second Edition

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

CHAPTER 4 ■ MANAGING PERSISTENT OBJECTSSELECT c FROM Customer c WHERE c.firstName = 'Vincent'This JPQL statement is rewritten in Listing 4-30 in an object-oriented way using the new CriteriaAPI:Listing 4-30. A Criteria Query Selecting All the Customers Named VincentCriteriaBuilder builder = em.getCriteriaBuilder();CriteriaQuery query = builder.createQuery(Customer.class);Root c = query.from(Customer.class);query.select(c).where(builder.equal(c.get("firstName"), "Vincent"));Without going into too much detail, you can see that the SELECT, FROM and WHERE keywords have anAPI representation through the methods select(), from() and where(). And this rule applies for everyJPQL keyword. Criteria queries are constructed through the CriteriaBuilder interface that is obtainedby the EntityManager (the em attribute in Listings 4-30 and 4-31). It contains methods to construct thequery definition (this interface defines keywords such as desc(), asc(), avg(), sum(), max(), min(),count(), and(), or(), greaterThan(), lowerThan()…). The other role of the CriteriaBuilder is to create aCriteriaQuery. This interface defines methods such as select(), from(), where(), orderBy(), groupBy(),and having(), which have the equivalent meaning in JPQL. In Listing 4-30, the way you get the alias c (asin SELECT c FROM Customer) is through the Root interface (Root c). Then you just have to usethe builder, the query and the root to write any JPQL statement you want: from the simplest (select allthe entities from the database) to the most complex (joins, subqueries, case expressions, functions…).Let’s take another example. Listing 4-31 shows a query that retrieves all the customers older than 40.The c.get("age") gets the attribute age from the Customer entity and checks if it’s greater than 40.Listing 4-31. A Criteria Query Selecting All the Customers Older than 40CriteriaBuilder builder = em.getCriteriaBuilder();CriteriaQuery query = builder.createQuery(Customer.class);Root c = query.from(Customer.class);query.select(c).where(builder.greaterThan(c.get("age").as(Integer.class), 40));I started this section saying the Criteria API allows you to write error-prone statements. But it’s notcompletely true yet. When you look at Listings 4-30 and 4-31, you can still see some strings ("firstName"and "age") that represent the attributes of the Customer entity. So typos can still be made. In Listing 4-31,we still need to cast the age into an Integer (c.get("age").as(Integer.class)) because there is no otherway to discover that the age attribute is of type Integer. To solve these problems, the Criteria API comes<strong>with</strong> the idea of a static meta-model class for each entity bringing type safety to the API.Type-Safe Criteria APIListings 4-30 and 4-31 are almost type safe: each JPQL keyword can be represented by a method of theCriteriaBuilder and CriteriaQuery interface. The only missing part is the attributes of the entity thatare string-based: the way to refer to the customer’s firstName attribute is by calling c.get("firstName").The get method takes a String as a parameter. Type-safe Criteria API solves this by overriding thismethod <strong>with</strong> a path expression from the meta-model API classes bringing type safety.Listing 4-32 shows the Customer entity <strong>with</strong> several attributes of different type (Long, String, Integer,Address).159

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!