Dao模式

虽然DAO模式已经有了好多的成熟的框架,但它仍然是一个比较重要的设计模式。要做一个比较合理的DAO模式,你需要对工厂模式、单例模式、模板模 式、策略模式、代理模式、泛型、反射机制、输入输出、异常等知识比较熟悉。下面结合自己理解,设计一个DAO设计模式的例子,希望大家给与指正。

1、数据库连接池的工具类。

     在数据库连接池的工具类中,采用了开源的DBCP数据库连接池,调用了DataSource接口,DBCP中关于Datasource的 Connection采用了动态代理的方式实现,在这里只是提出,感兴趣可以查看其源码,该工具类采用可配置的方式实现的,代码如下:

 

Java代码
  1. package  com.cvicse.utils;  
  2.   
  3. import  java.io.InputStream;  
  4. import  java.sql.Connection;  
  5. import  java.sql.ResultSet;  
  6. import  java.sql.SQLException;  
  7. import  java.sql.Statement;  
  8. import  java.util.Properties;  
  9.   
  10. import  javax.sql.DataSource;  
  11.   
  12. import  org.apache.commons.dbcp.BasicDataSourceFactory;  
  13.   
  14. /**  
  15.  * 数据库连接池操作工具类  
  16.  *   
  17.  */   
  18. public   class  JDBCUtils {  
  19.     private   static  DataSource myDataSource =  null ;  
  20.     private  JDBCUtils() {  
  21.     }  
  22.   
  23.     static  {  
  24.         try  {  
  25.             Properties prop = new  Properties();  
  26. //采用了类的加载获取路径下数据库的配置信息   
  27.             InputStream is = JDBCUtils.class .getClassLoader()  
  28.                     .getResourceAsStream("dbcpconfig.properties" );  
  29.             prop.load(is);  
  30.             myDataSource = BasicDataSourceFactory.createDataSource(prop);  
  31.         } catch  (Exception e) {  
  32.             throw   new  ExceptionInInitializerError(e);  
  33.         }  
  34.     }  
  35.   
  36.     /**  
  37.      * 获取数据源  
  38.      *   
  39.      * @return  
  40.      */   
  41.     public   static  DataSource getDataSource() {  
  42.         return  myDataSource;  
  43.     }  
  44.   
  45.     /**  
  46.      * 获取连接  
  47.      *   
  48.      * @return  
  49.      * @throws SQLException  
  50.      */   
  51.     public   static  Connection getConnection()  throws  SQLException {  
  52.         return  myDataSource.getConnection();  
  53.     }  
  54.   
  55.     /**  
  56.      * 关闭资源  
  57.      * @param rs  
  58.      * @param st  
  59.      * @param conn  
  60.      * @throws SQLException  
  61.      */   
  62.     public   static   void  free(ResultSet rs, Statement st, Connection conn)  
  63.             throws  SQLException {  
  64.         try  {  
  65.             if  (rs !=  null )  
  66.                 rs.close();  
  67.         } catch  (SQLException e) {  
  68.             throw   new  SQLException();  
  69.         } finally  {  
  70.             try  {  
  71.                 if  (st !=  null )  
  72.                     st.close();  
  73.             } catch  (SQLException e) {  
  74.                 throw   new  SQLException();  
  75.             } finally  {  
  76.                 if  (conn !=  null )  
  77.                     try  {  
  78.                         conn.close();  
  79.                     } catch  (Exception e) {  
  80.                         throw   new  SQLException();  
  81.                     }  
  82.             }  
  83.         }  
  84.     }  
  85. }  
package com.cvicse.utils;

import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.commons.dbcp.BasicDataSourceFactory;

/**
 * 数据库连接池操作工具类
 * 
 */
public class JDBCUtils {
	private static DataSource myDataSource = null;
	private JDBCUtils() {
	}

	static {
		try {
			Properties prop = new Properties();
//采用了类的加载获取路径下数据库的配置信息
			InputStream is = JDBCUtils.class.getClassLoader()
					.getResourceAsStream("dbcpconfig.properties");
			prop.load(is);
			myDataSource = BasicDataSourceFactory.createDataSource(prop);
		} catch (Exception e) {
			throw new ExceptionInInitializerError(e);
		}
	}

	/**
	 * 获取数据源
	 * 
	 * @return
	 */
	public static DataSource getDataSource() {
		return myDataSource;
	}

	/**
	 * 获取连接
	 * 
	 * @return
	 * @throws SQLException
	 */
	public static Connection getConnection() throws SQLException {
		return myDataSource.getConnection();
	}

	/**
	 * 关闭资源
	 * @param rs
	 * @param st
	 * @param conn
	 * @throws SQLException
	 */
	public static void free(ResultSet rs, Statement st, Connection conn)
			throws SQLException {
		try {
			if (rs != null)
				rs.close();
		} catch (SQLException e) {
			throw new SQLException();
		} finally {
			try {
				if (st != null)
					st.close();
			} catch (SQLException e) {
				throw new SQLException();
			} finally {
				if (conn != null)
					try {
						conn.close();
					} catch (Exception e) {
						throw new SQLException();
					}
			}
		}
	}
}

 数据库配置文件的信息如下dbcpconfig.properties

