Использование EclipseLink JPA для хранения типа XML в PostgreSQL

Я новичок в 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, но не повезло. Если кто-нибудь может помочь мне или указать мне сайт в Интернете, чтобы я мог прочитать больше об этом, тогда это было бы большим подспорьем! Спасибо за чтение!


person beyonddc    schedule 26.06.2013    source источник


Ответы (2)


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

Возня с системными каталогами может иметь неожиданные последствия. В этом случае я считаю, что внесение этого изменения достаточно безопасно, но оно все еще возится с внутренностями системы. Действуйте на свой страх и риск.

person Craig Ringer    schedule 26.06.2013

Потенциально вы можете использовать конвертер для преобразования между типом String и Postgres XML.

В противном случае вы можете расширить свою PostgreSQLPlatform для поддержки этого типа. (см. DatabasePlatform.setParameterValueInDatabaseCall(), DatabasePlatform.getCustomModifyValueForCall() и DatabasePlatform.shouldUseCustomModifyForCall()).

Я бы посоветовал вам также зарегистрировать ошибку, если вы не можете заставить ее работать. Должен быть простой способ сделать это.

person James    schedule 26.06.2013
comment
Привет Джеймс, спасибо за ваш ответ. Это тот метод конвертера, о котором вы говорили? stackoverflow.com/questions/3961237/ Я только что попробовал и все равно получаю то же исключение. - person beyonddc; 26.06.2013
comment
На самом деле вы можете использовать преобразователь JPA в PGobject Postgres JDBC stackoverflow.com/a/26126168/1535995 - person Sasa7812; 30.09.2014