用反射写出和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方法进行具体赋值了。