A Primer on Spring's Data Access Object (DAO) Frameworkby Dhrubojyoti Kayal AbstractThe business components in J2EE applications typically use the JDBC API to access and change persistent data in relational databases. This often leads to the mixing of persistence code with business logic—a bad idea. The Data Access Object (DAO) design pattern addresses this problem by separating the persistence logic into data access classes. This article is a primer on DAO design pattern, highlighting its merits and demerits. It then introduces the Spring 2.0 JDBC/DAO framework and demonstrates how it elegantly addresses the drawbacks in traditional DAO design. Traditional DAO DesignData Access Object (DAO) is an integration tier design pattern as cataloged in the book Core J2EE Design Pattern. It encapsulates persistence store access and manipulation code into a separate layer. The persistent store in the context of this article is an RDBMS. This pattern introduces an abstraction layer between the business logic tier and the persistent storage tier, as shown in Figure 1. Business objects access the RDBMS (data source) through the data access objects. This abstraction layer streamlines application code and introduces flexibility. Ideally, changes made to the data source, such as switching database vendors or type, would require changes only to the data access objects and should have minimal impact on the business objects.
Now that I've explained the basics of the DAO design pattern, it's time to write some code. The examples below are from a company domain model. To put it simply, the company has several employees working in various departments such as sales, marketing, and HR. For the sake of simplicity, I will concentrate on a single entity called "Employee." Program to an interfaceThe flexibility the DAO design pattern provides is attributed primarily to a best practice for object design: Program to an Interface (P2I). This principle states that concrete objects must implement an interface that is used in the caller program rather than the concrete object itself. Therefore, you can easily substitute a different implementation with little impact on client code. Going by this mantra I will define the Employee DAO
interface, import java.util.Map;
public interface IEmployeeDAO {
//SQL String that will be executed
public String FIND_BY_SAL_RNG = "SELECT EMP_NO, EMP_NAME, "
+ "SALARY FROM EMP WHERE SALARY >= ? AND SALARY <= ?";
//Returns the list of employees who fall into the given salary
//range. The input parameter is the immutable map object
//obtained from the HttpServletRequest. This is an early
//refactoring based on "Introduce Parameter Object"
public List findBySalaryRange(Map salaryMap);
}
Providing the DAO implementation classesHaving defined the interface, now I must provide a concrete implementation of the Employee DAO, import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import com.bea.dev2dev.to.EmployeeTO;
public class EmployeeDAOImpl implements IEmployeeDAO{
public List findBySalaryRange(Map salaryMap)
{
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
List empList = new ArrayList();
//Transfer Object for inter-tier data transfer
EmployeeTO tempEmpTO = null;
try{
//DBUtil - helper classes that retrieve connection from pool
conn = DBUtil.getConnection();
pstmt = conn.prepareStatement(FIND_BY_SAL_RNG);
pstmt.setDouble(1, Double.valueOf( (String)
salaryMap.get("MIN_SALARY") );
pstmt.setDouble(2, Double.valueOf( (String)
salaryMap.get("MIN_SALARY") );
rs = pstmt.executeQuery();
int tmpEmpNo = 0;
String tmpEmpName = "";
double tmpSalary = 0.0D;
while (rs.next()){
tmpEmpNo = rs.getInt("EMP_NO");
tmpEmpName = rs.getString("EMP_NAME");
tmpSalary = rs.getDouble("SALARY");
tempEmpTO = new EmployeeTO(tmpEmpNo,
tmpEmpName,
tmpSalary);
empList.add(tempEmpTO);
}//end while
}//end try
catch (SQLException sqle){
throw new DBException(sqle);
}//end catch
finally{
try{
if (rs != null){
rs.close();
}
}
catch (SQLException sqle){
throw new DBException(sqle);
}
try{
if (pstmt != null){
pstmt.close();
}
}
catch (SQLException sqle){
throw new DBException(sqle);
}
try{
if (conn != null){
conn.close();
}
}
catch (SQLException sqle){
throw new DBException(sqle);
}
}//end of finally block
return empList;
}//end method findBySalaryRange
}
The above listing illustrates these key points about DAO methods:
Therefore, the DAO layer provides a consistent data access API for the business tier abstracting the low level data access API. Building the DAO FactoryThe DAO Factory is a typical factory design pattern implementation for creating and serving concrete DAO implementations to the business objects. The business objects use the DAO interfaces and are not aware of the implementation classes. This dependency inversion due to the DAO factory provides enormous flexibility. It is easy to alter DAO implementation (for example, from straight JDBC to Kodo-based O/R mapping) without affecting the client business objects, as long as the contract established by the DAO interfaces remains unchanged: public class DAOFactory {
private static DAOFactory daoFac;
static{
daoFac = new DAOFactory();
}
private DAOFactory(){}
public DAOFactory getInstance(){
return daoFac;
}
public IEmployeeDAO getEmployeeDAO(){
return new EmployeeDAOImpl();
}
}
Collaborating with the business componentsNow it's time to see how DAOs fit into the bigger picture. As mentioned in previous sections, the DAOs collaborate with the business tier components to fetch and change persistent business data. This listing shows the business service component and its interaction with the DAO tier: public class EmployeeBusinessServiceImpl implements
IEmployeeBusinessService {
public List getEmployeesWithinSalaryRange(Map salaryMap){
IEmployeeDAO empDAO = DAOFactory.getInstance()
.getEmployeeDAO();
List empList = empDAO.findBySalaryRange(salaryMap);
return empList;
}
}
This is nice and clean, with no reliance on any persistence interfaces (including JDBC) at all. ProblemsThe DAO design pattern is not devoid of shortcomings:
Let's look at how to maintain the majority of the benefits of DAO while doing away with these problems. |
Article Tools Related Products Check out the products mentioned in this article:Related Technologies Related Articles Bookmark Article
|