针对上一篇文章通过JDBC对云端数据库的增删查改操作最后的一部分做的补充。
先贴代码,后给设计思路。若有对代码中的方法有疑惑的可以查看JDK帮助文档:
/**
* 使用 JDBC 进行查询,将结果赋值给对象的 Field,返回存放对象的 List
*调用 PreparedStatement 的 executeQuery() 方法进行查询
* ResultSet:结果集,封装可使用 JDBC 进行查询的结果
* ResultSetMetaData:JDBC元数据,可以得到结果集里列的别名等
* @param <T>:泛型
* @param sql:查询语句
* @param args :补充占位符的实参数组
* @return
*/
public static <T> List<T> getSelect(Class<T> clazz,String sql,Object...args) {
T entity =null;
//创建一个List,用于存放对象
List<T> list = new ArrayList<>();
Connection connection = null;
PreparedStatement preparedStatement= null;
ResultSet rs = null;
try {
//利用反射创建对象!!!若无此步骤,会抛出异常
entity = clazz.newInstance();
connection = getConnection();
//1.获取 preparedStatement 对象
preparedStatement = connection.prepareStatement(sql);
//2.向 sql 补充占位符变量
for(int i = 0;i<args.length;i++) {
preparedStatement.setObject(i+1, args[i]);
}
//3.获得查询结果:ResultSet 对象
rs = preparedStatement.executeQuery();
//4.获取 ResultSetMetaData 对象
ResultSetMetaData rsmd = rs.getMetaData();
//5.创建一个Map<String,Object>存放查询结果,键:列的别名(别名应与对象的属性值同名),值:列对应的值
Map<String,Object> map = new HashMap<>();
//6.处理结果集
while(rs.next()) {
//6.1利用 ResultSetMetaData 填充Map
for(int i= 0;i<rsmd.getColumnCount() ;i++) {
String columnName = rsmd.getColumnLabel(i+1);
Object columnValue = rs.getObject(i+1);
map.put(columnName, columnValue);
}
//6.2 判断map 是否为空,并为对象的字段赋值
if(map.size()>0) {
for(Map.Entry<String, Object> entry : map.entrySet()) {
String fieldName = entry.getKey();
Object fieldValue = entry.getValue();
//System.out.println(fieldName+ ":"+fieldValue);
//根据 fieldName 得到entity 实例对应的字段值并将 fieldValue 赋值给它
setFiledValue(entity, fieldName, fieldValue);
}
}
//7. 返回对象放入list 中
list.add(entity);
//清空 map,下次循环继续存键值
map.clear();
}
} catch (Exception e) {
e.printStackTrace();
}finally {
release(rs, preparedStatement, connection);
}
return list;
}
//向对象的对应属性赋值
private static void setFiledValue(Object obj,String filedName,Object value) {
Class clazz = obj.getClass();
try {
Field field = null;
field = clazz.getDeclaredField(filedName);
field.setAccessible(true);
field.set(obj, value);
} catch (Exception e) {
e.printStackTrace();
}
}
思路解析:
先说一下比较上一篇文章优化的地方:使用 PreparedStatement(Statement的子接口) 代替了 Statement,优点: 使用PreparedStatement 使代码更简洁;防止SQL注入攻击
实现思路:
- 获取与远程数据库的连接,得到查询结果集,
- 利用 ResultSetMetad 的 getColumnCount() 方法获取列的数量,getColumnLabel() 方法获取列的别名,将结果集存入 Map<String,Object> 中.
- 遍历 Map ,根据其 key 得到对象的 Field 名并将其 value 值赋给 Field。
- 遍历完 Map 后,对象的所有 Field 都被赋值了,然后将对象存入 List<T> 中,至此一行结果处理完毕
- 重复 2 3 4 步骤,直到结果集读完,即 ResultSet.next() 为 false。
- 返回存放对象的 List
接下来测试一下这个方法:
@Test
public void testGetSelect() {
Class<Person> clazz = Person.class;
String sql = "SELECT id AS Id,name AS Name,address AS Address from first_table WHERE address =?";
Object [] args = {"成都"};
List<Person> persons = new ArrayList<>();
persons = JDBCTools.getSelect(clazz, sql, args);
System.out.println(persons.toString());
}
结果:

本文介绍使用JDBC进行数据库查询的优化方法,通过PreparedStatement替代Statement,预防SQL注入,提高代码效率。文章详细讲解如何利用反射创建对象,处理查询结果,并将数据映射到Java对象的Field中。
966

被折叠的 条评论
为什么被折叠?



