Java Persistence Architecture 2.0 - Using The New TypedQuery Interface

Introduction

This is a continuation of articles on new features of JPA 2.0, which I'm studying because my programming team may adopt it as our standard for ORM. Another new feature provided by JPA 2.0 is TypedQuery. A TypedQuery is a JPA query that returns a specific type of Object. TypedQuery eliminates the need to cast the query result to a specific type or having to add a SuppressWarnings annotation to eliminate compiler warnings about unchecked conversions. TypedQuery is also used with the new JPA 2.0 CriteriaBuilder. Since some of the newer books and articles on JPA still only show the Query interface and don't mention the TypedQuery interface I thought a blog article and example application might be useful to others who are learning JPA 2.0.

Example Application

You can download the example application, which is a zipped Maven project. The example was created using Eclipse 3.6 and the m2eclipse Maven plugin. It is a standard Maven project, so if you're not using Eclipse you should be able to import (after unzipping the download) the project into any Maven aware Java IDE. If you don't have a Maven aware Java IDE you can view the source code in any text editor.

The example application uses HyperSQL to create an in-memory database for storing the project's entities.

After importing the project into your Java IDE, the domain classes--Applicant and Skill--are in package name.brucephillips.typedqueryexample.domain (under src/main/java). There is a JUnit 4 test of these classes, including an example of using TypedQuery, in src/test/java.

The persistence.xml file is found in src/main/resources META-INF folder. For this example application I used Hibernate as the JPA provider.

To run the example application's tests you must have Maven installed. Open a terminal (command) window and navigate to the unzipped project's root folder (TypedQueryExample) where the pom.xml file is located. Enter this Maven command to run the test.



mvn -e clean test

TypedQuery Interface

If you examine the TypedQueryTest class (in src/test/java) you'll find this code:



    @Test
    public void testTypedQuery() {
        
        EntityManager entityManager = entityManagerFactory.createEntityManager();        
        
        //Query querySkill = entityManager.createNamedQuery("skill.findBySkill");
        
        TypedQuery<Skill> querySkill = entityManager.createNamedQuery("skill.findBySkill", Skill.class);
        
        querySkill.setParameter("skill", "Oracle");
        
        //Skill skill = (Skill) querySkill.getSingleResult() ;
        
        Skill skill = querySkill.getSingleResult();
        
        //Query query = entityManager.createQuery("select a FROM Applicant a join a.skills s where s.id = :skillId ");
        
        TypedQuery<Applicant> query = entityManager.createQuery("select a FROM Applicant a join a.skills s where s.id = :skillId ", Applicant.class);
        
        query.setParameter( "skillId", skill.getId() );
        
     List<Applicant> applicants = query.getResultList();
        
        assertTrue("The number of applicants with Oracle skill is not 2 but should be.", applicants.size() == 2);
        
        
    }

This method demonstrates two uses of the TypedQuery interface to create a Query that will return a specific type of Object. I first use the EntityManager method createNamedQuery, which in JPA 2.0, was over-loaded to include a signature that has two parameters: String and Class<T>. The second argument is used to specify that the query should return the Objects as that Class type. This overloaded version of createNamedQuery returns a TypedQuery<T>. So in my example above the call to querySkill.getSingleResult will return a Skill object since I specified Skill.class as the second argument to createNamedQuery.

If I had used the Query interface instead of TypedQuery (see the commented out statements above) then when I called queryKill.getSingleResult I would need to cast the result to the specific type (in this case Skill).

The second example of using TypedQuery in the code above uses the over-loaded createQuery method that takes two arguments String and Class<T>. Using TypedQuery here prevents the unchecked conversion compiler warning when I call query.getResultList.

TypedQuery and Criteria Queries

JPA 2 also introduced criteria queries, which provide a means to create type-safe, object-based queries. In class TypedQueryTest is this method:



    @Test
    public void testTypedQueryWithCriteria() {
        
        EntityManager entityManager = entityManagerFactory.createEntityManager();
        
        CriteriaBuilder cb = entityManager.getCriteriaBuilder();
        
        CriteriaQuery<Applicant> cq = cb.createQuery(Applicant.class);
        
        cq.from(Applicant.class);
        
        TypedQuery<Applicant> typedQuery = entityManager.createQuery(cq);
        
        List<Applicant> applicants = typedQuery.getResultList();
        
        assertTrue("Two applicants were not found by the Criteria query but should have been.", applicants.size() == 2);
        
    }

The above method uses EntityManager and CriteriaBuilder to create a TypedQuery object to ensure that the query results are typed as Applicant objects. The combination of TypedQuery and CriteriaBuilder provide compile time checking of the query syntax and type safety.

Summary

JPA 2.0 added TypedQuery and over-loaded methods of EntityManager that allow you to specify the query result type. TypedQuery simplifies using the JPA EntityManager query methods by eliminating the need to cast query results to a specific type or to add SuppressWarnings annotations to remove compiler warnings. TypedQuery is also used when creating criteria queries.

References

Package javax.persistence Java Documentation
http://download.oracle.com/javaee/6/api/javax/persistence/TypedQuery.html
http://download.oracle.com/javaee/6/api/javax/persistence/criteria/CriteriaBuilder.html
Accessed November 2010

Java Persistence with JPA, Daoqi Yang, Outskirts Press, 2010, Chapters 3, 5, and 7

Comments (Comment Moderation is enabled. Your comment will not appear until approved.)
BlogCFC was created by Raymond Camden. This blog is running version 5.9.1.002. Contact Blog Owner