Java代码
  1. #连接设置  
  2. driverClassName=com.mysql.jdbc.Driver  
  3. url=jdbc:mysql://localhost:3306/test123   
  4. username=root  
  5. password=  
  6.   
  7. #<!-- 初始化连接 -->  
  8. initialSize=10   
  9.   
  10. #最大连接数量  
  11. maxActive=50   
  12.   
  13. #<!-- 最大空闲连接 -->  
  14. maxIdle=20   
  15.   
  16. #<!-- 最小空闲连接 -->  
  17. minIdle=5   
  18.   
  19. #<!-- 超时等待时间以毫秒为单位 6000 毫秒/ 1000 等于 60 秒 -->  
  20. maxWait=60000   
  21.   
  22.   
  23. #JDBC驱动建立连接时附带的连接属性属性的格式必须为这样:[属性名=property;]   
  24. #注意:"user"  与  "password"  两个属性会被明确地传递,因此这里不需要包含他们。  
  25. connectionProperties=useUnicode=true ;characterEncoding=UTF- 8   
  26.   
  27. #指定由连接池所创建的连接的自动提交(auto-commit)状态。  
  28. defaultAutoCommit=true   
  29.   
  30. #driver default  指定由连接池所创建的连接的只读(read-only)状态。  
  31. #如果没有设置该值,则“setReadOnly”方法将不被调用。(某些驱动并不支持只读模式,如:Informix)  
  32. defaultReadOnly=  
  33.   
  34. #driver default  指定由连接池所创建的连接的事务级别(TransactionIsolation)。  
  35. #可用值为下列之一:(详情可见javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE  
  36. defaultTransactionIsolation=READ_UNCOMMITTED  
#连接设置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test123
username=root
password=

#<!-- 初始化连接 -->
initialSize=10

#最大连接数量
maxActive=50

#<!-- 最大空闲连接 -->
maxIdle=20

#<!-- 最小空闲连接 -->
minIdle=5

#<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 -->
maxWait=60000


#JDBC驱动建立连接时附带的连接属性属性的格式必须为这样:[属性名=property;] 
#注意:"user" 与 "password" 两个属性会被明确地传递,因此这里不需要包含他们。
connectionProperties=useUnicode=true;characterEncoding=UTF-8

#指定由连接池所创建的连接的自动提交(auto-commit)状态。
defaultAutoCommit=true

#driver default 指定由连接池所创建的连接的只读(read-only)状态。
#如果没有设置该值,则“setReadOnly”方法将不被调用。(某些驱动并不支持只读模式,如:Informix)
defaultReadOnly=

#driver default 指定由连接池所创建的连接的事务级别(TransactionIsolation)。
#可用值为下列之一:(详情可见javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
defaultTransactionIsolation=READ_UNCOMMITTED

 2、异常定义,用于处理DAO层的异常类,因为异常最好要在业务层进行处理,个人认为这DAO层异常应该在业务层进行处理,所以DAO层的必要异常都抛出。

Java代码
  1. package  com.cvicse.dao.exception;  
  2.   
  3. /**  
  4.  *  
  5.  * 定义DAO异常类  
  6.  *  
  7.  */   
  8. public   class  DaoException  extends  Exception {  
  9.     private   static   final   long  serialVersionUID = 1L;  
  10.     /**  
  11.      * @param message  
  12.      * @param cause  
  13.      */   
  14.     public  DaoException(String message, Throwable cause) {  
  15.         super (message, cause);  
  16.     }  
  17.     /**  
  18.      * @param message  
  19.      */   
  20.     public  DaoException(String message) {  
  21.         super (message);  
  22.     }  
  23. }  
  24.   
  25. package  com.cvicse.dao.exception;  
  26.   
  27.   
  28. /**  
  29.  * 传入参数错误异常  
  30.  *  
  31.  */   
  32. public   class  DaoParameterException  extends  DaoException {  
  33.     private   static   final   long  serialVersionUID = 1L;  
  34.   
  35.     /**  
  36.      * @param message  
  37.      * @param cause  
  38.      */   
  39.     public  DaoParameterException(String message, Throwable cause) {  
  40.         super (message, cause);  
  41.     }  
  42.   
  43.     /**  
  44.      * @param message  
  45.      */   
  46.     public  DaoParameterException(String message) {  
  47.         super (message);  
  48.     }  
  49.   
  50. }  
package com.cvicse.dao.exception;

/**
 *
 * 定义DAO异常类
 *
 */
public class DaoException extends Exception {
	private static final long serialVersionUID = 1L;
	/**
	 * @param message
	 * @param cause
	 */
	public DaoException(String message, Throwable cause) {
		super(message, cause);
	}
	/**
	 * @param message
	 */
	public DaoException(String message) {
		super(message);
	}
}

package com.cvicse.dao.exception;


/**
 * 传入参数错误异常
 *
 */
public class DaoParameterException extends DaoException {
	private static final long serialVersionUID = 1L;

	/**
	 * @param message
	 * @param cause
	 */
	public DaoParameterException(String message, Throwable cause) {
		super(message, cause);
	}

	/**
	 * @param message
	 */
	public DaoParameterException(String message) {
		super(message);
	}

}

 

