天天看点

java basedao 泛性反射_泛型的补偿实例--使用泛型反射创建BaseDao

对于Java泛型,我们知道两点:

1.      泛型是JDK1.5以后才有的,可以在编译时期进行类型检查,将类和方法与所使用的类型之间的约束关系进行了解耦,从而可以编写更通用的代码。

2.      泛型只在编译时期有效,编译后的字节码文件中不存在有泛型信息!如果需要在运行时使用类型信息,需要显式地传递你的类型的Class对象来对泛型进行补偿。

下面的BaseDao就是通过泛型的反射来获得运行时的类型信息,从而编写更为通用的代码。

泛型反射涉及的API

包名:java.lang.reflect

接口 Type

已知子接口:

ParameterizedType

所有已知实现类:

Class

包名java.lang.reflect

接口 ParameterizedType

getActualTypeArguments()

返回表示此类型实际类型参数的 Type 对象的数组。

什么是参数化类型

ArrayList这种形式就是参数化类型

BaseDao代码

其中连接池使用C3P0;

约定:

1. 实体类名  -  表名

2. 实体属性名  -  表中字段名

3. 主键名称必须叫id

import java.lang.reflect.ParameterizedType;

import java.lang.reflect.Type;

import java.sql.SQLException;

import java.util.List;

import org.apache.commons.dbutils.handlers.BeanHandler;

import org.apache.commons.dbutils.handlers.BeanListHandler;

import util.*;

public class BaseDao {

// 保存当前运行类的参数化类型中的实际的类型

private Class clazz;

// 表名 约定表名就是实体类名 -- 在C#的BaseDAL中,是通过Lamda表达式传入表名的

private String tableName;

// 构造函数: 1. 获取当前运行类的参数化类型;

// 2. 获取参数化类型中实际类型的定义(class)

public BaseDao() {

// this 表示当前运行类 (AccountDao/AdminDao)

// this.getClass() 当前运行类的字节码对象(AccountDao.class/AdminDao.class)

// this.getClass().getGenericSuperclass(); 当前运行类的父类,即为BaseDao

// 其实就是“参数化类型”, ParameterizedType

//返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的直接超类的 Type

Type type = this.getClass().getGenericSuperclass();

// 强制转换为“参数化类型” 【BaseDao】

ParameterizedType pt = (ParameterizedType) type;

// Class类是Type接口的实现类

// 获取参数化类型中,实际类型的定义 【new Type[]{Account.class}】

Type types[] = pt.getActualTypeArguments();

// 获取数据的第一个元素:Accout.class

clazz = (Class) types[0];

// 表名 (与类名一样,只要获取类名就可以)

tableName = clazz.getSimpleName();

}

@SuppressWarnings({"unchecked"})

public T findById(int id) {

String sql = "select * from " + tableName + " where id=? ";

try {

return JdbcUtils.getQuerrRunner().query(sql,

new BeanHandler(clazz), id);

} catch (SQLException e) {

throw new RuntimeException(e);

}

}

public List getAll() {

String sql = "select * from " + tableName;

try {

return JdbcUtils.getQuerrRunner().query(sql,

new BeanListHandler(clazz));

} catch (SQLException e) {

throw new RuntimeException(e);

}

}

}

这样写完之后存在一个明显的问题,那就是前面的约定约束性太强了,如果数据库表和实体类名不是对应关系,该怎么做呢?