dao设计模式对mysql的crud_DAO设计模式(希望大家指正)

虽然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

#

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 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 Query(String sql, Object[] args, RowMapper rowMapper)

throws DaoException {

Connection conn = null;

PreparedStatement ps = null;

ResultSet rs = null;

List results = new ArrayList();

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 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会更能简化其中的实现。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值