3、定义要操作的pojo类,这里定义了2个pojo类

Java代码
  1. package  com.cvicse.po;  
  2.   
  3. /**  
  4.  * 课程持久层对象  
  5.  *  
  6.  */   
  7. public   class  Course {  
  8.     private   long  id;  
  9.     private  String name;  
  10.     /**  
  11.      * 构造函数类  
  12.      */   
  13.     public  Course() {  
  14.         this .id =  0 ;  
  15.         this .name =  null ;  
  16.     }  
  17.     /**  
  18.      * @param id  
  19.      * @param name  
  20.      */   
  21.     public  Course( long  id, String name) {  
  22.         this .id = id;  
  23.         this .name = name;  
  24.     }  
  25.   
  26.     /**  
  27.      * @return  
  28.      */   
  29.     public   long  getId() {  
  30.         return  id;  
  31.     }  
  32.   
  33.     /**  
  34.      * @param id  
  35.      */   
  36.     public   void  setId( long  id) {  
  37.         this .id = id;  
  38.     }  
  39.   
  40.     /**  
  41.      * @return  
  42.      */   
  43.     public  String getName() {  
  44.         return  name;  
  45.     }  
  46.   
  47.     /**  
  48.      * @param name  
  49.      */   
  50.     public   void  setName(String name) {  
  51.         this .name = name;  
  52.     }  
  53. }  
  54.   
  55. package  com.cvicse.po;  
  56.   
  57. /**  
  58.  * 学生持久层对象  
  59.  */   
  60. public   class  Student {  
  61.     private   long  id;  
  62.   
  63.     private  String name;  
  64.   
  65.     public  Student() {  
  66.         this .id =  0 ;  
  67.         this .name =  null ;  
  68.     }  
  69.   
  70.     public  Student( long  id, String name) {  
  71.         this .id = id;  
  72.         this .name = name;  
  73.     }  
  74.   
  75.     public   long  getId() {  
  76.         return  id;  
  77.     }  
  78.   
  79.     public   void  setId( long  id) {  
  80.         this .id = id;  
  81.     }  
  82.   
  83.     public  String getName() {  
  84.         return  name;  
  85.     }  
  86.   
  87.     public   void  setName(String name) {  
  88.         this .name = name;  
  89.     }  
  90. }  
package com.cvicse.po;

/**
 * 课程持久层对象
 *
 */
public class Course {
	private long id;
	private String name;
	/**
	 * 构造函数类
	 */
	public Course() {
		this.id = 0;
		this.name = null;
	}
	/**
	 * @param id
	 * @param name
	 */
	public Course(long id, String name) {
		this.id = id;
		this.name = name;
	}

	/**
	 * @return
	 */
	public long getId() {
		return id;
	}

	/**
	 * @param id
	 */
	public void setId(long id) {
		this.id = id;
	}

	/**
	 * @return
	 */
	public String getName() {
		return name;
	}

	/**
	 * @param name
	 */
	public void setName(String name) {
		this.name = name;
	}
}

package com.cvicse.po;

/**
 * 学生持久层对象
 */
public class Student {
	private long id;

	private String name;

	public Student() {
		this.id = 0;
		this.name = null;
	}

	public Student(long id, String name) {
		this.id = id;
		this.name = name;
	}

	public long getId() {
		return id;
	}

	public void setId(long id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}

 

4、定义对象操作的DAO接口,因为面向接口编程,定义接口目的是DAO层的操作能和业务层解耦。

Java代码
  1. package  com.cvicse.dao;  
  2.   
  3. import  java.util.List;  
  4.   
  5. import  com.cvicse.dao.exception.DaoException;  
  6. import  com.cvicse.po.Course;  
  7.   
  8. /**  
  9.  * 课程DAO层接口  
  10.  *  
  11.  */   
  12. public   interface  CourseDAO {  
  13.      
  14.     /**  
  15.      * 获取列表  
  16.      * @return  
  17.      * @throws DaoException  
  18.      */   
  19.     public  List<Course> selectCourses()  throws  DaoException;  
  20.   
  21.     /**  
  22.      * 插入记录  
  23.      * @param course  
  24.      * @throws DaoException  
  25.      */   
  26.     public   void  insertCourse(Course course)  throws  DaoException;  
  27. }  
  28.   
  29. package  com.cvicse.dao;  
  30.   
  31. import  java.util.List;  
  32.   
  33. import  com.cvicse.dao.exception.DaoException;  
  34. import  com.cvicse.po.Student;  
  35.   
  36. public   interface  StudentDAO {  
  37.   
  38.     /**  
  39.      * 查询方法  
  40.      * @return  
  41.      * @throws DaoException  
  42.      */   
  43.     public  List selectStudents()  throws  DaoException;  
  44.   
  45.     /**  
  46.      * 添加方法  
  47.      * @param student  
  48.      * @throws DaoException  
  49.      */   
  50.     public   void  insertStudent(Student student)  throws  DaoException;  
  51.   
  52.     /**  
  53.      * 删除方法  
  54.      * @param student  
  55.      * @throws DaoException  
  56.      */   
  57.     public   void  deleteStudent(Student student)  throws  DaoException;  
  58.   
  59.     /**  
  60.      * 修改方法  
  61.      * @param student  
  62.      * @throws DaoException  
  63.      */   
  64.     public   void  modifyStudent(Student student)  throws  DaoException;  
  65. }  
package com.cvicse.dao;

import java.util.List;

import com.cvicse.dao.exception.DaoException;
import com.cvicse.po.Course;

/**
 * 课程DAO层接口
 *
 */
public interface CourseDAO {
   
