ResultSet结果集转换为实体对象实现方案

转自:http://blog.csdn.net/stevene/article/details/575141

好吧 原文的排版就不吐槽了,重排一下如下~

============== 正文 ==============

在应用开发中,我们从数据库查询出的结果集(ResultSet)一般都需要取得(get)其中的数据然后存放到(set)实体对象(Entity,有的称为VO值对象或称为PO持久化对象)中,以便进一步的处理需要。常用也最容易理解的方式就是从ResultSet中get相应的字段值后调用实体对象的set方法,把值保存在实体对象中。这种方式编码量很大,特别是很多字段的查询,编码就会觉得很烦琐。这里我们提供了一种方法,封装实现了ResultSet结果集转换为实体对象(Entity,或叫VO值对象,或PO持久化对象)的方法。

注:三流合一项目有种实现方式,不过我觉得有点烦琐,这里做了重新设计定义,欢迎各位大家多多指教交流。

一、定义结果集返回表结构对象

首先我们需要对返回的结果集进行分析,需要知道它返回了那些字段,字段名、字段类型是什么等,结果集表结构对象定义如下:

public class DataTableEntity
{
    //查询出的ReslutSet中的字段数量
    private int columnCount = 0;
    //字段名称数组
    private String[] columnNames;
    //字段类型数组
    private int[] columnTypes;  

    this(0);
  
    //初始化构造器
    public DataTableEntity(int columnCount){
        this.columnCount = columnCount;
        this.columnNames = new String[columnCount];
        this.columnTypes = new int[columnCount];
    }
    //获取字段数量
    public int getColumnCount(){
        return this.columnCount;
    }
    //获取字段名称数组
    public String[] getColumnNames(){
        return this.columnNames;
    }
    //获取第index个字段名称,如果index字段不存在,则抛出ArrayIndexOutOfBoundsException异常
    public String getColumnName(int index){
        if (index <= this.columnCount){
            return this.columnNames[index];
        } else {
            throw new ArrayIndexOutOfBoundsException();
        }
    }
    //设置字段名称数组
    public void setColumnNames(String[] columnNames){
        this.columnNames = columnNames;
    }
    //设置第index个字段名称,如果index字段不存在,则抛出ArrayIndexOutOfBoundsException异常
    public void setColumnName(String columnName, int index){
        if(index <= this.columnCount){
            this.columnNames[index] = columnName;
        } else {
            thrownew ArrayIndexOutOfBoundsException();
        }
    }
    //获取字段类型数组
    public int[] getColumnTypes(){
        return this.columnTypes;
    }
    //获取字段类型
    public int getColumnType(int index){
        if(index <= this.columnCount){
            return this.columnTypes[index];
        } else {
            thrownew ArrayIndexOutOfBoundsException();
        }
    }
    //设置字段类型数组
    public void setColumnTypes(int[] columnTypes){
        this.columnTypes = columnTypes; 
    }
    //获取字段类型
    public void setColumnType(int columnType, int index){
        if(index <= this.columnCount){ 
            this.columnTypes[index] = columnType;
        } else {
            throw new ArrayIndexOutOfBoundsException();
        }
    }
}

二、定义实体对象(或值对象)的方法实体对象

我们在实体对象中定义set和get等方法,当ResultSet转换为Entity时,我们需要调用Entity的一系列set方法,那么我们就需要知道在entity中都定义了哪些方法,这些方法的参数是什么?返回值是什么?以及抛出的异常等信息。

因此,我们需要对实体对象进行分析,定义一个对象来存储分析后的实体对象中定义的方法(Methods)信息。

基于以上需要,我们定义了一个方法实体对象:

import java.util.ArrayList;

public class MethodEntity {
    //方法名称
    private String methodName;
    //重载方法个数
    private int repeatMethodNum = 1;
    //方法参数类型列表   
    private Class[] methodParamTypes;
    //存放重载方法参数
    private ArrayList repeatMethodsParamTypes;

    /**
     * 获取参数名称
     *
     * @return
     */
    public String getMethodName() {
        return methodName;
    }

    /**
     * 获取方法参数类型列表
     *
     * @return
     */
    public Class[] getMethodParamTypes() {
        return methodParamTypes;
    }

    /**
     * 设置参数名称
     *
     * @param string
     */
    public void setMethodName(String string) {
        methodName = string;
    }

