簡體   English   中英

Java:查詢結果集到 JSON

[英]Java: Query ResultSet to 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的值始終是 null。

我去過這里的解決方案,但它不適用於從表中選擇*

要輸出 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。 請記住,Paul Benn 的回答仍然有效。

注意:源代碼在 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 - Production\nVersion 21.3.0.0.0",
  "BANNER_LEGACY":"Oracle Database 21c Express Edition Release 21.0.0.0.0 - Production",
  "CON_ID":0
}

使用第三方的解決方案

如果您可以選擇使用第三方庫,您可以使用jOOQ ,它具有多種 JSON 導出功能,包括:

您也可以將其僅用於 JDBC ResultSet到 JSON 的轉換,例如:

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

免責聲明:我為 jOOQ 背后的公司工作

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM