Problem Description
When designing code that will access that you stored in relational tables, the code will need to create queries. Some of the queries are constructed dynamically, and other queries are static. These static queries can take parameters but the query stays the same. As your application gets larger, the code can have a lot of queries and this can get difficult to manage.
Solution
Many of persistace frameworks including Hibernate, iBatis, JPA, ...etc allow the creation of named queries for these predefined 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:
An advantage of named queries is that the Persistence provider might be able to precompile them
Pre-compiling of queries is useful because it can help to find bugs before deployment
Using named queries helps separate the query string from the code using it, so can help clean up your code. Otherwise, you may end up retyping the query in different places that use it in the code. Code not using named queries often puts the query strings into a String constants for reuse, but these are not pre-compiled like named queries are.
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 descriptor or hbm file 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.
Practical Aspect of using Named queries
Suppose need arises to use these notations/operators along with Hibernate
named query in hbm XML file. In that case one has to use CDATA along with
the named query in HBM file.
Using an example you might have seen already in one of the examples on
Hibernate:
Employee and Department sharing many to one type of association mapping
with one another.
This example uses following software environment:
1. JDK 5.0
2. Eclipse 3.4.x
3. Hibernate 3.2
4. MyQL 5.0
Java POJO for this example is Employee.java
Employee.java
---------------------------------------------------------
package test.hibernate.namedqueries;
import java.io.Serializable;
public class Address extends Contact implements Serializable {
private long id;
private String employeeName;
private String addrLine1;
private String addrLine2;
private String addrLine3;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getEmployeeName() {
return employeeName;
}
public void setEmployeeName(String employeeName) {
this. employeeName = employeeName;
}
public String getAddrLine1() {
return addrLine1;
}
public void setAddrLine1(String addrLine1) {
this.addrLine1 = addrLine1;
}
public String getAddrLine2() {
return addrLine2;
}
public void setAddrLine2(String addrLine2) {
this.addrLine2 = addrLine2;
}
public String getAddrLine3() {
return addrLine3;
}
public void setAddrLine3(String addrLine3) {
this.addrLine3 = addrLine3;
}
}
---------------------------------------------------------
Hibernate configuration file for creating Hibernate SessionFactory is as follows:
hibernate.cfg.xml
---------------------------------------------------------
---------------------------------------------------------
The named query is defined in the Employee.hbm.xml file:
Employee.hbm.xml
---------------------------------------------------------
< hibernate-mapping package="demo.profile" >
< class name="Address" table="Address" >
< id name="id" column="employee_id" >
< property name="employeeName" column="Emp_Name" >
< property name="addrLine1" column="address_Line_1" >
< /property >
---------------------------------------------------------
EmployeeTest.java
---------------------------------------------------------
import java.util.List;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class EmployeeTest {
private static final SessionFactory sessionFactory;
static {
try {
// Create the SessionFactory from hibernate.cfg.xml
sessionFactory = new Configuration().configure().buildSessionFactory();
} catch (Throwable ex) {
// Make sure you log the exception, as it might be swallowed
System.err.println("SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
public EmployeeTest() {
Session session = sessionFactory.openSession();
session.beginTransaction();
List listEmployee = session.getNamedQuery("findEmployee").
setParameter(0, 123).list();
System.out.println(listEmployee.size());
}
/**
* @param args
*/
public static void main(String[] args) {
new EmployeeTest();
}
}