用反射写出和apache中的Query方法(返回查询出的对象集合的那一个)功能相同的方法
用Apache的包那么舒服,自己也手痒了想写个玩玩
写了大概俩小时= = 期间遇到好多问题简直心态爆炸,好歹还是摸索出来了
颤抖的运行main方法、一次次的异常、刺眼的红字屡屡的嘲笑我
最后一次运行时。终于得出了我想要的结果,那一瞬间成就感简直爆炸,我能感受到大脑的多巴胺分泌迅速升高
不多说了贴代码:
package top.yibobo.dao;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import top.yibobo.util.DBUtil;
public class QueryUtil {
public static <T> List<T> query(Connection connection,String sql,Class<T> type){
Connection conn = connection;
List<T> list = new ArrayList<T>();
//这里很关键!!如果不使用这里的类对象,在创建ResultSet要使用的get方法时
//使用下面的rs.getClass()将会报错:oracle.jdbc.driver.OracleResultSet with modifiers "public"
Class rsclass = ResultSet.class;
Field[] field = type.getDeclaredFields();//获得class中所有的属性
try {
PreparedStatement ps = conn.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
while(rs.next()){//遍历结果集
Constructor c = type.getConstructor(null);
T t = (T) c.newInstance(null);//每循环一次就获取一次class的构造方法并new一个对象
for(Field f:field){//遍历属性
//获取set方法名
String fieldName = "set"+f.getName().substring(0,1).toUpperCase()
+f.getName().substring(1);
//获取ResultSet要使用的get方法名
String rsFieldName = "get"+f.getType().getSimpleName().substring(0,1).toUpperCase()
+f.getType().getSimpleName().substring(1);
//给对象赋值的set方法
Method m = type.getMethod(fieldName, f.getType());
//rs要用的get方法
Method m2 = rsclass.getMethod(rsFieldName, String.class);
Object obj = m2.invoke(rs, f.getName());
m.invoke(t, obj);
}
list.add(t);
}
} catch (NoSuchMethodException e1) {
e1.printStackTrace();
} catch (SecurityException e1) {
e1.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return list;
}
}
期间遇到的问题:
一开始是想用ResultSet结果集直接提取数据,用getObject(属性名/列名)。
然后使用反射得到的set方法,将提取到的数据作为参数给T对象进行赋值,结果直接雪崩。
试了半天,把各种属性都打印出来验证了个遍才知道
这玩意把Oracle中的NUMBER类型用getObject()提取出来后是个BigDecimal类型,我也是醉了。必须要用getInt()才行
我实验的是传个oracle中ORCL数据库里的emp表进去,里边有个时间单位,放进java里应该是sql.Date这个类型
结果通过getObject提取出来后是个Timestamp类型,也不能直接往set方法里塞。必须要用getDate()方法
后来思路就是,既然我获取了T对象的setXXX方法,那我也可以获取ResultSet的getXXX嘛
然后使用
String rsFieldName = “get”+f.getType().getSimpleName().substring(0,1).toUpperCase()+f.getType().getSimpleName().substring(1);
得到getXXX的具体名字
然后再用Method类把ResultSet的方法具现化出来,注意这儿只能用ResultSet.class来获得类对象
把取出的变量赋值给Object,然后就能够使用T的set方法进行具体赋值了。
