The Java Persistence APIs allow the creation of named queries for these predefined queries. The Query APIs allow the code to use these named queries. You can use a named query whenever you have a query that you run several times and just set parameters for. These are often called static queries. You can do this for all your pre-defined queries.
Using the Named queries is a good practice for the following reasons:
Named queries are thread-safe as they are meant to be reused by many classes and instances. Note that the names of named queries are scoped and it is important to avoid name clashes. When annotations are used to define named queries, the scope of the name is visible within a persistent unit. You can use the deployment descriptor to make the names visible at application scope. When using a named query in code, we use a naming convention of prefixing the class name of the class where the named queries are defined in front of the query name.
Named queries can only be defined on certain classes. They must be defined and placed only on entities and mapped superclasses.
Note that the named queries can be used for native SQL queries as well as for queries expressed in the Java Persistence query language.
Code Before | Code After using Named Queries |
public class MyDataFacade ... { query.setParameter
("cID",catID);
List<Item> items =
query.getResultList(); Note that this code could put the query into a string constant but still its not pre-compiled. |
Note the annotation is used on the class:
@NamedQuery( MyEntity. getItemsPerProductCategory",
public class MyDataFacade ... { private EntityManager em; public
List<Items> getItems(String catID) { |
As can be noted from the example above, it is relatively simple to refactor code to use a named query.
One minor
design choice for named queries is whether to use positional parameters
or named parameters. Named parameters are preferred as it makes the
code easier to understand and maintain. The example code above shows a
named query using a named parameter ":cID
" with query="SELECT i
FROM Item i WHERE i.product.categoryID LIKE
:cID
"
which is then set by calling query.setParameter("cID",catID)
.
Its clean and easy.
NamedQueries
annotation to create a list of all the named queries used in a class.
Here is an example of how it is used. Note that the annotation is
used on the class:
@NamedQueries(
{
@NamedQuery(
name="MyEntity.getItemsPerProductCategory",
query="SELECT i FROM Item i WHERE i.productID.categoryID LIKE :cID"
),
@NamedQuery(
name="MyEntity.getAllZipCityState",
query="SELECT z FROM ZipLocation z"
)
}
)
@Entity
public class MyEntity {...
Then your code can just use the each named query in the usual way,
Its fairly simple, though the syntax of listing the named queries is somewhat non-intuitive at first.public class MyDataFacade ... {
...
Query query = em.createNamedQuery("MyEntity.getItemsPerProductCategory");
NamedQuery
NamedQueries