	/**
	 * 获取列表
	 * @return
	 * @throws DaoException
	 */
	public List<Course> selectCourses() throws DaoException;

	/**
	 * 插入记录
	 * @param course
	 * @throws DaoException
	 */
	public void insertCourse(Course course) throws DaoException;
}

package com.cvicse.dao;

import java.util.List;

import com.cvicse.dao.exception.DaoException;
import com.cvicse.po.Student;

public interface StudentDAO {

	/**
	 * 查询方法
	 * @return
	 * @throws DaoException
	 */
	public List selectStudents() throws DaoException;

	/**
	 * 添加方法
	 * @param student
	 * @throws DaoException
	 */
	public void insertStudent(Student student) throws DaoException;

	/**
	 * 删除方法
	 * @param student
	 * @throws DaoException
	 */
	public void deleteStudent(Student student) throws DaoException;

	/**
	 * 修改方法
	 * @param student
	 * @throws DaoException
	 */
	public void modifyStudent(Student student) throws DaoException;
}

 

5、定义DAO操作的模板类,将DAO层的常用操作类进行提取。

Java代码
  1. package  com.cvicse.util;  
  2.   
  3. import  java.sql.Connection;  
  4. import  java.sql.PreparedStatement;  
  5. import  java.sql.ResultSet;  
  6. import  java.sql.SQLException;  
  7. import  java.sql.Statement;  
  8. import  java.util.ArrayList;  
  9. import  java.util.List;  
  10.   
  11. import  com.cvicse.dao.exception.DaoException;  
  12. import  com.cvicse.dao.exception.DaoParameterException;  
  13. import  com.cvicse.dao.refactor.RowMapper;  
  14.   
  15. public   class  DaoOperateTemplate {  
  16.     /**  
  17.      * 查找单个记录对象  
  18.      *   
  19.      * @param sql  
  20.      * @param args  
  21.      * @param rowMapper  
  22.      * @return  
  23.      * @throws DaoException  
  24.      */   
  25.     public  Object find(String sql, Object[] args, RowMapper rowMapper)  
  26.             throws  DaoException {  
  27.         Connection conn = null ;  
  28.         PreparedStatement ps = null ;  
  29.         ResultSet rs = null ;  
  30.         try  {  
  31.             conn = JDBCUtils.getConnection();  
  32.             ps = conn.prepareStatement(sql);  
  33.             for  ( int  i =  0 ; i < args.length; i++)  
  34.                 ps.setObject(i + 1 , args[i]);  
  35.             rs = ps.executeQuery();  
  36.             Object obj = null ;  
  37.             if  (rs.next()) {  
  38.                 obj = rowMapper.mapRow(rs);  
  39.             }  
  40.             return  obj;  
  41.         } catch  (SQLException e) {  
  42.             throw   new  DaoException(e.getMessage(), e);  
  43.         } finally  {  
  44.             try  {  
  45.                 JDBCUtils.free(rs, ps, conn);  
  46.             } catch  (SQLException e) {  
  47.                 throw   new  DaoParameterException(e.getMessage(), e);  
  48.             }  
  49.         }  
  50.     }  
  51.   
  52.     /**  
  53.      * 查找多条记录对象  
  54.      *   
  55.      * @param sql  
  56.      * @param args  
  57.      * @param rowMapper  
  58.      * @return  
  59.      * @throws DaoException  
  60.      */   
  61.     public  List<Object> Query(String sql, Object[] args, RowMapper rowMapper)  
  62.             throws  DaoException {  
  63.         Connection conn = null ;  
  64.         PreparedStatement ps = null ;  
  65.         ResultSet rs = null ;  
  66.         List<Object> results = new  ArrayList<Object>();  
  67.         try  {  
  68.             conn = JDBCUtils.getConnection();  
  69.             ps = conn.prepareStatement(sql);  
  70.             for  ( int  i =  0 ; i < args.length; i++)  
  71.                 ps.setObject(i + 1 , args[i]);  
  72.             rs = ps.executeQuery();  
  73.             Object obj = null ;  
  74.             while  (rs.next()) {  
  75.                 obj = rowMapper.mapRow(rs);  
  76.                 results.add(obj);  
  77.             }  
  78.             return  results;  
  79.         } catch  (SQLException e) {  
  80.             throw   new  DaoException(e.getMessage(), e);  
  81.         } finally  {  
  82.             try  {  
  83.                 JDBCUtils.free(rs, ps, conn);  
  84.             } catch  (SQLException e) {  
  85.                 throw   new  DaoParameterException(e.getMessage(), e);  
  86.             }  
  87.         }  
  88.     }  
  89.   
  90.     /**  
  91.      * 更新操作  
  92.      *   
  93.      * @param sql  
  94.      * @param args  
  95.      * @param isGeneralKey  
  96.      * @throws DaoException  
  97.      */   
  98.     public   void  update(String sql, Object[] args,  boolean  isGeneralKey)  
  99.             throws  DaoException {  
  100.         Connection conn = null ;  
  101.         PreparedStatement ps = null ;  
  102.         ResultSet rs = null ;  
  103.         try  {  
  104.             conn = JDBCUtils.getConnection();  
  105.             ps = (isGeneralKey ? conn.prepareStatement(sql,  
  106.                     Statement.RETURN_GENERATED_KEYS) : conn  
  107.                     .prepareStatement(sql));  
  108.             for  ( int  i =  0 ; i < args.length; i++)  
  109.                 ps.setObject(i + 1 , args[i]);  
  110.             ps.executeUpdate();  
  111.         } catch  (SQLException e) {  
  112.             throw   new  DaoException(e.getMessage(), e);  
  113.         } finally  {  
  114.             try  {  
  115.                 JDBCUtils.free(rs, ps, conn);  
  116.             } catch  (SQLException e) {  
  117.                 throw   new  DaoParameterException(e.getMessage(), e);  
  118.             }  
  119.         }  
  120.     }  
  121. }  
package com.cvicse.util;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import com.cvicse.dao.exception.DaoException;
import com.cvicse.dao.exception.DaoParameterException;
import com.cvicse.dao.refactor.RowMapper;

public class DaoOperateTemplate {
	/**
	 * 查找单个记录对象
	 * 
	 * @param sql
	 * @param args
	 * @param rowMapper
	 * @return
	 * @throws DaoException
	 */
	public Object find(String sql, Object[] args, RowMapper rowMapper)
			throws DaoException {
		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		try {
			conn = JDBCUtils.getConnection();
			ps = conn.prepareStatement(sql);
			for (int i = 0; i < args.length; i++)
				ps.setObject(i + 1, args[i]);
			rs = ps.executeQuery();
			Object obj = null;
			if (rs.next()) {
				obj = rowMapper.mapRow(rs);
			}
			return obj;
		} catch (SQLException e) {
			throw new DaoException(e.getMessage(), e);
		} finally {
			try {
				JDBCUtils.free(rs, ps, conn);
			} catch (SQLException e) {
				throw new DaoParameterException(e.getMessage(), e);
			}
		}
	}

