传统的DAO模式
<!--[if !vml]--><!--[endif]-->
Figure 1. Application structure, before and after DAO
设计一个接口
IEmployeeDAO.java |
import java.util.Map; public interface IEmployeeDAO { //Returns the list of employees who fall into the given salary public List findBySalaryRange(Map salaryMap); |
实现这个接口
IEmployeeDAO.java |
import java.sql.Connection; public class EmployeeDAOImpl implements IEmployeeDAO{ public List findBySalaryRange(Map salaryMap) |
以上说明了DAO几个关键点:
- They encapsulate all interactions with the JDBC API. If an O/R mapping solution like Kodo or Hibernate were being used, the DAO classes can wrap the proprietary APIs of these products.
- They wrap the retrieved data in a JDBC API-neutral transfer object and returns it to the business tier for further processing.
- They are stateless in nature. Their sole aim is to access and change persistent data for the business objects.
- They trap any errors (for example, database is unavailable, wrong SQL syntax) reported in the process by the underlying JDBC API or database as SQLException. The DAO objects notify the business objects of such errors again by a JDBC-neutral, custom build runtime exception class DBException.
- They release database resources like Connection and PreparedStatement objects back to the pool and relinquish memory held by ResultSet cursors after they have been used.
Therefore, the DAO layer provides a consistent data access API for the business tier abstracting the low level data access API.
生成DAO Factory
DAOFactory.java |
public class DAOFactory { static{ private DAOFactory(){} public DAOFactory getInstance(){ public IEmployeeDAO getEmployeeDAO(){ |
同business组件结合
EmployeeBusinessServiceImpl .java |
public class EmployeeBusinessServiceImpl implements public List getEmployeesWithinSalaryRange(Map salaryMap){ IEmployeeDAO empDAO = DAOFactory.getInstance() |
问题:
The DAO design pattern is not devoid of shortcomings:
- Code Repetition: As evident from the EmployeeDAOImpl listing, code repetition (shown in bold above) is a major problem with JDBC-based, traditional database access. Writing boilerplate code over and over is a clear violation of the basic OO principle of code reuse. This has obvious side effects in terms of project cost, timelines, and effort.
- Coupling: The DAO code is very tightly coupled with the JDBC interfaces and core collections. This is evident from the number of import statements per DAO class.
- Resource Leakage: Following the design of the EmployeeDAOImpl class, all DAO methods must relinquish control of acquired database resources like connection, statements, and result sets. This is a risky proposition because a novice programmer can very easily skip those bits. As a result, resources would run out and bring the system to a halt.
- Error Handling: JDBC drivers report all error situations by raising the SQLException. SQLException is a checked exception, therefore developers are forced to handle it—even though it isn't possible to recover from the majority of these exceptions, which results in cluttering the code. Moreover, the error code and message obtained from the SQLException object are database vendor-specific, so it's not possible to write portable DAO error messaging code.
- Fragile Code: The setting of the bind variables for the statement object, and the retrieval of the data using the result set getter methods are two frequently used tasks in JDBC-based DAO. If the number of columns in the SQL where clause is changed, or the column positions are altered, the code has to go through the rigorous cycle of change, test, and redeployment.
进入Spring DAO
Figure 2. Major components of the Spring JDBC framework
JdbcTemplate
是最重要的 类,使用它能避免很过 错误,它主要做了以下工作:
Retrieves connections from the datasource. Prepares appropriate statement object. Executes SQL CRUD operations. Iterates over result sets and populates the results in standard collection objects. Handles
SQLException
exceptions and translates them to a more error-specific exception hierarchy.
用Spring DAO重写