如何使用Java prepareStatement将JSON对象插入Postgres?

2022-08-31 14:53:33

我正在努力将JSON对象插入到我的postgres v9.4 DB中。我已将名为“evtjson”的列定义为类型(不是)。jsonjsonb

我正在尝试使用Java中的预准备语句(jdk1.8)将Json对象(使用JEE javax.json库构建)插入到列中,但我不断遇到SQLException错误。

我使用以下方法创建 JSON 对象:

JsonObject mbrLogRec = Json.createObjectBuilder().build();
…
mbrLogRec = Json.createObjectBuilder()
                .add("New MbrID", newId)
                .build();

然后,我将此对象作为参数传递给另一个方法,以使用预准备语句将其写入数据库。(以及其他几个字段)如:

pStmt.setObject(11, dtlRec);

使用此方法,我收到以下错误:

org.postgresql.util.PSQLException: No hstore extension installed.at org.postgresql.jdbc.PgPreparedStatement.setMap(PgPreparedStatement.java:553) at org.postgresql.jdbc.PgPreparedStatement.setObject(PgPreparedStatement.java:1036)

我也试过:

pStmt.setString(11, dtlRec.toString());
pStmt.setObject(11, dtlRec.toString());

这会产生不同的错误:

Event JSON: {“New MbrID”:29}

SQLException: ERROR: column “evtjson” 是 json 类型,但表达式的类型是字符可变

提示:您需要重写或强制转换表达式。

但是,至少这告诉我数据库正在将列识别为JSON类型。我确实尝试过安装hstore扩展,但它告诉我它不是hstore对象。

OracleDocs展示了许多在prekedStatement中设置参数值的各种方法,但是如果有人知道答案,我宁愿不尝试所有这些方法。(http://docs.oracle.com/javase/8/docs/api/java/sql/PreparedStatement.html)它们还引用了一个附加参数 SQLType,但我找不到对这些参数的任何引用。

我应该试试吗 ? ?CLOB?setAsciiStreamCharacterStream


答案 1

这种行为非常烦人,因为在SQL命令中用作文本字符串时,JSON字符串可以毫无问题地被接受。

在postgres驱动程序Github存储库中已经存在一个问题(即使问题似乎是服务器端处理)。

除了在 sql 字符串中使用强制转换(参见 @a_horse_with_no_name 的答案)之外,问题作者还提供了两种其他解决方案:

  1. 在 JDBC 连接 URL/选项中使用参数。stringtype=unspecified

这告诉PostgreSQL所有文本或varchar参数实际上都是未知类型,让它更自由地推断它们的类型。

  1. 将参数包装在 :org.postgresql.util.PGobject

 PGobject jsonObject = new PGobject();
 jsonObject.setType("json");
 jsonObject.setValue(yourJsonString);
 pstmt.setObject(11, jsonObject);

答案 2

你可以像这样做,你只需要json字符串:

将查询更改为:

String query = "INSERT INTO table (json_field) VALUES (to_json(?::json))"

并将参数设置为字符串。

pStmt.setString(1, json);