引入:
在需求中,数据库有两张表user,admin。我们要查询里面的id,name等信息通常都是写两个dao,然后分别给每个查询字段写一套方法。
然而其实查询这些字段的方法都大同小异,所以产生了一个更好的解决办法,就是写一个通用的dao,然后把相同的方法写在通用的dao(genericDao)里,然后然实体dao去继 承它。
下面通过模拟 贴出一般做法 和 优化后的做法:
首先 在数据库里建好两张表,分别为user和admin,再插入一些数据
CREATE TABLE USER(
id INT PRIMARY KEY,
userName VARCHAR(20),
age INT
);
CREATE TABLE admin(
id INT PRIMARY KEY,
adminName VARCHAR(20),
status_ INT
);
INSERT INTO USER VALUES(1,'李四',21);
INSERT INTO USER VALUES(2,'张三',20);
INSERT INTO admin VALUES(1,'超级管理员',1);
INSERT INTO admin VALUES(2,'普通管理员',0);
截下来写两个实体类
public class admin {
private int id;
private String adminName;
private int status_;
public admin() {
super();
// TODO Auto-generated constructor stub
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getAdminName() {
return adminName;
}
public void setAdminName(String adminName) {
this.adminName = adminName;
}
public int getStatus_() {
return status_;
}
public void setStatus_(int status_) {
this.status_ = status_;
}
@Override
public String toString() {
return "admin [id=" + id + ", adminName=" + adminName + ", status_=" + status_ + "]";
}
}
public class user {
private int id;
private String userName;
private int age;
public user() {
super();
// TODO Auto-generated constructor stub
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "userDao [id=" + id + ", userName=" + userName + ", age=" + age + "]";
}
}
一般做法
public class adminDao{
public admin getById(int id)
{
QueryRunner qr=jdbcUtil.getQueryRunner();
try {
return (admin)qr.query("select * from admin where id=", new BeanHandler(admin.class),new Object[]{id});
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new RuntimeException(e);
}
}
@Test
public void testId()
{
adminDao adminDao = new adminDao();
admin byId = adminDao.getById(2);
System.out.println(byId);
}
}
public class userDao extends genericDao<user>{
public user getById(int id)
{
QueryRunner qr=jdbcUtil.getQueryRunner();
try {
return (user)qr.query("select * from user where id=?", new BeanHandler(user.class),new Object[]{id});
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new RuntimeException(e);
}
}
@Test
public void testId()
{
userDao userDao = new userDao();
user byId = userDao.getById(2);
System.out.println(byId);
}
}
利用泛型优化后的做法:
首先写一个genericDao
**
* 通用的dao方法
* @author Administrator
*
*/
public class genericDao <T>{
private Class clazz;
private String tableName;
public genericDao(Class clazz,String tableName)
{
this.clazz=clazz;
this.tableName=tableName;
}
public T getById(int id)
{
QueryRunner qr=jdbcUtil.getQueryRunner();
try {
return (T)qr.query("select * from "+tableName+" where id=?", new BeanHandler(clazz),new Object[]{id});
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
然后让实体Dao类分别继承它public class adminDao extends genericDao<admin>{
public adminDao() {
super(admin.class, "admin");
}
@Test
public void testId()
{
adminDao adminDao = new adminDao();
admin byId = adminDao.getById(2);
System.out.println(byId);
}
}
public class userDao extends genericDao<user>{
public userDao() {
super(user.class, "user");
}
@Test
public void testId()
{
userDao userDao = new userDao();
user byId = userDao.getById(2);
System.out.println(byId);
}
}
利用泛型反射技术优化后的做法
generic类
/**
* 通用的dao方法
* @author Administrator
*
*/
public class genericDao <T>{
private Class clazz;
private String tableName;
public genericDao()
{
System.out.println(this);//this 指当前运行的类对象 如果有子类继承它,则它指的是子类,而不是generic本身类
System.out.println(this.getClass());//获得当前运行类的字节码
System.out.println(this.getClass().getSimpleName());//获得当前运行类的类名
System.out.println(this.getClass().getSuperclass());//获得当前运行类的父类的字节码
System.out.println(this.getClass().getGenericSuperclass());//获得参数化类型 reflect.genericDao<reflect.admin>
/**
* 参数化类型:genericDao<reflect.admin>
* 实体类型:reflect.admin
*/
//1.先获得当前运行类的泛型父类类型
Type type = this.getClass().getGenericSuperclass();
//2.强转为参数化类型
ParameterizedType p=(ParameterizedType)type;
//3.获取参数化类型中,实际类型的定义
Type[] actualTypeArguments = p.getActualTypeArguments();
//获取数组的第一个元素,即我们想要的实际类型的字节码类型
clazz=(Class<T>) actualTypeArguments[0];
//给表名赋值
tableName=clazz.getSimpleName();
}
public T getById(int id)
{
QueryRunner qr=jdbcUtil.getQueryRunner();
try {
return (T)qr.query("select * from "+tableName+" where id=?", new BeanHandler(clazz),new Object[]{id});
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
简化后的dao类
public class userDao extends genericDao<user>{
@Test
public void testId()
{
userDao userDao = new userDao();
user byId = userDao.getById(2);
System.out.println(byId);
}
}
public class adminDao extends genericDao<admin>{
@Test
public void testId()
{
adminDao adminDao = new adminDao();
admin byId = adminDao.getById(2);
System.out.println(byId);
}
}
得出结论:子类继承父类,并传一个实际类型给父类,父类可以在类中通过反射技术先获得参数化类型,再获得参数化类型中的实际类型。即xxx.class