Я новичок в JPA, и у меня есть вопрос о том, как использовать JPA для хранения типа XML в PostgreSQL. Я просто расширяю существующий POJO, чтобы включить в столбец сохранение дополнительного поля XML. POJO выглядит примерно так (я намеренно пропустил несколько других столбцов, чтобы сделать его короче, прежде чем добавлять этот дополнительный тип XML, этот POJO может прекрасно сохраняться в PostgreSQL через JPA).
public class Finding implements Serializable {
private static final long serialVersionUID = -5814053129578212916L;
...
@Column(name = "PLUGIN_TEXT_XML")
private String pluginTextXML;
public void setPluginText(String pluginText) {
this.pluginText = pluginText;
}
public String getPluginTextXML() {
return pluginTextXML;
}
}
Когда я пытаюсь сохранить этот POJO, я получил PSQLException
Caused by: org.postgresql.util.PSQLException: ERROR: column "plugin_text_xml" is of type xml but expression is of type character varying
Hint: You will need to rewrite or cast the expression.
Position: 668
Я пытался посмотреть в Интернете, как сопоставить тип XML в JPA, но не повезло. Если кто-нибудь может помочь мне или указать мне сайт в Интернете, чтобы я мог прочитать больше об этом, тогда это было бы большим подспорьем! Спасибо за чтение!
Ответ 1 · рейтинг 4 · Craig Ringer
PostgreSQL раздражающе строго относится к неявным приведениям между текстовыми типами, такими как json, xml и т. д.
Строго правильное решение - использовать setObject(the_string, java.sql.Types.SQLXML) при установке параметра с помощью JDBC. Это сложно через уровни ORM, и многие ORM, похоже, не понимают напрямую типы SQL/XML.
Вы можете указать PostgreSQL разрешить неявное преобразование text в xml, изменив системные каталоги. Это не идеально, но это сработает.
В psql вы можете использовать \dC xml для перечисления кошек в xml:
List of casts
Source type | Target type | Function | Implicit?
-------------------+-------------------+--------------------+---------------
character | xml | xml | no
character varying | xml | xml | no
text | xml | xml | no
xml | character | (binary coercible) | in assignment
xml | character varying | (binary coercible) | in assignment
xml | text | (binary coercible) | in assignment
(6 rows)
Видите "неявное: нет"?
Вам нужно сделать их присваиваемо-конвертируемыми. Так как это встроенные типы, вы не можете CREATE CAST для них, вы должны обновить каталоги напрямую, изменив pg_cast таблицу.
UPDATE pg_cast SET castcontext = 'a'
FROM pg_cast c
INNER JOIN pg_type srctype ON (c.castsource = srctype.oid)
INNER JOIN pg_type dsttype on (c.casttarget = dsttype.oid)
WHERE pg_cast.oid = c.oid
AND srctype.typname IN ('text','varchar')
AND dsttype.typname = 'xml';
Возня с системными каталогами может иметь неожиданные последствия. В этом случае я считаю, что внесение этого изменения достаточно безопасно, но оно все еще возится с внутренностями системы. Действуйте на свой страх и риск.
Ответ 2 · рейтинг 1 · James
Потенциально вы можете использовать конвертер для преобразования между типом String и Postgres XML.
В противном случае вы можете расширить свою PostgreSQLPlatform для поддержки этого типа. (см. DatabasePlatform.setParameterValueInDatabaseCall(), DatabasePlatform.getCustomModifyValueForCall() и DatabasePlatform.shouldUseCustomModifyForCall()).
Я бы посоветовал вам также зарегистрировать ошибку, если вы не можете заставить ее работать. Должен быть простой способ сделать это.