Saturday 17 August 2013

JPA Named Query




Using named queries instead of dynamic queries may improve code organization by separating the JPQL query strings from the Java code. It also enforces the use of query parameters rather than embedding literals dynamically into the query string and results in more efficient queries.  

 A named query is a predefined query that you create and associate with a container-managed entity. At deployment time, server stores named queries on the EntityManager. At run time, you can use the EntityManager to acquire, configure, and execute a named query.


@NamedQuery and @NamedQueries Annotations 

The following @NamedQuery annotation defines a query whose name is findAllUser and retrieves User object which will have all user details. 

@NamedQuery(name="findAllUser", query="SELECT OBJECT(user) FROM User user")

The @NamedQuery annotation contains four elements - two of which are required and two are optional. The two required elements, name and query define the name of the query and the query string itself and are demonstrated above. The two optional elements, lockMode and hints, provide static replacement for the setLockMode and setHint methods.

It makes sense to add the above @NamedQuery to the User entity class: 

@NamedQuery(name="findAllUser", query="SELECT OBJECT(user) FROM User user")
public class User {
  ...
}

You can attach multiple named queries to the same entity class requires wrapping them in a @NamedQueries annotation, as follows: 

@NamedQueries({
    @NamedQuery(name="findAllUser",
               query="SELECT OBJECT(user) FROM User user"),
    @NamedQuery(name="findAllStatus",
                query="SELECT s FROM Status s WHERE s.name = :name"),
})
public class User {
  ...
}


Note: Named queries can be defined in JPA XML mapping files instead of using the @NamedQuery annotation. ObjectDB supports JPA XML mapping files, including the definition of named queries. But, because mapping files are useful mainly for Object Relational Mapping (ORM) JPA providers and less so when using ObjectDB, this alternative is not covered in this manual.

Using Named Queries at Runtime

Named queries are represented at runtime by the same Query and TypedQuery interfaces but different EntityManager factory methods are used to instantiate them. The createNamedQuery method receives a query name and a result type and returns a TypedQuery instance: 

  TypedQuery<User> query =
      em.createNamedQuery("findAllUser", User.class);
  List<User> results = query.getResultList();

Implementing a Query With Parameters Using @NamedQuery

You can pass the parameters at runtime by the same @NamedQuery using following method

@Entity
@NamedQuery(
    name="findAllEmployeesByFirstName",
    queryString="SELECT OBJECT(emp) FROM Employee emp WHERE emp.firstName = :firstname"
)
public class Employee implements Serializable {
...
}
 
Setting Parameters in a Named Query  
Query queryEmployeesByFirstName = em.createNamedQuery("findAllEmployeesByFirstName");
queryEmployeeByFirstName.setParameter("firstName", "John");
Collection employees = queryEmployessByFirstName.getResultList();

Happy Coding.