Подтвердить что ты не робот

Java.sql.SQLException: Неверное строковое значение: '\ xF0\x9F\x91\xBD\xF0\x9F...'

У меня есть следующее строковое значение: "walmart obama 👽💔"

Я использую MySQL и Java.

Я получаю следующее исключение: `java.sql.SQLException: Неверное строковое значение: '\ xF0\x9F\x91\xBD\xF0\x9F...'

Вот переменная, которую я пытаюсь вставить:

var1 varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL`

Мой Java-код, который пытается вставить "walmart obama 👽💔", является подготовленнымСозданием. Поэтому я использую метод setString().

Похоже, что проблема заключается в кодировании значений 👽💔. Как я могу это исправить? Раньше я использовал Derby SQL, а значения 👽💔 только что оказались двумя sqaures (я думаю, что это представление нулевого символа)

Вся помощь очень ценится!

4b9b3361

Ответ 1

То, что у вас есть, - EXTRATERRESTRIAL ALIEN (U+1F47D) и EXTRATERRESTRIAL ALIEN (U+1F47D) BROKEN HEART (U+1F494) которые не находятся в основной многоязычной плоскости. Они даже не могут быть представлены в Java как один символ, "👽💔".length() == 4. Это определенно не нулевые символы, и вы увидите квадраты, если вы не используете шрифты, которые их поддерживают.

MySQL utf8 поддерживает только базовую многоязычную плоскость, и вам нужно использовать вместо utf8mb4:

Для дополнительного символа utf8 не может хранить символ вообще, в то время как utf8mb4 требуется четыре байта для его хранения. Поскольку utf8 не может хранить символ вообще, у вас нет дополнительных символов в столбцах utf8, и вам не нужно беспокоиться о преобразовании символов или потере данных при обновлении данных utf8 из более старых версий MySQL.

Таким образом, для поддержки этих символов ваш MySQL должен быть 5. 5+ и вам нужно везде использовать utf8mb4. Кодировка соединения должна быть utf8mb4, набор символов должен быть utf8mb4 и collaction должен быть utf8mb4. Для java это все еще просто "utf-8", но MySQL нуждается в различии.

Я не знаю, какой драйвер вы используете, но независимый от драйвера способ установить кодировку соединения - это отправить запрос:

SET NAMES 'utf8mb4'

Сразу после установления соединения.

Смотрите также это для Connector/J:

14.14: Как я могу использовать 4-байтовый UTF8, utf8mb4 с Connector/J?

Для использования 4-байтового UTF8 с Connector/J настройте сервер MySQL с параметром character_set_server = utf8mb4. Затем Connector/J будет использовать эту настройку до тех пор, пока символьная кодировка не будет установлена в строке подключения. Это эквивалентно автоматическому определению набора символов.

Настройте ваши столбцы и базу данных, а также:

var1 varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL

Опять же, ваша версия MySQL должна быть относительно современной для поддержки utf8mb4.

Ответ 2

Как ни странно, я обнаружил, что REMOVING &characterEncoding=UTF-8 из JDBC url мне с подобными проблемами.

Основываясь на моих свойствах,

jdbc_url=jdbc:mysql://localhost:3306/dbName?useUnicode=true

Я думаю, что это поддерживает то, что сказал @Esailija выше, то есть мой MySQL, который на самом деле является 5.5, выясняет свой любимый вкус кодировки UTF-8.

(Обратите внимание, я также указываю InputStream я читаю, как UTF-8 в коде Java, что, вероятно, не повредит)...

Ответ 3

В общем, для сохранения символов, требующих 4 байта, вам необходимо обновить набор characher и сортировку для utf8mb4:

  • таблица/столбец базы данных: alter table <some_table> convert to character set utf8mb4 collate utf8mb4_unicode_ci
  • соединение с сервером базы данных (см.)

В моей разработке enviromnt для # 2 я предпочитаю устанавливать параметры в командной строке при запуске сервера: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci


btw, обратите внимание на поведение коннектора /J с помощью SET NAMES 'utf8mb4':

