Java泛型Dao学习笔记

Java泛型Dao学习笔记:
针对数据库表中的共有字段(比如:id,title,name)。

设计泛型Dao:

public class BaseDao<T> {

    private String tableName;
    private Class clazz;

    //通过反射泛型,得到具体的参数类型
    protected BaseDao() {
        //得到字节码对象                       
        //Class baseDaoClass = BaseDao.class;这样会报错的,
        Class baseDaoClass = this.getClass();
        //得到BaseDao的泛型类型
        Type type = baseDaoClass.getGenericSuperclass();
        //把BaseDao的泛型类型转为ParameterizedTyp参数化类型
        ParameterizedType pt = (ParameterizedType) type;
        //从参数化类型带得实际具体类型
        Type actualType = pt.getActualTypeArguments()[0];
        //强转为字节码对象
        this.clazz = (Class) actualType;/////////////////

        String className = actualType.getTypeName().toLowerCase();
        tableName = className.substring(className.lastIndexOf(".")+1);
    }

    public T findTById(int id) throws SQLException {
        T t = null;
        String sql = "select * from " + tableName + " where id = ?;";
        QueryRunner runner = new QueryRunner(JdbcUtil.getDatasource());
        t = (T) runner.query(sql, new BeanHandler(clazz), id);
        return t;
    }
}

我对Class baseDaoClass = BaseDao.class;会报错的理解:(先来看完下面代码)

继承泛型Dao类:

如:TopicDao;ReplyDao;TypeDao只需要继承BaseDao,并确定泛型参数

public class TopicDao extends BaseDao<Topic> {
}
public class ReplyDao extends BaseDao<Reply>{
}
public class TypeDao extends BaseDao<Type> {
}

具体使用:

public class DoTest {
    @Test
    public void doTest () throws SQLException{
        TypeDao typeDao = new TypeDao();
        Type type = typeDao.findTById(1);
        System.out.println("id+title:"+type.getId()+":"+type.getTitle());
        System.out.println("==============================================");

        TopicDao topicDao = new TopicDao();
        Topic topic = topicDao.findTById(1);
        System.out.println("id+title:"+topic.getId()+":"+topic.getTitle());
        System.out.println("==============================================");

        ReplyDao replyDao = new ReplyDao();
        Reply reply = replyDao.findTById(1);
        System.out.println("id+title:"+reply.getId()+":"+reply.getTitle());
        System.out.println("==============================================");

    }

}

我对Class baseDaoClass = BaseDao.class;会报错的理解:

//得到字节码对象                       
//Class baseDaoClass = BaseDao.class;这样会报错的,
Class baseDaoClass = this.getClass();
//得到BaseDao的泛型类型
Type type = baseDaoClass.getGenericSuperclass();

为了方便这里将如上两行代码写成合并形式进行比较:

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

getGenericSuperclass()的到的是父类的泛型类型.
BaseDao的直接父类我们认为是Object,他是没有带泛型信息的,所以会报错。
而this.getClass()就比较有意思了,在使用时候,当TopicDao;ReplyDao;TypeDao任意一个创建实例对象的时候,构造函数会通过Super()调用的父类的构造函数,这里要明白一点,是谁在调用父类的构造方法?答案肯定是子类对象啦。子类对象调用Super()方法,当然,父类构造函数中的this还是指向调用者啦(this代表调用者),也就是子类对象啦。这时候this就有了具体的指向,就是子类实例对象。当然这是站在子类的视角上。如果直接BaseDao bd = new BaseDao(),这是后this.getClass()和BaseDao.class无差别,也会报错。
子类创建实例时候子类中的this和super中的this都是同一个,都只想当前调用者,这里只能用this或者super。目的是通过子类得到父类泛型类型。
所以this很有意思,BaseDao的子类创建实例时,这个this指向的是调用者。

这里我参考了一点资料
大家可以参考一片文章《为什么Java中子类对象和父类对象的hashcode相同? 》
原文链接:http://bbs.csdn.net/topics/392021100?page=1
为了方便,我粘过来了。

class A{
    public A(){
        System.out.println("father's hashcode : "+this.hashCode());
    }
}

class B extends A{
    public B(){
        System.out.println("child's hashcode : "+this.hashCode());
    }
}
public class test{
    public static void main(String[] args){
        new B();
    }
}
==============================
father's hashcode : 1043390835
child's hashcode : 1043390835

请看某位大神解答:

