zoukankan      html  css  js  c++  java
  • 基于cglib反射的数据库查询结果封装为对象(简单的orm实现)

    基于jar:cglib 2.2

    数据库:mysql

    背景:

    目前正在写一个简单的新闻等文字分析系统(爬虫搜索引擎类型的,写着玩的),为了提高分析数据分析的效率,提高数据库与代码的交换效率,并没有使用hibernate等工具。但是这个系统也必须实现对查询结果的对象封装。

    思路:

    因此我采用特别查询到频繁的对象直接写在代码里面,其他查询不是很频繁的类采用以下代码进行动态字节码生成进行对象封装。

    说明:

    简单的orm代码实现,可以通过传人的数据库字段名称和对象字段名称,进行数据库查询内容进行自动封装

     注意:这个只是演示cglib自动封装使用。正式环境中需要考虑以下问题:

    1:动态字节码生成效率低,当特别频繁调用的时候肯定是效率瓶颈。

    2:动态字节码生成肯定会给jvm内存中的方法区带来压力,也会给gc带来工作量。因此写相关代码一定要注意。

    3:注意ResultSet一般不要用于数据传递。

    对象封装类如下:

      1 package com.zwh.base.dao;
      2 
      3 import java.lang.reflect.Method;
      4 import java.sql.Date;
      5 import java.sql.ResultSet;
      6 import java.sql.ResultSetMetaData;
      7 import java.sql.SQLException;
      8 import java.util.ArrayList;
      9 import java.util.List;
     10 
     11 import net.sf.cglib.reflect.FastClass;
     12 import net.sf.cglib.reflect.FastMethod;
     13 
     14 /**
     15  * 用于与数据库查询使用的反射类,不知道咋设计啊,反正目前只用于数据库对象的封装
     16  * @ClassName: Reflect 
     17  * @author ZHANGWENHAO zhangwenhao3@sina.com 
     18  * @date 2013-10-29 下午01:50:28 
     19  * @param <T>
     20  */
     21 public class Reflect<T>{
     22 
     23     /**
     24      * 通过cglib反射自动封装数据库查询数据,注意,临时产生新的字节码过多的时候,会内存溢出,目前3.2以上的hibernate版本据说是直接使用asm 但是效率不会比这个效率明显增加多少了(增加的效率应不是产生在动态生成字节码这一部分了)
     25      * 这个效率是相当高的了,是直接调用的10倍左右,比有安全校验的java原生反射好很多
     26      * @param columnsName 数据库字段名称数组
     27      * @param fieldsName 对应的对象字段名称数组
     28      * @param columnsType 对应的字段的类型(简单数据类型请传入class,不要传入type)
     29      * @param rs 数据库查询结果
     30      * @param classType 需要封装的对象类别
     31      * @return 封装后的对象列表
     32      * @author ZHANGWENHAO 
     33      * @date 2013-10-29 下午05:00:44
     34      */
     35     public List<T> beanWrapper(String[] columnsName, String[] fieldsName, Class<?>[] columnsType, ResultSet rs, Class<T> classType){
     36         try {
     37 //            判断数据库查询结果是否有一个列阶段
     38             String columns = getAllColumn(rs);
     39             int length = columnsName.length;
     40             boolean[] keys = new boolean[length];
     41             for(int i=0;i<length;i++){
     42 //                获取是否有一个字段
     43                 keys[i] = columns.indexOf(columnsName[i])>=0;
     44             }
     45 //            对象反射阶段
     46             FastClass fastClass = FastClass.create(classType);
     47             List<T> result = new ArrayList<T>();
     48             while(rs.next()){
     49                 T temp = classType.newInstance();
     50                 for(int j=0;j<length;j++){
     51 //                    拼写方法名
     52                     String methodStr="set"+fieldsName[j].replaceFirst(fieldsName[j].substring(0, 1), fieldsName[j].substring(0, 1).toUpperCase());
     53                     Method method = classType.getMethod(methodStr, columnsType[j]);
     54                     FastMethod fastSetMethod = fastClass.getMethod(method);
     55                     if(keys[j]){//按照使用频率排列(按需书写) 为了提高效率啊 这里就不动态拼调用方法了,直接调用可是会快一个0的(10倍到100倍)
     56                         if(String.class.equals(columnsType[j])){//字符串
     57                             Object object = rs.getString(columnsName[j]);
     58                             fastSetMethod.invoke(temp, new Object[]{object});
     59                         }else if(Integer.class.equals(columnsType[j])){//int
     60                             Object object = rs.getInt(columnsName[j]);
     61                             fastSetMethod.invoke(temp, new Object[]{object});
     62                         }else if(Date.class.equals(columnsType[j])){//日期
     63                             Object object = rs.getDate(columnsName[j]);
     64                             fastSetMethod.invoke(temp, new Object[]{object});
     65                         }else if(Double.class.equals(columnsType[j])){//double
     66                             Object object = rs.getDouble(columnsName[j]);
     67                             fastSetMethod.invoke(temp, new Object[]{object});
     68                         }else if(Long.class.equals(columnsType[j])){//long
     69                             Object object = rs.getLong(columnsName[j]);
     70                             fastSetMethod.invoke(temp, new Object[]{object});
     71                         }else if(Short.class.equals(columnsType[j])){
     72                             Object object = rs.getShort(columnsName[j]);
     73                             fastSetMethod.invoke(temp, new Object[]{object});
     74                         }
     75                     }
     76                 }
     77                 result.add(temp);              
     78             }
     79             return result;
     80         } catch (Exception e) {
     81             System.out.println("通过反射,获取对象出错,对象名称");
     82             e.printStackTrace();
     83             return new ArrayList<T>();
     84         }
     85     }
     86     
     87     /**
     88      * 采用字符串校验是否有一个字段,最轻量级,效率最高(在目前这个情况下是这样的)
     89      * @return 
     90      * @author ZHANGWENHAO 
     91      * @throws SQLException 
     92      * @date 2013-9-22 下午03:42:46
     93      */
     94     private String getAllColumn(ResultSet rs) throws SQLException{
     95         StringBuilder sb = new StringBuilder();
     96         ResultSetMetaData rsmd = rs.getMetaData();
     97         for(int i=1;i<=rsmd.getColumnCount();i++){
     98             sb.append(rsmd.getColumnName(i)).append(",");
     99         }
    100         return sb.toString();
    101     }
    102     
    103 }

    调用实例:

    public List<SpiderModel> sqlResultToSpiderModel(ResultSet rs) {
    //        预留,参数传入,反正这个效率很高
            String columnsName[] = new String[]{
                    "id",
                    "source_name",
                    "title_tag",
                    "content_tag",
                    "char_set"
                    };
            String fieldsName[] = new String[]{
                    "id",
                    "sourceName",
                    "titleTag",
                    "contentTag",
                    "charSet"
                    };
            Class<?> columnsType[] = new Class<?>[]{Integer.class,String.class,String.class,String.class,String.class};
            Reflect<SpiderModel> reflect = new Reflect<SpiderModel>();
            List<SpiderModel> result = reflect.beanWrapper(columnsName, fieldsName, columnsType, rs, SpiderModel.class);
            return result;
        }

    说明:这个是我的数据库的测试测试代码,大家测试的时候请使用自己的数据库测试,rs使用原生的数据库查询方法生成conn.getStatement().executeQuery(sql);相关内容不再赘述。

    代码有什么不合适的地方或者不对的地方,请各位大神多多指点,多多交流。

     原创代码,转载请说明,并保留此出处http://www.cnblogs.com/zhangwenhao/p/3397068.html 。谢谢。

  • 相关阅读:
    全方位深度剖析--性能测试之LoardRunner 介绍
    国外性能测试博客
    由我主讲的软件测试系列视频之性能测试系列视频讲座目录出炉了
    性能测试之系统监控工具nmon
    性能测试学习内容指南
    性能测试之操作系统计数器分析方法
    JAVA正则表达式:Pattern类与Matcher类详解
    (总结)密码破解之王:Ophcrack彩虹表(Rainbow Tables)原理详解(附:120G彩虹表下载)
    border-collapse实现表格细线边框
    安卓造成内存泄露的几个原因
  • 原文地址:https://www.cnblogs.com/zhangwenhao/p/3397068.html
Copyright © 2011-2022 走看看