首页  »   数据库

DBUtils学习小结

网友分享于:2015-04-24  浏览:0次
DBUtils学习总结
这几天闲着无聊,就看了一下DBUtils这个数据库组件。中间有了一些想法,现在记录下来。
文章主要分几部分
1 最简单同时也是最经常使用的一些范例
2 学习源码前的一些知识储备
3 我自己写的mydbutils
4 两相比较
5 分析源码

 最简单同时也是最经常使用的一些范例

   看这个就OK
   http://www.cnblogs.com/xdp-gacl/p/4007225.html



学习源码前的一些知识储备


  1反射
  网上资料有很多,大家自己去看。

  2内省
  大家可以认为内省就是java对bean反射的再次包装。
  bean是什么我就不说了吧。
   http://blog.csdn.net/x605940745/article/details/20240959
   看上面的代码就知道怎么用了。

  3泛型
  为什么要使用泛型?
  http://www.cnblogs.com/panjun-Donet/archive/2008/09/27/1300609.html
  下面是我自己的一点理解
  Map m = new HashMap();
  m.put("key", "blarg");
  String s = (String) m.get("key");
  第三行代码需要转换类型
  如果我写成这个样子
  Map<String,String> m=new Hashmap<String,String>();
  m.put("key1","blarg");
  String s=m.get("key1");
  第三行就不需要转换了。我再声明map的时候就指定了它内部能存放(也只能存放)的数据类型。
  准确的说,就是在 通过知道使用泛型定义的变量的类型限制,编译器可以在一个高得多的程度上验证类型假设。

  对于泛型的使用,我认为大家多参考集合类,就OK了。
  我自己在看泛型的时候出了两个问题
 public <T> T getObject(Class<T> c) throws Exception{
    T t=c.newInstance();
    return t;
  }
  方法签名中,T就已经指明了返回的类型,那么<T>不就多余了吗?



  更详细的资料见:
  http://www.cnblogs.com/iyangyuan/archive/2013/04/09/3011274.html

  后来再看hashmap的源码时,发现get方法的签名就没有中就没有简括号
      HashMap.java
      public V get(Object key) {
        if (key == null)
            return getForNullKey();
        Entry<K,V> entry = getEntry(key);

        return null == entry ? null : entry.getValue();
    }
    通过查看<<java核心技术>>得到这样一个结论
    在泛型类中定义的泛型方法,其方法签名中不需要使用尖括号
    在普通类中定义的泛型发放,就得用<T>,来指示:这个方法是一个泛型方法。

 

自己写mydbutils

  我在泛型这里又遇到了一个问题。
  hashmap定义的时候,泛型写在了尖括号里。
  Map<String,String> m=new Hashmap<String,String>();
  而我自己定义的BeanHandler<T>,new的时候,参数就得放在园括号里
  new BeanHandler<>(Student.class)
  public class BeanHandler<T> implements ResultSetHandler<T>{

    private Class<T> type;
    
      public BeanHandler(Class<T> type){
     this.type=type;
      }
      ..../
  }
  为什么?
  想明白后,我就想抽自己。
  你们自己想想为什么new BeanHandler的时候泛型要放在圆括号里。
  另外,如果我想改成hashmap那种形式,怎么改?
  具体见下文
http://blog.csdn.net/dlf123321/article/details/45173505

 两相比较

   看看dbutils的设计思路
   http://blog.csdn.net/dlf123321/article/details/45203171
   看看我写的代码,与dbutils的源码,我认为至少有一下几个不同。
   1 源码考虑到了异步的数据库操作,因而有了AsyncQueryRunner。并且在AsyncQueryRunner与QueryRunner中提取了父类---AbstructQueryRunner。并且把关闭数据库资源,获得preparestatement,填充preparestatement等操作提炼到了父类中。


   2 源码中BeanHandler中持有一个RowProcessor对象,用来转换ResultSet到Bean,Map,List<Bean>等等,这这部分,我的代码中使用了静态方法

   public static <T> T creatBean(ResultSet rs, Class<T> type);
   仔细对比一下,源码中的方式还是比较好,专门有一个类做转换的工作,更加符合面向对象的思想。


   3 在转换的过程中,我使用的是最基础的反射方法:

   String methodName = "set"+filedName.substring(0, 1).toUpperCase()+ filedName.substring(1);
   Method m = class.getDeclaredMethod(methodName, filedType);
   其实在阅读DBUtils源码之前,我确实不知道还有内省这个东西。
   对应的代码转换成:
   Method setter = PropertyDescriptor.getWriteMethod();
   即可获得某个属性的set方法。


   4 在具体的creatBean过程中,我的逻辑是以bean中的属性为主,去ResultSet中去取。

   而源码的逻辑是生成一个数组,columnToProperty。例如columnToProperty[2]=4,就是说resultset的第二个字段对应于bean中的第4个属性
   源码方式的好处在于,表与bean的映射关系可以更为灵活,如何如果想让personName与person_name相对应也是可以的。而我那个思路更改起来就会很麻烦。



分析源码

   http://blog.csdn.net/dlf123321/article/details/45172429


参考资料
 http://www.cnblogs.com/xdp-gacl/p/4007225.html
 http://blog.csdn.net/x605940745/article/details/20240959
 http://www.cnblogs.com/panjun-Donet/archive/2008/09/27/1300609.html
 http://www.cnblogs.com/iyangyuan/archive/2013/04/09/3011274.html

相关解决方案

最新解决方案