在我以往开发所用的商业平台里,有一个Record对象,它类似ResultSet,是执行sql查询语句返回的结果集,它有一个toBean方法,可以将Record对象转换成实体对象。
就像某些登录案例中User表和User对象,其数据表字段和User类成员变量是一一对应的,当用select * from user得到一个ResultSet后,Record就不需要rs.getString(字段名)这样麻烦得获取了,只要类似有toBean(User.class)这样的方法,就可以得到一个List。那么处理list.get(i)要比rs.next()要方便得多了。
在csdn上找到一个解决方法,测试可行。根据TDD,我先贴出测试代码,只是修改了第一步里的测试代码。
通过执行方法,由rs和Plan类得到一个Object数组。这个数组里每一个对象可以被强制转换成Plan类型。可能作者为了展示一个由数据表到Bean的过程,在我所使用的商业中间件中,参数不是用"com.plan.dao.Plan"而是Plan.class,所以返回的也就是Plan类型。
通过那个网址也可以复制下代码,在这里我将运行成功的代码贴出来。以开源中国的代码空间,复制起来更容易一点。
ConvertResultSetToEntity.java
package com.plan.entity;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.HashMap;
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;
}
}
这个类还需要如下两个类
DataTableEntity.java
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();
}
}
}
MethodEntity.java
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查询结果以对象的形式操作了,无疑为我的小Plan计划奠定了更加坚实的基础。