116

我有以下字符串值:“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`

我试图插入“walmart obama”的Java 代码是preparedStatement。所以我正在使用该setString()方法。

看起来问题是值的编码。我怎样才能解决这个问题?以前我使用的是 Derby SQL,而这些值最终变成了两个正方形(我认为这是空字符的表示)

非常感谢所有帮助!

4

11 回答 11

152

你所拥有的EXTRATERRESTRIAL ALIEN (U+1F47D)BROKEN HEART (U+1F494)不在基本的多语言平面中的。它们甚至不能在 java 中表示为一个字符,"".length() == 4. 它们绝对不是空字符,如果你不使用支持它们的字体,你会看到方块。

MySQLutf8只支持基本的多语言平面,你需要utf8mb4改用

对于补充字符,utf8 根本无法存储字符,而 utf8mb4 需要四个字节来存储它。由于 utf8 根本无法存储字符,因此在 utf8 列中没有任何补充字符,并且在从旧版本的 MySQL 升级 utf8 数据时不必担心转换字符或丢失数据。

所以要支持这些字符,你的 MySQL 需要 5.5+ 并且你需要在utf8mb4任何地方使用。连接编码需要是utf8mb4,字符集需要是utf8mb4,并且整理需要是utf8mb4。对于 java 它仍然只是"utf-8",但 MySQL 需要区分。

我不知道您使用的是什么驱动程序,但设置连接字符集的与驱动程序无关的方法是发送查询:

SET NAMES 'utf8mb4'

在建立连接之后。

另请参阅 Connector/J

14.14: 如何在 Connector/J 中使用 4 字节 UTF8、utf8mb4?

要将 4 字节 UTF8 与 Connector/J 一起使用,请使用 character_set_server=utf8mb4 配置 MySQL 服务器。只要在连接字符串中设置characterEncoding ,Connector/J 就会使用该设置 。这相当于字符集的自动检测。

调整您的列和数据库:

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

同样,您的 MySQL 版本需要相对最新才能支持 utf8mb4。

于 2012-12-07T00:15:18.547 回答
19

奇怪的是,我发现&characterEncoding=UTF-8JDBC url类似的问题中删除对我有用。

根据我的属性,

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

我认为这支持@Esailija 上面所说的,即我的MySQL,它确实是5.5,正在找出它自己最喜欢的UTF-8 编码风格。

(注意,我还指定了InputStreamUTF-8在 java 代码中读取的内容,这可能没有什么坏处)......

于 2013-09-10T22:12:01.623 回答
17

总而言之,要保存需要 4 个字节的符号,您需要更新字符集和排序规则utf8mb4

  1. 数据库表/列: alter table <some_table> convert to character set utf8mb4 collate utf8mb4_unicode_ci
  2. 数据库服务器连接(

在#2 的开发环境中,我更喜欢在启动服务器时在命令行上设置参数: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci


顺便说一句,注意连接器/J的行为SET NAMES 'utf8mb4'

不要使用 Connector/J 发出查询集名称,因为驱动程序不会检测到字符集已更改,并将继续使用在初始连接设置期间检测到的字符集。

并避免characterEncoding在连接 url 中设置参数,因为它会覆盖配置的服务器编码:

要覆盖客户端自动检测到的编码,请使用用于连接到服务器的 URL 中的 characterEncoding 属性。

于 2015-12-22T18:40:54.430 回答
6

我是如何解决我的问题的。

我有

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

在我的休眠 jdbc 连接 url 中,我将字符串数据类型更改为数据库中的 longtext,之前是 varchar。

于 2013-10-24T14:30:40.500 回答
4

我遇到了同样的问题,并通过将每列的排序规则设置为utf8_general_ci来解决它。

于 2015-05-26T06:58:27.973 回答
3

将该行附加useUnicode=true&amp;characterEncoding=UTF-8到您的 jdbc url。

在您的情况下,数据不是使用UTF-8编码发送的。

于 2012-11-30T21:54:31.987 回答
2

我猜 MySQL 不相信这是有效的 UTF8 文本。我尝试在具有相同列定义的测试表上插入(mysql 客户端连接也是 UTF8),虽然它进行了插入,但我使用 MySQL CLI 客户端和 JDBC 检索的数据没有正确检索值。为了确保 UTF8 能正常工作,我为 obama 插入了一个“ö”而不是“o”:

johan@maiden:~$ mysql -vvv test < insert.sql 
--------------
insert into utf8_test values(_utf8 "walmart öbama ")
--------------

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

johan@maiden:~$ 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();
        }
    }

}

输出:

johan@appel:~/workspaces/java/javatest/bin$ java test.sql.Test
test string=walmart öbama 
retrieved="walmart öbama "

此外,我已经尝试使用 JDBC 连接进行相同的插入,它抛出了与您得到的相同的异常。我相信这是一个 MySQL 错误。也许已经有关于这种情况的错误报告..

于 2012-12-06T12:34:58.120 回答
1

我遇到了同样的问题,在仔细检查所有字符集并发现它们都很好之后,我意识到我在课堂上的错误属性被注释为 @Column 而不是 @JoinColumn (javax.presistence; hibernate) 和它打破了一切。

于 2015-02-18T20:21:50.617 回答
0

这个设置 useOldUTF8Behavior=true 对我来说很好。它没有给出不正确的字符串错误,而是将 Ã 等特殊字符转换为多个字符并保存在数据库中。

为了避免这种情况,我从 JDBC 参数中删除了这个属性,而是将我的列的数据类型转换为 BLOB。这很完美。

于 2019-01-28T15:27:29.417 回答
0

执行

show VARIABLES like "%char%”;

如果不是 utf8mb4,则查找字符集服务器。

将其设置在您的 my.cnf 中,例如

vim /etc/my.cnf

添加一行

character_set_server = utf8mb4

最后重启mysql

于 2018-07-05T05:39:31.993 回答
-3

此外,数据类型可以使用 varchar 或 text 的 blob install。

于 2018-09-23T16:38:23.543 回答