本文主要是介绍ResultSet结果集转换为实体对象实现方案,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
ResultSet结果集转换为实体对象实现方案
在应用开发中,我们从数据库查询出的结果集(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;
//默认构造器
public DataTableEntity()
{
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
{
throw new ArrayIndexOutOfBoundsException();
}
}
//获取字段类型数组
public int[] getColumnTypes()
{
return this.columnTypes;
}
//获取字段类型
public int getColumnType(int index)
{
if(index <= this.columnCount)
{
return this.columnTypes[index];
}
else
{
throw new 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;
}
}
这篇关于ResultSet结果集转换为实体对象实现方案的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!