本章学习目录
- 问题的引出:往日的工具类需要针对不同的环境做出适当的改变,这里由于,增删改已经实现通用,那么对于查询是否可以一个工具类多用呢?(之前细讲过普通的DBUtil设置,传送门:普通DBUtil工具类)
- 问题的解决:反射机制能让我们动态的获得类中的属性或者方法,从而实现多用性
- 页内目录
一,构建建立连接和释放资源的方法
二,思考需要建立的通用工具类需要哪些参数
三,建立连接获得预处理对象设置?占位符
四,获得查询结果的元数据和表结构
五,依靠反射机制循环遍历结果集并放入集合
六,释放资源
七,展示整体流程(本方法适用于查询)
一,构建建立连接和释放资源的方法(将异常都try catch
了)
- 为连接属性,预处理对象属性,结果集对象提升作用域:
java"> protected Connection conn = null;
protected PreparedStatement ps = null;
protected ResultSet rs = null;
java"> protected Connection getConn() throws ClassNotFoundException, SQLException {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/goods?useSSL=true","root","root");
return conn;
}
java"> protected void closeAll(){
try { if(rs != null){ rs.close(); }
if(ps != null){ ps.close(); }
if(conn != null){ conn.close(); }
} catch (SQLException e) {
e.printStackTrace();
} finally {
conn = null;
ps = null;
rs = null;
}
}
二,建立的通用工具类的方法需要哪些参数
- 少不了的sql语句
- 既然是动态的那就少不了反射中的Class
- ?占位符的不定长设置
java">public <T>List<T> excuteQuery(String sql,Class<T> cla,Object...params){}
三,建立连接获得预处理对象设置?占位符
java">this.getConn();
java">ps=conn.prepareStatement(sql);
java">if (params!=null&¶ms.length!=0){
for (int i=0;i<params.length;i++){
ps.setObject(i+1,params[i]);
}
}
四,获得查询结果的元数据和表结构
java">rs=ps.executeQuery();
java">ResultSetMetaData rsmt= rs.getMetaData();
java">int columnCount = rsmt.getColumnCount();
五,依靠反射机制循环遍历结果集并放入集合
java">List<T> list=new ArrayList<>();
java">while (rs.next()){
java">T t = cla.newInstance();
java">for (int i = 1; i <=columnCount; i++) {
java">Object value = rs.getObject(i);
java">String columnName = rsmt.getColumnName(i);
java">Field field = cla.getDeclaredField(columnName);
java">String methodName="set"+columnName.substring(0,1).toUpperCase()+columnName.substring(1);
- 运用反射根据set方法名和参数类型获取方法对象(因为方法名和参数可以唯一确定一个方法)
java">Method method = cla.getDeclaredMethod(methodName, field.getType());
java">method.invoke(t, ConvertUtils.convert(value,field.getType()));
for循环
完毕while循环
完毕- 将对象添加到集合内
java">list.add(t);
六,释放资源
- 因为资源必须释放,否则占用内存,所以在最后执行的
finally
里释放资源
java">finally {
this.closeAll();
}
七,展示整体流程
java"> public <T>List<T> excute(String sql,Class<T> cla,Object...params){
try {
this.getConn();
ps=conn.prepareStatement(sql);
if (params!=null&¶ms.length!=0){
for (int i=0;i<params.length;i++){
ps.setObject(i+1,params[i]);
}
}
rs=ps.executeQuery();
ResultSetMetaData rsmt= rs.getMetaData();
int columnCount = rsmt.getColumnCount();
List<T> list=new ArrayList<>();
while (rs.next()){
T t = cla.newInstance();
for (int i = 1; i <=columnCount; i++) {
Object value = rs.getObject(i);
String columnName = rsmt.getColumnName(i);
Field field = cla.getDeclaredField(columnName);
String methodName="set"+columnName.substring(0,1).toUpperCase()+columnName.substring(1);
Method method = cla.getDeclaredMethod(methodName, field.getType());
System.out.println(value);
method.invoke(t, ConvertUtils.convert(value,field.getType()));
}
list.add(t);
}
return list;
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} finally {
this.closeAll();
}
return null;
}