Java利用反射封装获取数据库的数据的工具类
在我们查询到数据库的数据的时候,一般我们都会封装一个类接收获取到的数据,方便再其他方法或者页面使用,但是有时侯需要的数据的字段太多,如果每次查询都写一次那么效率很慢,如果封装一个类,只要调用这个类就可以把查询到的数据准确的转到一个数据接收类里的话,那么效率快的不用说。
下面是我总结出了封装这个类的思路;
*下面将A类作为接收数据的类
- 写一个方法,获取A类和数据库传过来的数据集作为参数;
- 加载A类,然后获取A类的所有属性变量,将属性变量名保存起来;
- 创建A类的list集合
- 然后遍历数据库传过来的数据集,通过getObject的方法获取数据,然后保存到A类的list集合中;
- 返回A类的list集合
注:因为A类中有些属性字段是私有的,所以要通过反射来获取和赋值
代码如下:
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.sql.Date;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
public class Reflect {
// 封装一个方法,该方法实现获取数据库的数据传输到自定义的类里面
/**
* 注意:数据库的字段名必须和自定义的类的字段名一样,否则无数据
*
* @param genericity
* 自定义的类,接收数据库数据的类
* @param resultSets
* 数据库返回的数据
* @return 返回自定义类的list聚合
* @throws Exception
*/
public static <T extends Object, V extends ResultSet> List<T> getReflectRrsult(
T genericity, V resultSets) throws Exception {
// 加载类
Class<?> genericityClass = genericity.getClass();
// 实例化NameAndType类的聚合,该类记录genericity的属性名和类型;
List<NameAndType> andTypes = new ArrayList<NameAndType>();
// Field类,获取genericityClass里面的属性对象,这里是获取属性对象的数组
Field[] fields = genericityClass.getDeclaredFields();
// 获取fields集合的长度,因为多处用的,所以定义个变量存放
int fieldsLength = fields.length;
// 循环所有属性,目的是获取每个属性的属性名和类型
for (int i = 0; i < fieldsLength; i++) {
// 实例化NameAndType类,接收数据
NameAndType andType = new NameAndType();
fields[i].setAccessible(true);// 打破封装,在这里不知道有没有用,先加上;
andType.type = fields[i].getType();// 获取属性类型
// System.out.println(fields[i].getType());
// 获取属性名,不能用fields[i].tosing(),获取的不是名字,是整个对象的字符串
andType.name = fields[i].getName();
// 将NameAndType类添加到聚合里面
andTypes.add(andType);
}
// 实例化一个泛型集合,存放数据库传来的数据
List<T> list = (List<T>) new ArrayList<Object>();
// 实例化一个ResultSet类等于resultSets;
ResultSet resultSet = resultSets;
// 用while循环判断resultSet是否有下一条数据
while (resultSet.next()) {
// 获取genericityClass类的构造函数
Constructor<?> constructorClass = genericityClass
.getDeclaredConstructor();
// 打破封装,防止构造函数私有化
constructorClass.setAccessible(true);
// 调用构造函数,获取
T class44 = (T) (constructorClass.newInstance());
// 循环NameAndType类,将通过NameAndType类记录的属性名和属性类型获取和设置数据
for (int i = 0; i < andTypes.size(); i++) {
// 获取属性名
String string = andTypes.get(i).name;
Class<?> type = andTypes.get(i).type;
// System.out.println(string);
// 通过属性名获取到该属性的对象【getDeclaredField(string)方法>>获取单个Field对象】
Field fineld3 = genericityClass.getDeclaredField(string);
// 打破封装,给私有属性对象赋值
fineld3.setAccessible(true);
// 给Field字段属性对象赋值
try {
// resultSet.getObject(string)方法获取数据集中通过name值来获取数据
Object object = resultSet.getObject(string);
// System.out.println(object.getClass().equals(type));
// set(x,y)第一个参数是类对象,第二个参数是存放的值
fineld3.set(class44, object);
} catch (Exception e) {
//用try捕捉异常,防止有些类有多余字段是不用获取数据库的数据的;
break;
}
}
// 将具体的类添加到类集合中,返回给调用者
list.add(class44);
}
return list;
}
}
class NameAndType {// 定义一个类,接收传过来的类的名字和类型
public String name;
public Class<?> type;//本想着判断数据库获取的数据跟接收数据类中对应的属性字段类型不一样则不赋值。但是没实现这个功能
}
在外部需要查询数据的时候只需两句代码;例如
ResultSet rs = ps.executeQuery();// ResultSet为数据查询出来的数据集合
List<Uitl> list=Reflect.getReflectRrsult(new Uitl(), rs);