У меня возникают проблемы с записью и чтением специальных символов, таких как знак евро (€), в свойства 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? Есть ли способ настроить это поведение?
Заранее спасибо,
С уважением,
Франк де Брюйн