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; } }