	/**
	 * 查找多条记录对象
	 * 
	 * @param sql
	 * @param args
	 * @param rowMapper
	 * @return
	 * @throws DaoException
	 */
	public List<Object> Query(String sql, Object[] args, RowMapper rowMapper)
			throws DaoException {
		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		List<Object> results = new ArrayList<Object>();
		try {
			conn = JDBCUtils.getConnection();
			ps = conn.prepareStatement(sql);
			for (int i = 0; i < args.length; i++)
				ps.setObject(i + 1, args[i]);
			rs = ps.executeQuery();
			Object obj = null;
			while (rs.next()) {
				obj = rowMapper.mapRow(rs);
				results.add(obj);
			}
			return results;
		} catch (SQLException e) {
			throw new DaoException(e.getMessage(), e);
		} finally {
			try {
				JDBCUtils.free(rs, ps, conn);
			} catch (SQLException e) {
				throw new DaoParameterException(e.getMessage(), e);
			}
		}
	}

	/**
	 * 更新操作
	 * 
	 * @param sql
	 * @param args
	 * @param isGeneralKey
	 * @throws DaoException
	 */
	public void update(String sql, Object[] args, boolean isGeneralKey)
			throws DaoException {
		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		try {
			conn = JDBCUtils.getConnection();
			ps = (isGeneralKey ? conn.prepareStatement(sql,
					Statement.RETURN_GENERATED_KEYS) : conn
					.prepareStatement(sql));
			for (int i = 0; i < args.length; i++)
				ps.setObject(i + 1, args[i]);
			ps.executeUpdate();
		} catch (SQLException e) {
			throw new DaoException(e.getMessage(), e);
		} finally {
			try {
				JDBCUtils.free(rs, ps, conn);
			} catch (SQLException e) {
				throw new DaoParameterException(e.getMessage(), e);
			}
		}
	}
}

 上面DAO通用操作类中定义接口,用于对象的转化。

Java代码
  1. package  com.cvicse.dao.refactor;  
  2.   
  3. import  java.sql.ResultSet;  
  4. import  java.sql.SQLException;  
  5.   
  6. /**  
  7.  * @author Administrator  
  8.  *  
  9.  */   
  10. public   interface  RowMapper {  
  11.       
  12.     /**  
  13.      * 映射接口  
  14.      * @param rs  
  15.      * @return  
  16.      * @throws SQLException  
  17.      */   
  18.     public  Object mapRow(ResultSet rs)  throws  SQLException;  
  19. }  
package com.cvicse.dao.refactor;

import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * @author Administrator
 *
 */
public interface RowMapper {
	
	/**
	 * 映射接口
	 * @param rs
	 * @return
	 * @throws SQLException
	 */
	public Object mapRow(ResultSet rs) throws SQLException;
}