    /**
     * 设置参数类型列表
     *
     * @param classes
     */
    public void setMethodParamTypes(Class[] classes) {
        methodParamTypes = classes;
    }

    /**
     * 获取重载方法个数
     *
     * @return
     */
    public int getRepeatMethodNum() {
        return repeatMethodNum;
    }

    /**
     * 获取第i个重载方法参数列表
     *
     * @return
     */
    public Class[] getRepeatMethodsParamTypes(int i) {
        int count = this.repeatMethodsParamTypes.size();
        if (i <= count) {
            return (Class[]) this.repeatMethodsParamTypes.get(i);
        } else {
            throw new ArrayIndexOutOfBoundsException();
        }
    }

    /**
     * 设置重载方法个数
     *
     * @param i
     */
    public void setRepeatMethodNum(int i) {
        repeatMethodNum = i;
    }

    /**
     * 设置重载方法参数类型
     *
     * @param list
     */
    public void setRepeatMethodsParamTypes(ArrayList list) {
        repeatMethodsParamTypes = list;
    }

    /*
     *获取重载方法类型
     * @return
     */
    public ArrayList getRepeatMethodsParamTypes() {
        return repeatMethodsParamTypes;
    }

    /**
     * 设置重载方法参数类型列表
     *
     * @param paramTypes
     */
    public void setRepeatMethodsParamTypes(Class[] paramTypes) {
        if (this.repeatMethodsParamTypes == null) {
            this.repeatMethodsParamTypes = new ArrayList();
        }
        repeatMethodsParamTypes.add(paramTypes);
    }
}

三、实现ResultSet到Entity对象转换方法定义

 

定义完毕方法实体对象和结果集表结构实体对象后,我们就可以对返回的结果集进行分析,把分析结构分别存储在方法实体对象和结果集表结构实体对象中。

首先我们需要知道返回的结果集和哪个实体对象相对应,需要指定ResultSet转化为的Entity对象类名称。

然后我们对这个实体对象类中定义的方法进行分析,获取实体中定义的方法名称,方法参数类型等信息,如下:

//注册实体, strEntity指定的实体类名称字符串
Class classEntity = Class.forName(strEntity);
//获取实体中定义的方法
HashMap hmMethods = new HashMap();
for (int i = 0; i < classEntity.getDeclaredMethods().length; i++) {
    MethodEntity methodEntity = new MethodEntity();
    //方法的名称        
    String methodName = classEntity.getDeclaredMethods()[i].getName();  
    String methodKey = methodName.toUpperCase();        
    //方法的参数        
    Class[] paramTypes = classEntity.getDeclaredMethods()[i].getParameterTypes();   
    methodEntity.setMethodName(methodName);        
    methodEntity.setMethodParamTypes(paramTypes);                         
    //处理方法重载        
    if(hmMethods.containsKey(methodKey)){
        methodEntity.setRepeatMethodNum(methodEntity.getRepeatMethodNum()+1);
        methodEntity.setRepeatMethodsParamTypes(paramTypes);        
    } else {        
        hmMethods.put(methodKey, methodEntity);
    }        
}        

这里我们把解析出来的方法信息存储在方法实体对象中,通过全大写方法名作为key存放在HashMap中。
这个方法的实现,我们支持方法的重载。
然后我们分析返回结果集的字段信息,存放在表结构对象实体中:

ResultSetMetaData rsMetaData = rsResult.getMetaData();        
int columnCount = rsMetaData.getColumnCount();        
dataTable = new DataTableEntity(columnCount);
//获取字段名称,类型
for (int i = 0; i < columnCount; i++)
{
  String columnName = rsMetaData.getColumnName(i + 1);
  int columnType = rsMetaData.getColumnType(i + 1);
  dataTable.setColumnName(columnName, i);
  dataTable.setColumnType(columnType, i);
}

下面就可以对返回的结果集数据进行处理了:

while(rsResult.next())
{
        //调用方法,根据字段名在hsMethods中查找对应的set方法
} 

完整是实现如下:

import java.sql.ResultSet;  
import java.sql.ResultSetMetaData;  
import java.lang.reflect.Method;  
import java.util.HashMap;  
import java.lang.reflect.Array;    

