Как вставить объект JSON в Postgres с помощью Java readyStatement?
Я пытаюсь вставить объект JSON в свою базу данных postgres v9.4. Я определил столбец "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();
Затем я передаю этот объект в качестве параметра другому методу, чтобы записать его в БД, используя подготовленный оператор. (вместе с несколькими другими полями) As:
pStmt.setObject(11, dtlRec);
Используя этот метод, я получаю следующую ошибку:
org.postgresql.util.PSQLException: не установлено расширение hstore. на org.postgresql.jdbc.PgPreparedStatement.setMap(PgPreparedStatement.java:553) на org.postgresql.jdbc.PgPreparedStatement.setObject(PgPreparedStatement.java:1036)
Я также пробовал:
pStmt.setString(11, dtlRec.toString());
pStmt.setObject(11, dtlRec.toString());
Из-за чего возникает другая ошибка:
Событие JSON: { "New MbrID": 29}
SQLException: ОШИБКА: столбец "evtjson" имеет тип json, но выражение имеет характерный символ, изменяющийся
Подсказка: вам нужно будет переписать или применить выражение.
Но, по крайней мере, это говорит мне, что БД распознает столбец как тип JSON.
Я попытался установить расширение hstore, но потом сказал мне, что это не объект hstore.
OracleDocs показывает ряд различных методов для установки значения параметра в подготовленном состоянии, но я бы не попробовал их, если кто-то знает ответ. (http://docs.oracle.com/javase/8/docs/api/java/sql/PreparedStatement.html) Они также ссылаются на дополнительный параметр SQLType, но я не могу найти ссылки на них.
Должен ли я попробовать setAsciiStream
? CharacterStream
? CLOB?
Ответы
Ответ 1
Такое поведение довольно раздражает, поскольку строки JSON принимаются без проблем при использовании в качестве литералов в командах SQL.
Существует уже issue для этого в репозитории gigub-драйвера postgres (даже если проблема кажется обработкой на сервере).
Кроме того, используя приведение (см. ответ
@a_horse_with_no_name) в строке sql автор проблемы предлагает два дополнительных решения:
- Используйте параметр
stringtype=unspecified
в URL/опциях подключения JDBC.
Это сообщает PostgreSQL, что все параметры текста или varchar на самом деле неизвестного типа, позволяя ему более свободно выводить свои типы.
- Оберните параметр в
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);
Ответ 3
Передача JSON в качестве строки - правильный подход, но, как сообщает об этом сообщение об ошибке, вам нужно указать параметр в выражении INSERT
в значение JSON
:
insert into the_table
(.., evtjson, ..)
values
(.., cast(? as json), ..)
Затем вы можете использовать pStmt.setString(11, dtlRec.toString())
для передачи значения
Ответ 4
У вас есть два варианта:
- Используйте Statement.setString(jsonStr), а затем обработайте преобразование в выражении 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);
"
Я лично предпочитаю последнее, так как запрос чище
Ответ 5
PostgreSQL чрезмерно, досадно строгий в отношении преобразований типа данных. Он не будет неявно передавать текст даже в текстовые значения, такие как xml и json.
поэтому исходное решение в этом ответе обходит проверку JSON на
создать литье (CHARACTER VARYING как json) без функции как неявное;
здесь CHARACTER VARYING на самом деле вы пытаетесь перейти к вашему подготовленному объекту утверждения.
Ответ 6
Вместо передачи объекта json передать его строковое значение и передать его в json в запросе.
Пример:
JSONObject someJsonObject=..........
String yourJsonString = someJsonObject.toString();
String query = "INSERT INTO table (json_field) VALUES (to_json(yourJsonString::json))";
это сработало для меня.
Ответ 7
мне помогло добавить следующую строку в application.properties:
spring.datasource.hikari.data-source-properties.stringtype=unspecified
как писал Wero:
Это говорит PostgreSQL, что все параметры text или varchar на самом деле неизвестного типа