Java反射实现不同对象相同代码地对象查询和封装
一段可重用的代码来完成不同类的查询封装操作。经过我一下午地编写、测试,终于,得到一份可以完成我们需要功能的Java代码。如下:
首先,JSP页面的需求是:通过一段Java代码如:ArrayList<Object> result =new com.jkx.web.Query.Web_TestQuery(Test).QueryAll("test");得到一个查询好了的装有对象的集合来进行对象属性的显示,那么,我们需要完成的就是得到这样一个集合。此处Test应为该对象的实例,test为数据库相应表名。
那么,com.jkx.web.Query.Web_TestQuery类中应有构造方法:
public Web_TestQuery(Object obj) { //obj即为传过来的Test
this.object=obj; //此处需预先申明属性:Object object;
objclass=obj.getClass();
因此,通用类的查询类应该这样命名:
public ArrayList<Object> QueryAll(String TableName) { //要满足通用所有对象,即不知道对象的类类型是什么,故用Object代替
ArrayList<Object> AlistTest = new ArrayList<Object>(); //这是我们需要的这个集合,不过现在还是空的。
Field[] fields = objclass.getDeclaredFields(); //获得该类的所有属性,Field[]需导入包java.lang.reflect.Field
for(Field field:fields){ //遍历 fields ,获取每一个属性
Method set = pd.getWriteMethod(); //获得属性名field.getName()的set方法
rs.getObject(i);//因无法得知ield.getName()属性类型,故rs.getObject(i)
i++;
AlistTest.add(object);
最后,返回 集合AlistTest即可。然而,当你们实现了上面的代码后,运行会发现,读取的数据全是ResultSet最后一条数据,那是因为,我们在while (rs.next()) { }循环开始时没有再次实例化对象object,即我们通过for(Field field:fields)不停地遍历对象属性并赋值仅仅是不停地传过来的这个唯一对象赋值(内存中仅有的一个对象)。因此虽然通过AlistTest.add(object)加入了和数据库总记录数相同条数的数据,但是这些数据的指针均指向内存中同一个对象。所以,我们需要每次在while (rs.next()) { }循环开始时都要实例化对象object一次,这样才能有不同属性值的不同对象存在于集合中。我想,对于我来说,这个才是这段代码最难的地方了,至少我是用了许多方式都没有完成这个对象的实例化。因为我不知道传入对象的类型,故无法new一个新对象。最后,才想到,实例化对象的方式不止new一种,同样可以通过object=objclass.newInstance()来实现实例化。这样,Java虚拟机也同样知道了object对象的类型,类型就是传入的Test的类类型(objclass)。至此,我们完成了Java不同对象的相同查询及封装方法的代码实现。当然此代码不仅可以完成查询操作,增删改操作同样可以,只是sql语句不同而已并且不会返回数据集了。
注:在对象类的Javabean当中,类属性申明顺序必须和数据库相应字段名顺序一致,不然必然出现乱赋值或者无法赋值现象。