PostgreSQL вставляет знаки вопроса вместо символов Юникода

1

Всякий раз, когда в приложении появляется вставка, все символы Юникода (будь то японский, греческий и т.д.) Заменяются вопросительными знаками.

SAVEPOINT "DAO"
LOG:  execute <unnamed>: insert into foo values ($1,$2,$3)
DETAIL:  parameters: $1 = '23', $2 = '34bcb5f2-e7ee-40cf-9103-f2d1bf2ac7acd853d7c6-1703-44d2-aa99-6fd1df84da37', $3 = 'Anyone-日本語_l'

Как видно из приведенной выше записи в журнале, база данных принимает правильные параметры Юникода.

Однако после вставки запись в таблице выглядит следующим образом:

23 | 34bcb5f2-e7ee-40cf-9103-f2d1bf2ac7acd853d7c6-1703-44d2-aa99-6fd1df84da37 | Anyone-???_l

Мое первое предположение заключалось в том, что это проблема с конфигурацией базы данных, однако я подтвердил (насколько мне известно), что Postgres действительно принимает UTF-8, выполняя следующие действия:

SHOW server_encoding;
server_encoding
-----------------
UTF8
(1 row)

SHOW client_encoding;
client_encoding
-----------------
UTF8
(1 row)

Я также подтвердил это, вручную вставив запись в базу данных:

INSERT INTO foo values(25, ‘the_id, ‘ΑΒΓΔΕΖΗΘ);
INSERT 0 1
25 | the_id | ΑΒΓΔΕΖΗΘ

Как вы можете понять из вышеизложенного, база данных приняла мои значения и успешно добавила символы Юникода в базу данных.

На данный момент я считаю, что проблема возникает, когда эти значения переносятся из моего приложения в JDBC-коннектор и в базу данных. Я думал, что, возможно, JDBC-коннектор должен сказать, что он будет передавать данные Unicode. Это действительно способ сделать это, добавив следующее в URL-адрес соединителя JDBC:

jdbc:postgresql://localhost/bar?useUnicode=yes&characterEncoding=UTF-8

К сожалению, вышесказанное не имело никакого значения.

Я исключил код приложения, поскольку он является частью очень большого проекта, и соответствующие фрагменты фрагментированы здесь и там. Тем не менее, я думаю, что они не имеют отношения к проблеме, поскольку журнал Postgres ясно отображает полученные им параметры.

Запрос и данные Unicode, полученные базой данных, являются правильными, так что вызывает эту проблему?

OS: RHEL 6.6
Postgres version: 9.3.5
JDBC Connector: Tried a couple (8.1, 9.3)
JRE: 1.7

База данных действительно ожидает UTF-8:

psql -U postgres -h localhost --list

Name      |  Owner   | Encoding |   Collate   |    Ctype    |   Access privileges
----------------+----------+----------+-------------+-------------+--------------
bar       | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 |

Результат bytea соответствующей записи следующий:

SELECT foo_name::bytea FROM foo;

foo_name
--------------------------
\x416e796f6e652d3f3f3f5f6c

В базу данных фактически вставлены вопросительные знаки:

SELECT * FROM foo WHERE foo_name LIKE 'Anyone-?%'
23 | 34bcb5f2-e7ee-40cf-9103-f2d1bf2ac7acd853d7c6-1703-44d2-aa99-6fd1df84da37 | Anyone-???_l

Я также схватил байтовую последовательность одного из моих тестов, который был сгенерирован контроллером JDBC, прежде чем он был отправлен в PGStream.

{65, 110, 121, 111, 110, 101, 45, -26, -105, -91, -26, -100, -84, -24, -86, -98, 95, 105}

Я преобразовал это в строку UTF-8, выполнив следующее (в автономном приложении):

String result = new String(bytes, StandardCharsets.UTF_8);

Результат был правильным: Anyone- 日本語 _i

  • 2
    Просто для записи, параметры соединения useUnicode=yes и characterEncoding=UTF-8 не применяются ко всем драйверам JDBC. Они характерны для MySQL Connector / J и не отображаются в списке параметров соединения для драйвера PostgreSQL JDBC .
  • 1
    Попробуйте psql -U postgres -h localhost --list из командной строки ОС, чтобы psql -U postgres -h localhost --list список баз данных и проверить Encoding конкретной базы данных. Вы убедились, что кодировка (по умолчанию) для сервера - UTF8 но возможно, что база данных имеет другую кодировку.
Показать ещё 2 комментария
Теги:
jdbc
unicode

2 ответа

3
Лучший ответ

После изучения глубокого устаревшего кода я нашел и исправил проблему.

Уровень базы данных работал нормально; проблема возникла, когда система попыталась повторно вставить одно и то же значение в базу данных с помощью ByteArrayInputStream.

ByteArrayInputStream заполнялся выполнением getBytes() в String, который содержал имя foo_name. Однако при вызове этого метода необходимо определить кодировку UTF-8.

Путем изменения:

String name = "日本語";
InputStream is = new ByteArrayInputStream(name.getBytes());

чтобы:

String name = "日本語";
InputStream is = new ByteArrayInputStream(name.getBytes(StandardCharsets.UTF_8));

проблема была исправлена.

1

У меня была проблема с unicode-8, с postgres и glassfish. Я попробовал это в файле persistence.xml и исправил это. Я надеюсь, что это может помочь вам

<properties>
  <property name="javax.persistence.jdbc.url"
           value="jdbc:postgresql://(url_Project)?useUnicode=yes"/>
</properties>

(url_Proyecto) - полный URL-адрес базы данных

Ещё вопросы

Сообщество Overcoder
Наверх
Меню