Comment puis-je insérer un objet JSON dans Postgres en utilisant Java preparedstat?

j'ai du mal à insérer un objet JSON dans mon postgres v9.4 DB. J'ai défini la colonne appelée "evtjson" comme type json (pas jsonb).

j'essaie d'utiliser une déclaration préparée en Java (jdk1.8) pour insérer un objet JSON (construit en utilisant JEE javax.JSON libraries) dans la colonne, mais je continue à courir dans les erreurs SQLException.

je crée l'objet JSON en utilisant:

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

alors je passe cet objet comme paramètre à une autre méthode pour l'écrire au DB en utilisant une déclaration préparée. (ainsi que plusieurs autres champs):

pStmt.setObject(11, dtlRec);

en utilisant cette méthode, je reçois l'erreur suivante:

org.PostgreSQL.util.PSQLException: aucune extension hstore installée. au org.PostgreSQL.jdbc.PgPreparedStatement.setMap (PgPreparedStatement.java: 553) au org.PostgreSQL.jdbc.PgPreparedStatement.setObject (PgPreparedStatement.java: 1036)

j'ai aussi essayé:

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

qui produisent une erreur différente:

Événement JSON: {"Nouvelle MbrID":29}

SQLException: ERREUR: la colonne "evtjson" est de type json, mais l'expression est de type character varying

Conseil: vous aurez besoin de réécrire ou de lancer l'expression.

mais, au moins cela me dit que le DB reconnaît la colonne comme étant de type JSON. J'ai essayé d'installer le hstore extension, mais il m'a dit qu'il n'était pas un objet hstore.

OracleDocs montre un certain nombre de différentes méthodes pour définir la valeur du paramètre dans l'état de préparation, mais je préfère ne pas les essayer tous si quelqu'un connaît la réponse. (http://docs.oracle.com/javase/8/docs/api/java/sql/PreparedStatement.html) Ceux-ci font également référence à un paramètre supplémentaire, SQLType, mais je ne trouve aucune référence à ceux-ci.

Devrais-je essayer <!--5? <!--6? CLOB?

30
demandé sur Alexander Farber 2016-03-07 15:46:18

6 réponses

ce comportement est assez gênant puisque les chaînes JSON sont acceptées sans problème lorsqu'elles sont utilisées comme des chaînes littérales dans les commandes SQL.

Il y a déjà un problème pour cela dans le pilote Github de Postgres (même si le problème semble être le traitement serverside).

en plus d'utiliser un plâtre (voir réponse de @a_horse_with_no_name) dans la chaîne sql, l'auteur de la question offre deux solutions supplémentaires:

  1. utilisez un paramètre stringtype=unspecified dans la connexion JDBC URL / options.

cela indique à PostgreSQL que tous les paramètres de texte ou de varchar sont en fait de type inconnu, laissant inférer leurs types plus librement.

  1. Enrouler le paramètre org.postgresql.util.PGobject:

 PGobject jsonObject = new PGobject();
 jsonObject.setType("json");
 jsonObject.setValue(yourJsonString);
 pstmt.setObject(11, jsonObject);
36
répondu wero 2016-03-07 13:38:58

Vous pouvez le faire comme ceci et vous avez juste besoin de la chaîne json:

Modifier la requête:

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

et définissez le paramètre comme une chaîne de caractères.

pStmt.setString(1, json);
18
répondu Tiago 2016-03-07 15:06:51

passer le JSON comme une chaîne est la bonne approche, mais comme le message d'erreur vous le dit, vous devez lancer le paramètre dans le INSERT déclaration JSON valeur:

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

alors vous pouvez utiliser pStmt.setString(11, dtlRec.toString()) pour passer la valeur à

11
répondu a_horse_with_no_name 2016-03-07 12:53:22

Vous avez deux options:

  1. déclaration d'Utilisation.setString (jsonStr) puis gérer la conversion dans la déclaration sql:

`

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

` Personnellement, je préfère ce dernier car la requête est plus propre

1
répondu pedram bashiri 2018-04-18 19:39:04

PostgreSQL est excessivement strict sur les conversions de type de données. Il ne va pas lancer le texte même implicitement à des valeurs de type texte telles que xml et json.

ainsi la solution originale dans cette réponse contourne la validation JSON par

créer un cast (CARACTÈRE VARIABLE json) sans fonction implicite;

ici VARIATION DES CARACTÈRES est en fait vous essayez de passer à votre déclaration de l'objet.

0
répondu deadpool 2016-10-03 10:29:06

au lieu de passer l'objet json, passez sa valeur string et jetez-la à json dans la requête. Exemple:

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

String yourJsonString = someJsonObject.toString();

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

cela a fonctionné pour moi.

0
répondu Komal Thakur 2017-05-03 12:24:05