首页 > 经验记录 > 用反射写出和apache中的Query方法(返回查询出的对象集合的那一个)功能相同的方法

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

           


EA PLAYER &

历史记录 [ 注意:部分数据仅限于当前浏览器 ]清空

      00:00/00:00