public class ConvertResultSetToEntity { /* * * 实现结果集到实体对象/值对象/持久化对象转换 * @param rsResult ResultSet * @param strEntity String * @throws Exception * @return Object[] */ public static Object[] parseDataEntityBeans(ResultSet rsResult, String strEntity) throws Exception { DataTableEntity dataTable = null; java.util.List listResult = new java.util.ArrayList(); //注册实体,strEntity指定的实体类名称字符串 Class classEntity = Class.forName(strEntity); //获取实体中定义的方法 HashMap hmMethods = new HashMap(); for (int i = 0; i < classEntity.getDeclaredMethods().length; i++) { MethodEntity methodEntity = new MethodEntity(); //方法的名称 String methodName = classEntity.getDeclaredMethods()[i].getName(); String methodKey = methodName.toUpperCase(); //方法的参数 Class[] paramTypes = classEntity.getDeclaredMethods()[i].getParameterTypes(); methodEntity.setMethodName(methodName); methodEntity.setMethodParamTypes(paramTypes); //处理方法重载 if (hmMethods.containsKey(methodKey)) { methodEntity.setRepeatMethodNum(methodEntity.getRepeatMethodNum() + 1); methodEntity.setRepeatMethodsParamTypes(paramTypes); } else { hmMethods.put(methodKey, methodEntity); } } //处理ResultSet结构体信息 if (rsResult != null) { ResultSetMetaData rsMetaData = rsResult.getMetaData(); int columnCount = rsMetaData.getColumnCount(); dataTable = new DataTableEntity(columnCount); //获取字段名称,类型 for (int i = 0; i < columnCount; i++) { String columnName = rsMetaData.getColumnName(i + 1); int columnType = rsMetaData.getColumnType(i + 1); dataTable.setColumnName(columnName, i); dataTable.setColumnType(columnType, i); } } //处理ResultSet数据信息 while (rsResult.next()) { //调用方法,根据字段名在hsMethods中查找对应的set方法 Object objResult = ParseObjectFromResultSet(rsResult, dataTable, classEntity, hmMethods); listResult.add(objResult); } //以数组方式返回 Object objResutlArray = Array.newInstance(classEntity, listResult.size()); listResult.toArray((Object[]) objResutlArray); return (Object[]) objResutlArray; } /* * 从Resultset中解析出单行记录对象,存储在实体对象中 */ public static Object ParseObjectFromResultSet( ResultSet rs, DataTableEntity dataTable, Class classEntity, java.util.HashMap hsMethods) throws Exception { Object objEntity = classEntity.newInstance(); Method method = null; int nColumnCount = dataTable.getColumnCount(); String[] strColumnNames = dataTable.getColumnNames(); for (int i = 0; i < nColumnCount; i++) { //获取字段值 Object objColumnValue = rs.getObject(strColumnNames[i]); //HashMap中的方法名key值 String strMethodKey = null; //获取set方法名 if (strColumnNames[i] != null) { strMethodKey = String.valueOf("SET" + strColumnNames[i].toUpperCase()); } //值和方法都不为空,这里方法名不为空即可,值可以为空的 if (strMethodKey != null) { //判断字段的类型,方法名,参数类型 try { MethodEntity methodEntity = (MethodEntity) hsMethods.get(strMethodKey); String methodName = methodEntity.getMethodName(); int repeatMethodNum = methodEntity.getRepeatMethodNum(); Class[] paramTypes = methodEntity.getMethodParamTypes(); method = classEntity.getMethod(methodName, paramTypes); //如果重载方法数 > 1,则判断是否有java.lang.IllegalArgumentException异常,循环处理 try { //设置参数,实体对象,实体对象方法参数 method.invoke(objEntity, new Object[]{objColumnValue}); } catch (java.lang.IllegalArgumentException e) { //处理重载方法 for (int j = 1; j < repeatMethodNum; j++) { try { Class[] repeatParamTypes = methodEntity.getRepeatMethodsParamTypes(j - 1); method = classEntity.getMethod(methodName, repeatParamTypes); method.invoke(objEntity, new Object[]{objColumnValue}); break; } catch (java.lang.IllegalArgumentException ex) { continue; } } } } catch (NoSuchMethodException e) { throw new NoSuchMethodException(); } catch (Exception ex) { ex.printStackTrace(); } } } return objEntity; } }

 

 

posted @ 2013-06-09 10:50  eatpockyboy  阅读(3930)  评论(0)    收藏  举报