Не выдавайте имена наборов запросов с помощью Connector/J, так как драйвер не обнаружит, что набор символов изменился, и будет продолжать использовать набор символов, обнаруженный во время начальной настройки соединения.

И не следует устанавливать параметр characterEncoding в URL-адресе подключения, поскольку он будет переопределять настроенную кодировку сервера:

Чтобы переопределить автоматически обнаруженную кодировку на стороне клиента, используйте свойство characterEncoding в URL-адресе, используемом для подключения к серверу.

Ответ 4

Как я решил свою проблему.

У меня был

?useUnicode=true&amp;characterEncoding=UTF-8

В моем hibernate подключении jdbc url и я изменили тип данных строки на longtext в базе данных, который раньше был varchar.

Ответ 5

Я столкнулся с той же проблемой и решил ее, установив Collation на utf8_general_ci для каждого столбца.

Ответ 6

Добавьте строку useUnicode=true&amp;characterEncoding=UTF-8 к URL-адресу jdbc.

В вашем случае данные не отправляются с использованием UTF-8.

Ответ 7

Я думаю, что MySQL не считает это действительным текстом UTF8. Я попробовал вставку в тестовую таблицу с тем же определением столбцов (соединение с mysql-клиентом также было UTF8), и хотя он вставлял, данные, которые я получил с клиентом MySQL CLI, а также JDBC, неправильно отображали значения. Чтобы убедиться, что UTF8 работает правильно, я вставил вместо "o" для obama "ö":

[email protected]:~$ mysql -vvv test < insert.sql 
--------------
insert into utf8_test values(_utf8 "walmart öbama 👽💔")
--------------

Query OK, 1 row affected, 1 warning (0.12 sec)

[email protected]:~$ file insert.sql 
insert.sql: UTF-8 Unicode text

Малое приложение Java для тестирования:

package test.sql;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class Test
{

    public static void main(String[] args)
    {
        System.out.println("test string=" + "walmart öbama 👽💔");
        String url = "jdbc:mysql://hostname/test?useUnicode=true&characterEncoding=UTF-8";
        try
        {
            Class.forName("com.mysql.jdbc.Driver").newInstance();
            Connection c = DriverManager.getConnection(url, "username", "password");
            PreparedStatement p = c.prepareStatement("select * from utf8_test");
            p.execute();
            ResultSet rs = p.getResultSet();
            while (!rs.isLast())
            {
                rs.next();
                String retrieved = rs.getString(1);
                System.out.println("retrieved=\"" + retrieved + "\"");

            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

}

Вывод:

[email protected]:~/workspaces/java/javatest/bin$ java test.sql.Test
test string=walmart öbama 👽💔
retrieved="walmart öbama "

Кроме того, я пробовал одну и ту же вставку с JDBC-соединением, и это привело к тому же исключению, которое вы получаете. Я считаю, что это ошибка MySQL. Может быть, там уже есть сообщение об ошибке.

Ответ 8

У меня была одна и та же проблема, и после тщательного изучения всех кодировок и выяснения, что с ними все в порядке, я понял, что свойство bugged, которое у меня было в моем классе, было аннотировано как @Column вместо @JoinColumn (javax.presistence; hibernate), и это все ломало.

Ответ 9

выполнять

show VARIABLES like "%char%";

найти набор символов сервера, если не utf8mb4.

установите его в вашем my.cnf, как

vim /etc/my.cnf

добавить одну строку

character_set_server = utf8mb4

наконец перезапустите MySQL

Ответ 10

Этот параметр useOldUTF8Behavior = true работал нормально для меня. Он не дал неправильных строковых ошибок, но он преобразовал специальные символы, такие как Ã, в несколько символов и сохранил в базе данных.

Чтобы избежать подобных ситуаций, я удалил это свойство из параметра JDBC и вместо этого преобразовал тип данных моего столбца в BLOB. Это сработало идеально.

Ответ 11

Кроме того, тип данных может использовать blob install из varchar или text.