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?
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:
- 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.
- Enrouler le paramètre
org.postgresql.util.PGobject
:
PGobject jsonObject = new PGobject();
jsonObject.setType("json");
jsonObject.setValue(yourJsonString);
pstmt.setObject(11, jsonObject);
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);
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 à
Vous avez deux options:
- 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
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.
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.