this:
 这个关键字始终代表的是调用者,如下伪代码:
    A类有方法hashCode(){ System.out.println( this.hashCode());}
    创建对象a后
   调用:a.hashCode(),其中this就是代表a
在上面代码中,new一个子类的对象时会调用子类中对应的构造方法,在编译后生成.class文件中子类的构造方法会有点变动对应的java代码如下:
public B(){
                super();
System.out.println("child's hashCode:" + this.hashCode());
}
这里所加的super();是调用了父类中的构造方法,但是这个父类的构造方法并不是由父类的对象调用的,而是由子类的对象b(注意一个对象在内存中代表一段空间,在创建对象的第一步就是分配空间,生成hash码值,再从创建对象到调用构造函数的过程中虚拟机肯定还做了很多工作)调用构造方法,在执行构造方法的过程中由调用了父类的构造方法,整个过程中并没有创建父类的任何对象,所以调用者还依旧是b对象整个执行的过程中的两个this指针都是对象b,所以最终的hashcode是一样的(为什么在子类对象能调用父类的构造方法而其非子类之间没办法调用? 因为java继承的这个功能就是这样设计的,到此就可以点到为止,等楼主的功力更上几层楼时在去深入研究JVM)

再方法执行的过程中可能会调用其他方法,可能会通过其他对象调用其他方法,也可能通过其他手段如super关键字来调用父类的方法,但this代表的始终是方法的调用者,只有通过对象调用带有this关键字的方法,this才会代表这个对象,否则代表的还是以前的那个对象
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Struts2、Hibernate、Spring整合的泛型DAO (本人评价: 代码开发效率提高30% 代码出错率减少70%) 对于大多数开发人员,系统中的每个 DAO 编写几乎相同的代码到目前为止已经成为一种习惯。虽然所有人都将这种重复标识为 “代码味道”,但我们大多数都已经学会忍受它。能不能不写重复的dao 呢 ? 泛型dao,顾名思义就是一个dao可以对多个实体对象进行持久化。当应用中需要使用到上十张表时,DAO的维护变得日益困难,主要表现在这几个方面: 1)dao类的繁多,很多设计都是一个entity对应一个dao (不同的只有类名和方法名) 2)dao接口需要维护的method庞大。 3)业务逻辑改变时,dao需要同时修改两个类文件(接口和实现类) 在本文中,我将为您展示如何避免再三地重复 DAO 代码。 在这里我建议项目最好使用一个共通的DAO,因为这样会为你省去非常多的类,而那些类里的逻辑往往差不多。当然是用共通的DAO你需要对结果转型,转成你需要的bean,但这也比写那么多DAO强多了,你可以放下包袱,只关注你的业务逻辑。 如果你真能只用一个dao解决,那么祝贺你,你得到了一个虚拟数据层(高度抽象的数据接口)。这是一个比dao更高级的存在。 欢迎大家指正 -_- 虚心求教 代码层次: bean-->dao-->service-->action 技术概述:1.继承 继承是利用现有的类创建新类的过程,现有的类称作基类(或父类),创建的新类称作派生类(子类)。继承其实就是自动地共享基类中成员属性和成员方法的机制。引入继承,实现了代码重用; 2.泛型 泛型类型的限定 3.反射 代码概述: bean :Person.java 这个人员类我就不说了 泛型dao接口 :GenericDao 泛型作为DAO的通用接口 CRUD方法 dao接口 : PersonDAO extends GenericDao 可以不写代码,方法已经在父类泛型dao里了,这里为了说明:可扩展添加 findByNameExact()方法 子类的附加方法。 泛型daoimpl :GenericDaoImpl implements GenericDao 必须提供的构造方法,以便创建实例的时候就知道具体实体的类型。 daoimpl :PersonDAOImpl extends GenericDaoImpl implements PersonDAO public PersonDAOImpl() { super(Person.class); } 告诉对哪个类操作,如不需要自定义扩展方法就作有一个构造方法。 泛型Service:GenericService.java泛型dao没有区别 Service :PersonService.java 直接继承。 泛型serviceimpl与serviceimpl实现和dao层实现一样。 Action : SavePersonAction直接调用PersonService。 下面是代码 为了演示减少代码量而且直观去掉些方法方便读者自己扩展写出适合自己的代码,这里我只抛砖引玉了。主要介绍这个技术。 本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/zylyueliang/archive/2010/09/17/5890043.aspx
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值