Spring DAO入门
摘要在J2EE 应用中,业务组件通常使用JDBC API 访问和改变关系数据库中的持久化数据。这样经常导致将持久化代码和业务逻辑混合在一起--- a bad idea. Data Access Object (DAO) 设计模式通过把持久化逻辑分离到数据访问类中从而解决了这个问题。本篇文章有关于DAO 设计模式的入门 ,重点放在DAO模式的优缺点。然后介绍了Spring 2.0 JDBC/DAO 框架并展示了它如何优雅的解决传统DAO 设计中的缺点。 传统DAO设计按照J2EE 核心设计模式( Core J2EE Desgin Pattern) 这本书中的分类,Data Access Object(DAO) 属于集成层设计模式。DAO在一个分开的层中封装了持久化存储访问和操作的代码。本篇文章中设计到的持久存储指的是RDBMS。DAO模式是业务逻辑层和持久存储层之间的抽象层,例如图1. 业务对象通过数据访问对象访问RDBMS(data source)。这个抽象层可以灵活的介入并简化了应用程序代码。理想情况下,当改变数据源,比如更换数据库厂商或者类型,只需要改变数据访问对象并对业 务对象的影响最小。 ![]() 图1 使用DAO之前和之后的对比 现在我已经说明了基本的DAO设计模式,到了写一些代码的时候了.下面的例子是一个公司的域模型(domain model).为了简单化,界定公司有若干工作在不同部门的雇员,比如销售,市场和人力资源.因为简化的原因,我将只关注一个单一的实体叫做雇员 “Employee”。 面向接口编程(Program to an Interface(P2I))DAO设计模式提供的灵活性主要归因于一个对象设计的最佳实践(best pratice):面向接口编程。这个规则是指具体对象必须实现一个接口,在调用程序中使用接口而不是具体对象本身。这样做,你可以很容易的代理到一个不 同的实现而对客户端的代码影响最小。按照这个规则,我将定义Employee DAO 接口,IEmployeeDAO ,并定义findBySalaryRange()方法。业务组件和DAO的这个方法交互。 public interface IEmployeeDAO { //被执行的SQL 语句 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); } DAO实现类 已经定义了DAO类,现在必须提供一个DAO的实现类 EmployeeDAOImpl
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 } 上面的代码展示了DAO方法的几个关键点:
因此,DAO层通过抽象底层的数据访问API,从而提供了一直的数据访问方式。
构建DAO Factory
DAO Factory 是典型的Factory
设计模式的实现,为的是让业务对象能创建和使用具体DAO的实现类。业务对象使用DAO接口而不关心其具体实现类。这种可以依赖倒置的原因是DAO
Factory提供了巨大的灵活性。只有DAO接口建立的约定保持不变,可以很容易的去改变DAO的实现(比如,从直接的JDBC
到基于Kodo的O/R Mapping),而不影响客户端的业务对象。
private static DAOFactory daoFac; static{ daoFac = new DAOFactory(); } private DAOFactory(){} public DAOFactory getInstance(){ return daoFac; } public IEmployeeDAO getEmployeeDAO(){ return new EmployeeDAOImpl(); } } 现在应该看看DAO怎么在整个应用中使用的时候了,正如前面部分提到的,业务层组件通过和DAO的交互去提取和改变持久业务数据,下面列举了业务服务组件和DAO的交互: IEmployeeBusinessService { public List getEmployeesWithinSalaryRange(Map salaryMap){ IEmployeeDAO empDAO = DAOFactory.getInstance() .getEmployeeDAO(); List empList = empDAO.findBySalaryRange(salaryMap); return empList; } } 这是很清晰的,根本没有任何对持久化接口的依赖。 问题 DAO设计模式也不是没有缺点:
|



wolfoxer
博客统计信息
热门文章
最新评论
友情链接