У меня проблемы с записью и чтением специальных символов, таких как знак евро (€), в свойства 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 для получения прямого поведения при хранении.
Оба подхода работают нормально, за исключением того момента, когда я хочу работать со специальными символами, такими как знак евро (€). В этом случае механизм прямого хранения продолжает работать, но механизм косвенного хранения выходит из строя.
Я бы хотел продемонстрировать это на примере. Я создал тестовую сущность с 2 свойствами @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, я вижу следующее.
id | clob_value_direct_storage | clob_value_indirect_storage
----+---------------------------+----------------------------
6 | € | 910579
Если я затем запрашиваю таблицу pg_largeobject, то вижу:
loid | pageno | data
--------+--------+------
910579 | 0 | \254
Столбец «data» в pg_largeobject имеет тип bytea, что означает, что информация хранится в виде необработанных байтов. Выражение «\ 254» представляет один байт, а в UTF-8 представляет символ «¬». Это именно то значение, которое я получаю при загрузке объекта обратно из базы данных.
Знак евро в UTF-8 состоит из 3 байтов, поэтому я ожидал, что столбец «data» будет иметь 3 байта, а не 1.
Это происходит не только для знака евро, но и для многих специальных символов. Это проблема в Hibernate? Или драйвер JDBC? Есть ли способ, которым я могу настроить это поведение?
Заранее спасибо,
С уважением,
Франк де Брюйн