通用DAO类

本文探讨了在MVC架构中,为避免针对每个数据库表重复编写DAO类,如何通过泛型和反射机制抽象出通用DAO实现类。基础部分介绍了DAO模式的组成部分,如VO、DAO接口、DAOFactory和DAOImpl。思考部分分析了实现通用DAO的关键难点,尤其是实体类的方法调用。关键技术部分讲解了Java反射的应用,用于在运行时动态获取和调用对象的方法。详细设计部分则未展开,而测试部分则意味着对通用DAO类的功能验证。
摘要由CSDN通过智能技术生成

基础:

一般编写MVC的数据持久化层是使用DAO模式。所谓DAO,也就是Data Access Object(数据访问接口)。DAO与业务逻辑层传递的是一个实体对象,而这个实体对象是数据库表在程序中的一个映射。

所以对于数据库中要操作的每一张表,都要建立一个VO(实体对象)类,一个DAO接口,一个创建DAO的工厂类,以及一个DAO的实现类。而这些基本是一样的,如果程序需要访问多个表的时候,需要大量的重复劳动。就有了抽象出来的必要

 

思考:

首先分析DAO模式中的每一部分

VO(对象实体):这个类成员变量与数据库中每个字段一一对应,同时提供了相应是set和get方法来设置或取得数值。这个类一般是通过IDE自动生成的

DAO(数据访问接口):这个是业务逻辑层使用数据持久化层服务的一个接口

DAOFactory(工厂类):它提供了创建DAO类的一个方法,目的是更改数据持久化层实现时(比如更换数据库),不需要对业务逻辑层进行更改,只要再创建一个实现了DAO接口的类,再交给DAOFactory创建对象就可以了。为程序提供了更好的扩充性

DAOImpl(实现类):这个类实现了DAO接口。同时也是代码最多的类。

从上文分析看出,抽象DAO首先要从实现类下手。在不同的表中,DAO提供的操作基本类似,所以实现类所实现的方法基本相同,不同的地方主要有这样几个方面:

1、传递的实体类类型

2、实体类的取值赋值方法

3、SQL语句

这些问题第一个解决起来最容易,可以通过Java的泛型解决。第三个也比较容易,可以在创建时传入字段,执行时生成SQL语句。只有第二个最困难,因为并不知道实体类提供哪些方法,以及方法的返回值和参数列表,怎么样去调用未知的方法?

 

关键技术:

Java为我们提供了反射机制,来进行一些对象的操作。

 

比如通过这个方法可以让加载器加载一个类:

Class c = Class.forName(className);

得到Class对象以后,我们可以调用它的公有的无参构造方法,获得它的一个实例

Object o = c.newInstance();

也可以获得描述它所有方法的一个数组

Method[] m = c.getMethods();

也可以得到某一个方法的方法名

System.out.println(m[0].getName());
或者对一个方法的参数列表及返回值类型的描述
System.out.println(m[0].toGenericString());
通过以上方法,可以分析出哪个方法是我们想要的方法,我们怎么调用它呢
public Object invoke(Object obj, Object... args)

参数:
obj - 从中调用底层方法的对象
args - 用于方法调用的参数
返回:
使用参数 argsobj 上指派该对象所表示方法的结果

通过这个方法,在第一个参数传入一个创建的对象,2~n个参数传入调用方法的参数,就可以调用这个方法,
同时也可以接受得到Object类型的返回值。想了解更详细的内容可以参考JDK API
理解了以上的函数,我们可以动手编写这个类了
 

详细设计:

为了更规范,我们希望用户创建的VO类都有一个标志,所以我们创建一个接口,这个接口不需要实现任何方法,只起一个标记作用
package generalDAO;

/**
 * 实体类标记接口
 * 
 * @author 石莹
 *
 */
public interface VO {

}
 
因为是通过方法名的字符串来确定我们究竟要调用哪个方法,如果VO类并不是符合我们规范的类,应该抛出一个异常
package generalDAO;

/**
 * VO类不符合规范异常
 * @author 石莹
 *
 */
public class VOClassIllegalException extends Exception {

	private static final long serialVersionUID = 861316221880365983L;

	public VOClassIllegalException() {
		
	}
	
	public VOClassIllegalException(String str) {
		super(str);
	}
}
 
下面就是主要的部分,注释已经非常清楚
package generalDAO;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;

import connectionPool.ConnectionPool;


/**
 * 通用DAO类
 * 
 * 通过这个类,只需要按照命名约定编写一个实现了VO接口的实体类,就能操作数据库中相应的表
 * 方便的同时必然带来性能的降低。类的实现使用了Java的一些底层特性,可以供初学者学习
 * 
 * 使用DAO类必须遵循以下约定:
 * 
 * 1、所有实体类必须实现VO接口
 * 2、实体类的类名必须和数据库表名一致
 * 3、当实体类中同时存在getXXX()和setXXX()方法时,XXX可被识别为一个字段
 * 4、实体类中的字段名必须和数据库中的字段名一致
 * 5、主键必须使用“表名 + Id”的命名规则
 * 6、目前支持的类型:float,String,int
 * 
 * 另:使用需要传入我编写的一个简单的数据库连接池,请参考这里
 * http://blog.csdn.net/lingdushanke/archive/2010/09/11/5877163.aspx
 * 
 * (2010.9.19)
 * 
 * @author 石莹
 * @version 1.0
 *
 */
public class DAO {


	/** 数据库连接池 */
	private ConnectionPool connectionPool = null;

	/**
	 * 加载后的实体类
	 */
	@SuppressWarnings("unchecked
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值