webentwicklung-frage-antwort-db.com.de

Wie kann ich ein JSON-Objekt mit Java prepareStatement) in Postgres einfügen?

Ich habe Probleme, ein JSON-Objekt in meine postgres v9.4-Datenbank einzufügen. Ich habe die Spalte mit dem Namen "evtjson" als Typ json (nicht jsonb) definiert.

Ich versuche, eine vorbereitete Anweisung in Java (jdk1.8)) zu verwenden, um ein Json-Objekt (erstellt mit JEE javax.json-Bibliotheken) in die Spalte einzufügen, aber es treten weiterhin SQLException-Fehler auf.

Ich erstelle das JSON-Objekt mit:

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

Dann übergebe ich dieses Objekt als Parameter an eine andere Methode, um es mit einer vorbereiteten Anweisung in den DB zu schreiben. (zusammen mit einigen anderen Feldern) Als:

pStmt.setObject(11, dtlRec);

Bei Verwendung dieser Methode erhalte ich die folgende Fehlermeldung:

org.postgresql.util.PSQLException: Keine Speichererweiterung installiert. um org.postgresql.jdbc.PgPreparedStatement.setMap (PgPreparedStatement.Java:553) um org.postgresql.jdbc.PgPreparedStatement.setObject (PgPreparedStatement.Java:1036)

Ich habe auch versucht:

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

Welche erzeugen einen anderen Fehler:

Ereignis-JSON: {"New MbrID": 29}

SQLException: ERROR: Spalte "evtjson" ist vom Typ json, aber Ausdruck ist vom Typ Character Variating

Hinweis: Sie müssen den Ausdruck neu schreiben oder umwandeln.

Aber zumindest sagt mir dies, dass die Datenbank die Spalte als Typ JSON erkennt. Ich habe versucht, die hstore-Erweiterung zu installieren, aber dann wurde mir mitgeteilt, dass es sich nicht um ein hstore-Objekt handelt.

OracleDocs zeigt eine Reihe verschiedener Methoden zum Festlegen des Parameterwerts im prepareStatement, aber ich würde sie lieber nicht alle ausprobieren, wenn jemand die Antwort kennt. ( http://docs.Oracle.com/javase/8/docs/api/Java/sql/PreparedStatement.html ) Diese verweisen auch auf einen zusätzlichen Parameter, SQLType, aber ich kann keinen finden Verweis auf diese.

Soll ich setAsciiStream versuchen? CharacterStream? CLOB?

39

Dieses Verhalten ist ziemlich ärgerlich, da JSON-Zeichenfolgen problemlos akzeptiert werden, wenn sie als Literalzeichenfolgen in SQL-Befehlen verwendet werden.

Es gibt bereits ein Problem im Github-Repository des Postgres-Treibers (auch wenn das Problem bei der serverseitigen Verarbeitung zu liegen scheint).

Neben der Verwendung einer Besetzung (siehe Antwort von @a_horse_with_no_name) in der SQL-Zeichenfolge bietet der Issue-Autor zwei zusätzliche Lösungen an:

  1. Verwenden Sie einen Parameter stringtype=unspecified in der JDBC-Verbindungs-URL/-Optionen.

Dies teilt PostgreSQL mit, dass alle Text- oder Varchar-Parameter tatsächlich von unbekanntem Typ sind, so dass sie ihre Typen freier ableiten können.

  1. Wickle den Parameter in ein org.postgresql.util.PGobject:
 PGobject jsonObject = new PGobject();
 jsonObject.setType("json");
 jsonObject.setValue(yourJsonString);
 pstmt.setObject(11, jsonObject);
45
wero

Du kannst es so machen und brauchst nur den json String:

Ändern Sie die Abfrage in:

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

Und setzen Sie den Parameter als String.

pStmt.setString(1, json);
23
Tiago

Das Übergeben des JSON als String ist der richtige Ansatz, aber wie Sie in der Fehlermeldung sehen, müssen Sie das Parameter in der INSERT -Anweisung in einen JSON-Wert umwandeln :

insert into the_table
   (.., evtjson, ..) 
values 
   (.., cast(? as json), ..)

Dann können Sie pStmt.setString(11, dtlRec.toString()) verwenden, um den Wert zu übergeben

12

Sie haben zwei Möglichkeiten:

  1. Verwenden Sie statement.setString (jsonStr) und führen Sie dann die Konvertierung in der SQL-Anweisung durch:

`

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);

`Ich persönlich bevorzuge letzteres, da die Abfrage sauberer ist

5
pedram bashiri

PostgreSQL geht bei der Konvertierung von Datentypen übermäßig streng vor. Es wird nicht implizit Text in textähnliche Werte wie xml und json umgewandelt.

die ursprüngliche Lösung in dieser Antwort umgeht daher die JSON-Validierung durch

cast erstellen (CHARACTER VARYING as json) ohne implizite Funktion;

hier CHARACTER VARYING ist eigentlich, dass Sie versuchen, an Ihr vorbereitetes Anweisungsobjekt zu übergeben.

0
deadpool

Anstatt das json-Objekt zu übergeben, übergeben Sie seinen Zeichenfolgenwert und wandeln ihn in der Abfrage in json um. Beispiel:

JSONObject someJsonObject=..........

String yourJsonString = someJsonObject.toString();

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

das hat bei mir funktioniert.

0
Komal Thakur