Java:将结果集查询为 JSON



查询到Oracle DB通过以下代码发送,并应返回查询结果为JSON

Connection conn ;
try {
Class.forName("oracle.jdbc.driver.OracleDriver"); 
String url = "jdbc:oracle:thin:@localhost:1521:dbname";     
conn = DriverManager.getConnection(url,"username","pwd");  
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM table4 where ID = '5'");

while (rs.next()) {
String s = rs.getString("*");
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
response.getWriter().write(s);
}
conn.close();

} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} 

但是,String s的值始终为空。

我去过这里的解决方案,但它不适用于从表中选择*

要输出 JSON,您需要先将数据累积到List<Map<String, Object>>中。

使用ResultSetMetaData获取列计数和列名。

List<Map<String, Object>> rows = new ArrayList<>();
ResultSetMetaData rsmd = rs.getMetaData();
int columnCount = rsmd.getColumnCount();
while (rs.next()) {
// Represent a row in DB. Key: Column name, Value: Column value
Map<String, Object> row = new HashMap<>();
for (int i = 1; i <= columnCount; i++) {
// Note that the index is 1-based
String colName = rsmd.getColumnName(i);
Object colVal = rs.getObject(i);
row.put(colName, colVal);
}
rows.add(row);
}
// Write the list of rows to output
// Recommend to use jackson-ObjectMapper to streaming json directly to outputstream:
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.writeValue(response.getOutputStream(), rows);

要使用 Jackson ObjectMapper,请将依赖项添加到项目中:

<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.4</version>
</dependency>

这里的问题不是转换为JSON(这已经在您在帖子中链接的这个问题中得到解决(,而是您调用ResultSet的方式。浏览其文档,我们可以看到getString方法可以采用列索引或列标签,但没有提及通配符搜索,例如*.如果您对数据库中的列一无所知,则可以使用 getMetadata(( 方法获取有关列的信息(包括列名(。

我遇到了同样的问题,我写了一个消息正文编写器来解决它。天真地将结果集传递给 Jakarta JSON 绑定 API 不起作用:

jakarta.json.bind.JsonbException: 无法序列化属性 "创作者"来自 oracle.ucp.jdbc.proxy.oracle$1ucp$1jdbc$1proxy$1oracle$1ResultSetProxy$2oracle$1jdbc$1internal$1OracleResultSet$$$Proxy

它与数据库无关,但可扩展并使用Oracle(>= 19(和PostgreSQL进行测试。有许多陷阱需要避免,我不希望公认的解决方案能够完美运行,尤其是对于 Oracle。ResultSet.getObject(int( 和 ResultSet.getObject(String( 可能会返回无法直接序列化的对象,因为它们不是 Java bean。请记住,保罗·本恩的回答仍然有效。

注意:源代码在GPL下。我使用结果集的元数据来获取列,循环访问行,将每个值转换为可以传递给 Jakarta JSON 处理的内容。它需要最新的 JDBC 驱动程序正确管理日期和时间,因为今年实施的一些错误修复和功能会影响它们的转换。如果你必须(重新(实现这样一个工具,请尽可能远离ResultSet.getObject((,否则你的源代码最终将在很大程度上依赖于Oracle JDBC驱动程序中不断变化的和潜在的错误类(ResultSetMetaData.getColumnClassName((为FLOAT返回错误的类名,"java.lang.Double"而不是"java.math.BigDecimal"(。

Oracle/JDBC专用解决方案

如果你想坚持使用 JDBC,那么你可以让 Oracle 数据库为你完成工作,只使用有用的JSON_OBJECT(*)语法:

SELECT JSON_OBJECT(*) FROM table4 WHERE id = '5'

例如:

SELECT JSON_OBJECT(*) FROM v$version;

生产:

{
"BANNER":"Oracle Database 21c Express Edition Release 21.0.0.0.0 - Production",
"BANNER_FULL":"Oracle Database 21c Express Edition Release 21.0.0.0.0 - ProductionnVersion 21.3.0.0.0",
"BANNER_LEGACY":"Oracle Database 21c Express Edition Release 21.0.0.0.0 - Production",
"CON_ID":0
}

使用第三方的解决方案

如果可以选择使用第三方库,则可以使用 jOOQ,它具有多种 JSON 导出功能,包括:

  • 原生 SQL/JSON 支持
  • 将结果集导出为 JSON

您也可以仅将其用于 JDBCResultSet到 JSON 的转换,例如:

try (ResultSet rs = stmt.executeQuery("SELECT * FROM table4 where ID = '5'")) {
String json = ctx.fetch(rs).formatJSON();
}

免责声明:我为jOOQ背后的公司工作

相关内容

  • 没有找到相关文章

最新更新