Невозможно сохранить Euro-sign в свойстве LOB String с Hibernate/PostgreSQL

У меня возникают проблемы с записью и чтением специальных символов, таких как знак евро (€), в свойства LOB String в PostgreSQL 8.4 с Hibernate 3.6.10.

Что мне известно, так это то, что PostgreSQL предоставляет два различных способа хранения больших символьных объектов в столбце таблицы. Они могут храниться либо непосредственно в этом столбце таблицы, либо косвенно в отдельной таблице (на самом деле она называется pg_largeobject). В последнем случае столбец содержит ссылку (OID) на строку в pg_largeobject.

Поведение по умолчанию в Hibernate 3.6.10 — непрямой подход OID. Однако можно добавить дополнительную аннотацию @org.hibernate.annotations.Type(type="org.hibernate.type.TextType") к свойству Lob, чтобы получить поведение прямого хранения.

Оба подхода работают нормально, за исключением того момента, когда я хочу работать со специальными символами, такими как знак евро (€). В этом случае механизм прямого хранения продолжает работать, но ломается механизм косвенного хранения.

Я хотел бы продемонстрировать это на примере. Я создал тестовую сущность с двумя свойствами @Lob.Один следует принципу прямого хранения, другой — косвенному:

@Basic
@Lob
@Column(name = "CLOB_VALUE_INDIRECT_STORAGE", length = 2147483647)
public String getClobValueIndirectStorage()

и

@Basic
@Lob
@org.hibernate.annotations.Type(type="org.hibernate.type.TextType")
@Column(name = "CLOB_VALUE_DIRECT_STORAGE", length = 2147483647)
public String getClobValueDirectStorage()

Если я создаю объект, заполняю оба свойства знаком евро, а затем сохраняю его в базе данных, я вижу следующее, когда я делаю SELECT I см.

 id | clob_value_direct_storage | clob_value_indirect_storage
----+---------------------------+----------------------------
  6 | €                         | 910579                     

Если я затем запрошу таблицу pg_largeobject, я увижу:

  loid  | pageno | data
--------+--------+------
 910579 |      0 | \254

Столбец «данные» pg_largeobject имеет тип bytea, что означает, что информация хранится в виде необработанных байтов. Выражение '\254' представляет один единственный байт, а в UTF-8 представляет символ '¬'. Это именно то значение, которое я получаю, когда загружаю объект обратно из базы данных.

Знак евро в UTF-8 состоит из 3 байтов, поэтому я ожидал, что столбец «данные» будет иметь 3 байта, а не 1.

Это происходит не только для знака евро, но и для многих специальных символы. Это проблема в Hibernate? Или драйвер JDBC? Есть ли способ настроить это поведение?

Заранее спасибо,
С уважением,
Франк де Брюйн

10
задан Franck de Bruijn 3 April 2012 в 12:54
поделиться