У меня возникли проблемы с написанием и чтением специальных символов, таких как знак Евро (€), в свойства 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, чтобы получить прямое поведение хранилища.
Оба подхода работают отлично, за исключением того, что я хочу работать со специальными символами, такими как знак Euro (€). В этом случае механизм прямого хранения продолжает работать, но механизм косвенного хранения прерывается.
Я хотел бы продемонстрировать это на примере. Я создал тестовый объект с 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()
Если я создаю объект, заполните оба свойства знаком Euro, а затем сохраняйте его в базе данных, я вижу следующее, когда я делаю 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 - символ "¬". Это именно то значение, которое я возвращаю, когда я загружаю объект обратно из базы данных.
Знак Euro в UTF-8 состоит из 3 байтов, поэтому я ожидал, что столбец "data" будет иметь 3 байта, а не 1.
Это происходит не только для знака Euro, но и для многих специальных символов. Это проблема в Hibernate? Или драйвер JDBC? Есть ли способ, которым я могу настроить это поведение?
Спасибо заранее,
С уважением,
Franck de Bruijn