 6、定义具体DAO的实现,在DAO具体实现中,我们采用组合的方式引用通用类,正如设计原则中说的先考虑组合后考虑继承。所以我们在这里选择组合,而不用继承,同时继承对象的转换同样会存在问题。在每个具体DAO操作的实现类中,我们采用了策略模式。

Java代码
  1. package  com.cvicse.dao.impl;  
  2.   
  3. import  java.sql.ResultSet;  
  4. import  java.sql.SQLException;  
  5. import  java.util.List;  
  6.   
  7. import  com.cvicse.dao.CourseDAO;  
  8. import  com.cvicse.dao.exception.DaoException;  
  9. import  com.cvicse.dao.refactor.RowMapper;  
  10. import  com.cvicse.po.Course;  
  11. import  com.cvicse.util.DaoOperateTemplate;  
  12.   
  13. public   class  CourseDAOImpl  implements  CourseDAO {  
  14.   
  15.     private  DaoOperateTemplate daoTemplate =  new  DaoOperateTemplate();  
  16.   
  17.     public   void  insertCourse(Course course)  throws  DaoException {  
  18.         // TODO Auto-generated method stub   
  19.         String sql = "insert into course(id,name) values (?,?) " ;  
  20.         Object[] args = new  Object[] { course.getId(), course.getName() };  
  21.         daoTemplate.update(sql, args, false );  
  22.     }  
  23.   
  24.     public  List<Course> selectCourses()  throws  DaoException {  
  25.         // TODO Auto-generated method stub   
  26.         String sql = "select * from course where id=? " ;  
  27.         Object[] args = new  Object[] {  1  };  
  28.         List courseList = daoTemplate.Query(sql, args, new  courseRowMapper());  
  29.         return  courseList;  
  30.     }  
  31.   
  32.     /**  
  33.      * 内部匿名类  
  34.      *   
  35.      * @author Administrator  
  36.      *   
  37.      */   
  38.     class  courseRowMapper  implements  RowMapper {  
  39.         public  Object mapRow(ResultSet rs)  throws  SQLException {  
  40.             Course course = new  Course();  
  41.             course.setId(rs.getLong("id" ));  
  42.             course.setName(rs.getString("name" ));  
  43.             return  course;  
  44.         }  
  45.     }  
  46. }  
  47. package  com.cvicse.dao.impl;  
  48.   
  49. import  java.sql.ResultSet;  
  50. import  java.sql.SQLException;  
  51. import  java.util.List;  
  52.   
  53. import  com.cvicse.dao.StudentDAO;  
  54. import  com.cvicse.dao.exception.DaoException;  
  55. import  com.cvicse.dao.refactor.RowMapper;  
  56. import  com.cvicse.po.Student;  
  57. import  com.cvicse.util.DaoOperateTemplate;  
  58.   
  59. public   class  StudentDAOImpl  implements  StudentDAO {  
  60.   
  61.     private  DaoOperateTemplate daoTemplate =  new  DaoOperateTemplate();  
  62.   
  63.     /*  
  64.      * (non-Javadoc)  
  65.      *   
  66.      * @see com.cvicse.dao.StudentDAO#deleteStudent(com.cvicse.po.Student)  
  67.      */   
  68.     public   void  deleteStudent(Student student)  throws  DaoException {  
  69.         // TODO Auto-generated method stub   
  70.         String sql = "delete from user where id=?" ;  
  71.         Object[] args = new  Object[] { student.getId() };  
  72.         daoTemplate.update(sql, args, false );  
  73.     }  
  74.   
  75.     /*  
  76.      * (non-Javadoc)  
  77.      *   
  78.      * @see com.cvicse.dao.StudentDAO#insertStudent(com.cvicse.po.Student)  
  79.      */   
  80.     public   void  insertStudent(Student student)  throws  DaoException {  
  81.         // TODO Auto-generated method stub   
  82.         String sql = "insert into student(id,name) values (?,?) " ;  
  83.         Object[] args = new  Object[] { student.getId(), student.getName() };  
  84.         daoTemplate.update(sql, args, false );  
  85.     }  
  86.   
  87.     public   void  modifyStudent(Student student)  throws  DaoException {  
  88.         // TODO Auto-generated method stub   
  89.         String sql = "update student set name=? where id=? " ;  
  90.         Object[] args = new  Object[] { student.getName(), student.getId() };  
  91.         daoTemplate.update(sql, args, false );  
  92.     }  
  93.   
  94.     public  List selectStudents()  throws  DaoException {  
  95.         // TODO Auto-generated method stub   
  96.         String sql = "select * from course where id=? " ;  
  97.         Object[] args = new  Object[] {  1  };  
  98.         List courseList = daoTemplate.Query(sql, args, new  studentRowMapper());  
  99.         return  courseList;  
  100.     }  
  101.   
  102.     /**  
  103.      * 内部匿名类  
  104.      *   
  105.      * @author Administrator  
  106.      *   
  107.      */   
  108.     class  studentRowMapper  implements  RowMapper {  
  109.         public  Object mapRow(ResultSet rs)  throws  SQLException {  
  110.             Student student = new  Student();  
  111.             student.setId(rs.getLong("id" ));  
  112.             student.setName(rs.getString("name" ));  
  113.             return  student;  
  114.         }  
  115.     }  
  116. }  
package com.cvicse.dao.impl;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import com.cvicse.dao.CourseDAO;
import com.cvicse.dao.exception.DaoException;
import com.cvicse.dao.refactor.RowMapper;
import com.cvicse.po.Course;
import com.cvicse.util.DaoOperateTemplate;

public class CourseDAOImpl implements CourseDAO {

