- 浏览: 762348 次
- 性别:
- 来自: 深圳
文章分类
- 全部博客 (241)
- 个人思考 (1)
- 数据库 (5)
- java基础 (32)
- 软件工程 (2)
- zk开源框架 (15)
- 设计模式 (25)
- javascript (12)
- css (9)
- UML (2)
- CMMI软件需求 (3)
- CMMI软件设计 (2)
- CMMI软件实现 (1)
- CMMI软件测试 (1)
- 正则表达式 (4)
- 系统日志配置 (4)
- 应用服务器 (1)
- spring (7)
- XML (6)
- java web (10)
- Ajax (3)
- RichFaces (14)
- 问题 (1)
- 评论文章 (2)
- fushioncharts (2)
- MAVN (4)
- jquery (26)
- Ext js学习 (2)
- 学习心得 (2)
- CSS兼容问题 (3)
- XSL-FOP (1)
- Quartz (0)
- OSGI (1)
- spring--security (6)
- apache tools (1)
- eclispe 小技巧 (2)
- Ant (1)
- 杂记 (1)
- spring3系列 (5)
- java cache (4)
- EffectiveJava (2)
- 代码重构 (0)
最新评论
-
psz6696:
可以说是超级简单的Demo了,可惜没有演示设值注入和构造注入两 ...
模拟spring中的ClassPathXmlApplicationContext类的实现 -
ziyourJava:
[flash=200,200][img][url][list] ...
spring security进级篇 V 自定义标签控制显示 -
ztw1122:
...
zk组件开发指南(目录) -
zjysuv:
容我说一句 在座的各位都是垃圾 spring 3.2以后的@C ...
三. spring mvc 异常统一处理 -
chengwu1201:
二 基于Spring的异常体系处理
虽然DAO模式已经有了好多的成熟的框架,但它仍然是一个比较重要的设计模式。要做一个比较合理的DAO模式,你需要对工厂模式、单例模式、模板模式、策略模式、代理模式、泛型、反射机制、输入输出、异常等知识比较熟悉。下面结合自己理解,设计一个DAO设计模式的例子,希望大家给与指正。
1、数据库连接池的工具类。
在数据库连接池的工具类中,采用了开源的DBCP数据库连接池,调用了DataSource接口,DBCP中关于Datasource的Connection采用了动态代理的方式实现,在这里只是提出,感兴趣可以查看其源码,该工具类采用可配置的方式实现的,代码如下:
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
#连接设置 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层的必要异常都抛出。
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类
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层的操作能和业务层解耦。
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层的常用操作类进行提取。
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通用操作类中定义接口,用于对象的转化。
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操作的实现类中,我们采用了策略模式。
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、我们定义工厂类,在定义工厂类,考虑到通用性,我们采用了反射机制加配置文件的形式来实现的。同时,在工厂模式中引入了饿汉式单例模式。
/** * */ 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
courseDao=com.cvicse.dao.impl.CourseDAOImpl studentsDao=com.cvicse.dao.impl.StudentDAOImpl
8、业务层的调用方式,这里用客户端方式模拟的。在业务层通过接口的方式调用,使得DAO层和业务层能够解耦。
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会更能简化其中的实现。
评论
autoCommit 有意义吗? 通常会把connection autoCommit设置为false,等做完一段操作后 connection。commit() 这不就实现了transcation事务么
如果在代码中编写事务的话,有使用Connection类的autoCommit的设置方式,还有使用SUN的JTA处理...不过这是很久以前看的一篇文章说的了~还有的话请楼下补充~
现如今很少有人愿意把代码拿上来讨论了; 不管是什么模式,那些几乎每个项目里都要或多或少重复写的代码,都需要我们把逻辑抽象出来,然后可以封装成自己的代码片断或者库! 我们的目标都是快速高效地解决问题。
关于RowMapper的例子大家给我说看commons dbutil 我会学习的,关于事务处理希望给出意见。
DaoOperateTemplate, 可以看看 spring 的 jdbcTemplate;再将DaoOperateTemplate壮大,成为自己的代码库.
先赞一个 lz 的敬业精神。
代码量我希望少少的!
但是要在质量上有保证!
而且又像jQuery的口号一样!
这是我的想法!
感觉太啰嗦了,什么设计模式,什么....
匿名内部类很丑陋,感觉可以写个通用类,自动匹配
Spring的依赖注入我觉得更像静态工厂方法吧(没看过Spring源码),也是去读取配置文件...
控制反转(IoC)是一种理论,依赖注入(DI)是实现IoC的一种方式而已,并不重复...
如果lz可以把,RowMapper做的更好直接用到第三方BeanUtils的组件,根据查询的结果自动封装。更好 。。。仅做学习
相关推荐
DAO(Data Access Object)设计模式是软件开发中一种常见的用于处理数据访问的模式,它将业务逻辑与数据访问逻辑分离,使得代码结构更加清晰,更易于维护和测试。在Java开发中,DAO模式广泛应用于数据库操作,为应用...
DAO(Data Access Object)设计模式是一种在Java编程中常见的软件设计模式,主要目的是为了将业务逻辑与数据访问操作分离,从而提高代码的可重用性和可维护性。这个压缩包文件"DAO设计模式辅助资料"显然是为了帮助...
DAO(Data Access Object)设计模式是一种软件设计模式,它用于封装对数据库的所有访问,从而将业务逻辑和数据访问逻辑分离开来。DAO模式的核心思想是创建一个接口或抽象类,代表一个特定的数据操作,然后创建该接口...
DAO(Data Access Object)设计模式是一种在软件工程中常见的用于处理数据访问的模式,它将业务逻辑和数据访问逻辑分离,使得系统更加模块化,提高了代码的可复用性和可测试性。在这个“DAO设计模式(工厂+代理)”...
**JSP+Servlet+AJAX DAO设计模式详解** 在Web开发中,DAO(Data Access Object)设计模式是一种常用的设计模式,用于将业务逻辑与数据访问层进行解耦,提高代码的可维护性和可复用性。本篇我们将深入探讨如何在JSP...
DAO(Data Access Object)设计模式是一种在软件工程中用于封装对数据库访问的模式,它将业务逻辑和数据访问逻辑分离,提高代码的可重用性和可测试性。在这个基于DAO设计模式的新闻发布系统中,我们可以深入探讨以下...
DAO(Data Access Object)设计模式是一种在软件开发中用于封装对数据库操作的模式,它将数据访问逻辑与业务逻辑分离,使得系统更易于维护和扩展。在这个设计模式中,DAO作为数据层,提供了对数据库的一系列原子性...
### DAO设计模式详解 #### 一、概述 数据访问对象(Data Access Object,简称DAO)设计模式是一种在软件工程特别是企业级应用开发中非常常见的设计模式。它的主要目的是分离业务逻辑与数据访问逻辑,使系统架构...
DAO设计模式是Java开发中常用的一种数据访问模式,它将底层数据访问操作与上层业务逻辑相分离。这一模式的目的在于封装所有对数据源的访问,并提供抽象接口,使得业务逻辑层与数据访问层解耦,从而降低业务代码与...
DAO(Data Access Object)设计模式是Java Web开发中常用的一种设计模式,它的主要目的是将业务逻辑与数据访问操作分离,提高代码的可复用性和可维护性。在本精讲中,我们将深入探讨DAO设计模式的原理、实现方式以及...
**DAO设计模式详解** 在Web开发中,DAO(Data Access Object)设计模式是一种常见的用于分离业务逻辑层与数据访问层的架构模式。DAO的主要目的是为了提供一个统一的接口,使得业务逻辑组件可以与数据库交互而无需...
### J2EE学习笔记——DAO设计模式基础 #### 一、引言 在J2EE(Java 2 Enterprise Edition)开发中,DAO (Data Access Object) 设计模式是一种常用的数据访问层实现方式,用于分离业务逻辑与数据访问逻辑,使得程序...
JAVA+DAO 设计模式详解 在软件开发中,数据持久化是一个非常重要的步骤,特别是在WEB应用程序中。为了解决数据持久化的问题,开发者通常会采用各种设计模式,其中DAO(Data Access Object)设计模式是一个非常流行...
DAO(Data Access Object)设计模式是一种在软件工程中常见的用于处理数据访问的模式,它将业务逻辑与数据访问操作分离,使得系统更加模块化,提高了代码的可复用性和可测试性。在这个“李兴华 DAO设计模式 实现 增...
### Java DAO 设计模式 #### 一、DAO设计模式的概念 **DAO**(Data Access Object)设计模式是一种在Java EE环境中广泛使用的数据访问模式,它主要应用于处理数据存储组件的交互。这种模式的主要目的是将底层数据...
Java DAO(Data Access Object)设计模式是一种常用的软件设计模式,用于在Java应用程序中与数据库进行交互。DAO模式的主要目的是为了实现数据访问层的隔离,它将业务逻辑与数据存储细节分离开来,使得代码更加模块...
暴露给客户端的DAO接口在低层数据源的实现发生改变时并不会随着改变,所以这种设计模式使得DAO可以适应不同的数据储存方式类型而不影响客户端和商业组件.最主要的, DAO还在组件和数据源之间扮演着协调者的角色. DAO...
DAO(Data Access Object)设计模式是一种在Java编程中常见的用于处理数据访问的模式,它将业务逻辑组件与数据访问逻辑分离,提供了一种抽象层,使得应用代码与具体的数据存储方式解耦。DAO模式的核心思想是创建一个...