JSONオブジェクトをpostgres v9.4 DBに挿入するのに苦労しています。 「_evtjson」という列をjson
型(jsonb
ではない)として定義しました。
Java(jdk1.8)の準備されたステートメントを使用してJsonオブジェクト(JEE javax.jsonライブラリを使用して構築された)を列に挿入しようとしていますが、SQLExceptionエラーが発生し続けます。
以下を使用してJSONオブジェクトを作成します。
JsonObject mbrLogRec = Json.createObjectBuilder().build();
…
mbrLogRec = Json.createObjectBuilder()
.add("New MbrID", newId)
.build();
次に、このオブジェクトを別のメソッドにパラメーターとして渡し、準備されたステートメントを使用してDBに書き込みます。 (他のいくつかのフィールドとともに)As:
pStmt.setObject(11, dtlRec);
この方法を使用すると、次のエラーが表示されます。
org.postgresql.util.PSQLException:hstore拡張機能がインストールされていません。 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());
別のエラーが発生します:
イベントJSON:{"新しいMbrID":29}
SQLException:エラー:列 "evtjson"はjson型ですが、expressionは可変文字型です
ヒント:式を書き換えるか、キャストする必要があります。
しかし、少なくともこれは、DBが列をJSON型として認識していることを示しています。 hstore拡張機能をインストールしようとしましたが、hstoreオブジェクトではないことを教えてくれました。
OracleDocsでは、preparedStatementにパラメータ値を設定するための様々なメソッドが示されていますが、答えがわかっている場合はすべて試してみたくはありません。 ( http://docs.Oracle.com/javase/8/docs/api/Java/sql/PreparedStatement.html )これらは追加のパラメーターSQLTypeを参照していますが、何も見つかりませんこれらへの参照。
setAsciiStream
を試す必要がありますか? CharacterStream
? CLOB?
JSONコマンドはSQLコマンドでリテラル文字列として使用される場合、問題なく受け入れられるため、この動作は非常に面倒です。
既にpostgresドライバーのGithubリポジトリに issue があります(問題がサーバー側の処理であると思われる場合でも)。
Sql文字列でキャスト(@a_horse_with_no_nameの回答を参照)を使用することに加えて、問題の作成者は2つの追加ソリューションを提供します。
stringtype=unspecified
を使用します。これにより、すべてのテキストまたはvarcharパラメーターは実際には不明なタイプであり、より自由にタイプを推測できるようになります。
org.postgresql.util.PGobject
でラップします。 PGobject jsonObject = new PGobject();
jsonObject.setType("json");
jsonObject.setValue(yourJsonString);
pstmt.setObject(11, jsonObject);
このようにすることができ、json文字列が必要です:
クエリを次のように変更します。
String query = "INSERT INTO table (json_field) VALUES (to_json(?::json))"
パラメータを文字列として設定します。
pStmt.setString(1, json);
JSONを文字列として渡すのが正しいアプローチですが、エラーメッセージが示すように、INSERT
ステートメントのparameterをJSON
値にキャストする必要があります。
insert into the_table
(.., evtjson, ..)
values
(.., cast(? as json), ..)
次に、pStmt.setString(11, dtlRec.toString())
を使用して値を渡すことができます
次の2つのオプションがあります。
`
PreparedStatement statement = con.prepareStatement("insert into table
(jsonColumn) values (?::json)");
statement.setString(1, jsonStr);
2. Another option is to use PGobject to create a custom value wrapper.
PGobject jsonObject = new PGobject();
PreparedStatement statement = con.prepareStatement("insert into table
(jsonColumn) values (?)");
jsonObject.setType("json");
jsonObject.setValue(jsonStr);
statement.setObject(1, jsonObject);
`個人的にはクエリがクリーンなので後者を好む
PostgreSQLは、データ型の変換について非常に面倒です。 xmlやjsonなどのテキストのような値にでも暗黙的にテキストをキャストしません。
したがって、この回答の元のソリューションは、JSON検証をバイパスします
暗黙的な関数なしでキャストを作成します(jsonとしての文字可変);
here CHARACTER VARYINGは、実際に準備済みステートメントオブジェクトに渡そうとしているものです。
Jsonオブジェクトを渡す代わりに、その文字列値を渡し、クエリでjsonにキャストします。例:
JSONObject someJsonObject=..........
String yourJsonString = someJsonObject.toString();
String query = "INSERT INTO table (json_field) VALUES (to_json(yourJsonString::json))";
これは私のために働いた。