	private DaoOperateTemplate daoTemplate = new DaoOperateTemplate();

	public void insertCourse(Course course) throws DaoException {
		// TODO Auto-generated method stub
		String sql = "insert into course(id,name) values (?,?) ";
		Object[] args = new Object[] { course.getId(), course.getName() };
		daoTemplate.update(sql, args, false);
	}

	public List<Course> selectCourses() throws DaoException {
		// TODO Auto-generated method stub
		String sql = "select * from course where id=? ";
		Object[] args = new Object[] { 1 };
		List courseList = daoTemplate.Query(sql, args, new courseRowMapper());
		return courseList;
	}

	/**
	 * 内部匿名类
	 * 
	 * @author Administrator
	 * 
	 */
	class courseRowMapper implements RowMapper {
		public Object mapRow(ResultSet rs) throws SQLException {
			Course course = new Course();
			course.setId(rs.getLong("id"));
			course.setName(rs.getString("name"));
			return course;
		}
	}
}
package com.cvicse.dao.impl;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import com.cvicse.dao.StudentDAO;
import com.cvicse.dao.exception.DaoException;
import com.cvicse.dao.refactor.RowMapper;
import com.cvicse.po.Student;
import com.cvicse.util.DaoOperateTemplate;

public class StudentDAOImpl implements StudentDAO {

	private DaoOperateTemplate daoTemplate = new DaoOperateTemplate();

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.cvicse.dao.StudentDAO#deleteStudent(com.cvicse.po.Student)
	 */
	public void deleteStudent(Student student) throws DaoException {
		// TODO Auto-generated method stub
		String sql = "delete from user where id=?";
		Object[] args = new Object[] { student.getId() };
		daoTemplate.update(sql, args, false);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.cvicse.dao.StudentDAO#insertStudent(com.cvicse.po.Student)
	 */
	public void insertStudent(Student student) throws DaoException {
		// TODO Auto-generated method stub
		String sql = "insert into student(id,name) values (?,?) ";
		Object[] args = new Object[] { student.getId(), student.getName() };
		daoTemplate.update(sql, args, false);
	}

	public void modifyStudent(Student student) throws DaoException {
		// TODO Auto-generated method stub
		String sql = "update student set name=? where id=? ";
		Object[] args = new Object[] { student.getName(), student.getId() };
		daoTemplate.update(sql, args, false);
	}

	public List selectStudents() throws DaoException {
		// TODO Auto-generated method stub
		String sql = "select * from course where id=? ";
		Object[] args = new Object[] { 1 };
		List courseList = daoTemplate.Query(sql, args, new studentRowMapper());
		return courseList;
	}

	/**
	 * 内部匿名类
	 * 
	 * @author Administrator
	 * 
	 */
	class studentRowMapper implements RowMapper {
		public Object mapRow(ResultSet rs) throws SQLException {
			Student student = new Student();
			student.setId(rs.getLong("id"));
			student.setName(rs.getString("name"));
			return student;
		}
	}
}

 7、我们定义工厂类,在定义工厂类,考虑到通用性,我们采用了反射机制加配置文件的形式来实现的。同时,在工厂模式中引入了饿汉式单例模式。

Java代码
  1. /**  
  2.  *   
  3.  */   
  4. package  com.cvicse.daofactory;  
  5.   
  6. import  java.io.IOException;  
  7. import  java.io.InputStream;  
  8. import  java.util.Properties;  
  9.   
  10. /**  
  11.  * 工厂类方法  
  12.  *   
  13.  */   
  14.   
  15. public   class  DaoFactory {  
  16.   
  17.     private   static  DaoFactory instance =  new  DaoFactory(); //懒汉法声明对象   
  18.     private   static  Properties pro; // 配置文件对象   
  19.   
  20.     private  DaoFactory() {  
  21.         try  {  
  22.             // 初始化配置文件   
  23.             pro = new  Properties();  
  24.             // 采用类加载器方法读取配置文件信息到字节流对象,采用类加载灵活,不用写死   
  25.             InputStream inputStream = DaoFactory.class .getClassLoader()  
  26.                     .getResourceAsStream("applicationContext.properties" );  
  27.             // 加载字节流对象   
  28.             pro.load(inputStream);  
  29.         } catch  (IOException e) {  
  30.             throw   new  ExceptionInInitializerError(e);  
  31.         }  
  32.     }  
  33.   
  34.     /**  
  35.      * 单例模式获取唯一实例  
  36.      *   
  37.      * @return  
  38.      */   
  39.     public   static  DaoFactory getInstance() {  
  40.         return  instance;  
  41.     }  
  42.   
  43.     /**  
  44.      * 根据配置文件的名字获取类的名字,采用反射机制获取其对象  
  45.      *   
  46.      * @param Key  
  47.      * @return  
  48.      */   
  49.     public  Object getDAO(String Key)  throws  Exception {  
  50.         String className = (String) pro.get(Key);  
  51.         return  (Class.forName(className).newInstance());  
  52.     }  
  53. }  
/**
 * 
 */
package com.cvicse.daofactory;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

/**
 * 工厂类方法
 * 
 */

public class DaoFactory {

