目标

引入 HashMap,让返回值变为哈希表,而不是 ResultSet。因为 ResultSet 不能直接转为 JSON 字符串。

HashMap 是键值对,键是唯一的,值是不唯一的。所以可以通过键来找到对应的值。

修改函数的返回值为:HashMap<String, Object>。意味着我们需要的键值对为字符串和 Object 类型

然后再将数据通过 Servlet 返回

仅仅通过 HashMap 返回是不行的。因为我们需要返回的数据可能是多条,而 HashMap 只能是一条记录。下面我们会一步一步的去升级它,看着!

准备

首先,我们最后要返回的是 JSON 字符串。所以需要下载阿里巴巴的 FastJson 包。到 Central Repository: com/alibaba/fastjson/1.2.78 (maven.org) 下载 fastjson-1.2.78.jar。然后拖入项目的 src/main/webapp/WEB-INF/lib 文件夹下。

第一次升级

修改 executeQuery:

这里我省略了 中间一大段,改为注释。

public static HashMap<String, Object> executeQuery(String sql, Object[] params) {
HashMap<String, Object> map = new HashMap<String, Object>();
try {
/* 建立连接 */
/* 创建 PreparedStatement 对象 */
/* 遍历 Params */
/* 执行查询 */
// 处理结果
while (rs.next()) {
map.put("UserId", rs.getObject(1)); // 获取数据中的第 1 列
map.put("Name", rs.getObject("Name")); // 获取数据中列名为 Name
}
/* 关闭资源 */
} catch (SQLException e) {
}
return map;
}

然后在 servlet 的 Get 或 Post 函数中写上:

/* 获取 URL 中的参数 */
// 获取数据
HashMap<String, Object> map = MySqlHelper.executeQuery(sql, null);
// 转换为 JSON 字符串
String json = JSON.toJSONString(map);
response.getWriter().append(json);

上面执行查询的时候,我们的参数列表传递的是 null,也就是会返回整张表的数据。但是当我们实际运行的时候,会发现接口只返回了最后一项数据。

因为每次执行 while 循环,map.put 就会查询 UserId,第一次循环,没有,就创建一个 UserId 键,然后赋值。第二次循环,前面说键是唯一的,所以查询到了 UserId 就会覆盖旧的,然后替换为新的值。所以他只会返回最后一条数据。

第二步

为了让它能够返回多条数据,我们需要让 HashMap 变成一个列表,可以保存多条数据。这时候我们就需要用到 List 对象了。

我们把代码改一改:

public static List<HashMap<String, Object>> executeQuery(String sql, Object[] params) {
List<HashMap<String, Object>> list = new ArrayList<HashMap<String, Object>>();
try {
/* 建立连接 */
/* 创建 PreparedStatement 对象 */
/* 遍历 Params */
/* 执行查询 */
// 处理结果
while (rs.next()) {
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("UserId", rs.getObject(1)); // 获取数据中的第 1 列
map.put("Name", rs.getObject("Name")); // 获取数据中列名为 Name
list.add(map); // 将 map 添加到 List 里。
}
/* 关闭资源 */
} catch (SQLException e) {
}
return list;
}

这里要注意,实例化 List 的时候不能直接 new List,而是要 new ArrayList。ArrayList 是 List 的子类。这是 Java 面向对象中的多态。

然后在 servlet 的 Get 或 Post 函数中写上:

/* 获取 URL 中的参数 */
// 获取数据
List<HashMap<String, Object>> list = MySqlHelper.executeQuery(sql, null);
// 转换为 JSON 字符串
String json = JSON.toJSONString(list);
response.getWriter().append(json);

第三步

仔细看,我们的 while 循环里,map 的键是写死的。但是如果我们要访问不同的表呢?或者说我们增加了新的数据列呢?所以我们要让 map 的键是动态调整的

这时候我们就需要把返回的列名提取出来,让 map 的键根据类名动态添加。首先,ResultSet 里边是没有获取列名的方法的。这时候我们就需要用到另一个对象:ResultSetMetaData

再修改代码:

public static List<HashMap<String, Object>> executeQuery(String sql, Object[] params) {
List<HashMap<String, Object>> list = new ArrayList<HashMap<String, Object>>();
try {
/* 建立连接 */
/* 创建 PreparedStatement 对象 */
/* 遍历 Params */
// 执行查询
rs = pstmt.executeQuery();
// 获取 ResultSet 元数据
ResultSetMetaData = rs.getMetaData();
// 处理结果
while (rs.next()) {
HashMap<String, Object> map = new HashMap<String, Object>();
// 遍历返回的所有列
for(int i = 0; i < rsmd.getColumnCount(); i++) {
map.put(rsmd.getColumnName(i + 1), rs.getObject(i + 1));
}
list.add(map); // 将 map 添加到 List 里。
}
/* 关闭资源 */
} catch (SQLException e) {
}
return list;
}
  1. 我们用 rs.getMetaData() 获得 ResultSet 元数据
  2. rsmd.getColumnCount() 获得返回的列数
  3. rsmd.getColumnName(i + 1) 获得列名,因为 java.sql 包下的索引都是 1 开始,所以 i + 1

然后我们可以把之前的关闭也一并取消注释,因为 ResultSet 已经被我们整理好了,可以直接关闭释放资源。