	private static DaoFactory instance = new DaoFactory();//懒汉法声明对象
	private static Properties pro;// 配置文件对象

	private DaoFactory() {
		try {
			// 初始化配置文件
			pro = new Properties();
			// 采用类加载器方法读取配置文件信息到字节流对象,采用类加载灵活,不用写死
			InputStream inputStream = DaoFactory.class.getClassLoader()
					.getResourceAsStream("applicationContext.properties");
			// 加载字节流对象
			pro.load(inputStream);
		} catch (IOException e) {
			throw new ExceptionInInitializerError(e);
		}
	}

	/**
	 * 单例模式获取唯一实例
	 * 
	 * @return
	 */
	public static DaoFactory getInstance() {
		return instance;
	}

	/**
	 * 根据配置文件的名字获取类的名字,采用反射机制获取其对象
	 * 
	 * @param Key
	 * @return
	 */
	public Object getDAO(String Key) throws Exception {
		String className = (String) pro.get(Key);
		return (Class.forName(className).newInstance());
	}
}

 配置文件的内容如下:applicationContext.properties

Java代码
  1. courseDao=com.cvicse.dao.impl.CourseDAOImpl  
  2. entsDao=com.cvicse.dao.impl.StudentDAOImpl  
    courseDao=com.cvicse.dao.impl.CourseDAOImpl
studentsDao=com.cvicse.dao.impl.StudentDAOImpl

 8、业务层的调用方式,这里用客户端方式模拟的。在业务层通过接口的方式调用,使得DAO层和业务层能够解耦。

Java代码
  1. package  com.cvicse.Test;  
  2.   
  3. import  com.cvicse.dao.CourseDAO;  
  4. import  com.cvicse.daofactory.DaoFactory;  
  5.   
  6. /**  
  7.  * @author Administrator  
  8.  *   
  9.  */   
  10. public   class  ServiceClient {  
  11.   
  12.     /**  
  13.      * @param args  
  14.      */   
  15.     public   static   void  main(String[] args) {  
  16.         // TODO Auto-generated method stub   
  17.         try  {  
  18.             CourseDAO courseDao = (CourseDAO) DaoFactory.getInstance().getDAO(  
  19.                     "courseDao" );  
  20.         } catch  (Exception e) {  
  21.             // TODO Auto-generated catch block   
  22.             e.printStackTrace();  
  23.         }  
  24.     }  
  25. }  
package com.cvicse.Test;

import com.cvicse.dao.CourseDAO;
import com.cvicse.daofactory.DaoFactory;

/**
 * @author Administrator
 * 
 */
public class ServiceClient {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		try {
			CourseDAO courseDao = (CourseDAO) DaoFactory.getInstance().getDAO(
					"courseDao");
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

 

总结:在这个DAO设计模式中,涉及到很多java的基础知识,同时,也涉及太多的模式。只有灵活应用,才能体会的其中的灵活。关于DAO具体实现可以采用spring的simpetempate会更能简化其中的实现。

DAO(Data Access Object,数据访问对象)模式是一种常用的设计模式,主要用于封装对数据库或其他持久化存储机制的操作。通过引入DAO层,应用程序的业务逻辑与数据访问逻辑得以分离,提高了程序的可维护性和灵活性。 ### DAO 模式的主要特点: 1. **职责单一**:DAO 类负责所有与特定实体相关的 CRUD (Create, Read, Update, Delete) 操作,并将这些操作从其他应用组件中隔离出来。 2. **统一接口**:为不同的数据源提供一致性的访问接口,无论底层的数据存储是基于文件系统、SQL 数据库还是 NoSQL 等形式。 3. **事务管理透明化**:对于需要跨多个资源协调工作的场景,如分布式系统的两阶段提交协议,DAO 可以让客户端不必关心具体的事务控制细节。 4. **增强复用性及测试便利度**:由于其独立于业务规则的存在,因此可以更方便地进行单元测试并促进代码重用。 #### 实现步骤 - 定义 `Dao` 接口用于声明通用方法; - 根据需求创建相应的实现类 (`UserDaoImpl`, `OrderDaoImpl`) 来完成具体功能; - 使用工厂模式或依赖注入的方式获取 Dao 对象实例; - 在 Service 层调用对应的 Dao 方法来进行增删改查等动作; ```java // User.java - Entity Class public class User { private Long id; private String name; // Getters and Setters... } // UserDao Interface interface UserDao { void add(User user); List<User> findAll(); Optional<User> findById(Long userId); boolean update(User updatedUser); int deleteById(Long userId); } // UserDao Implementation with JDBC or ORM framework like Hibernate etc. class UserDaoJdbc implements UserDao{ @Override public void add(User user){/*...*/} @Override public List<User> findAll(){/*...*/} @Override public Optional<User> findById(Long userId){/*...*/} @Override public boolean update(User updatedUser){/*...*/} @Override public int deleteById(Long userId){/*...*/} } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值