java.sql.SQLException:不正确的字符串值:'\ xF0 \ x9F \ x91 \ xBD \ xF0 \ x9F…'


107

我有以下字符串值:“ 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代码是prepareStatement。所以我正在使用该setString()方法。

看来问题在于值the的编码。我怎样才能解决这个问题?以前我使用的是Derby SQL,而值👽💔最终只是两个平方(我认为这是空字符的表示形式)

非常感谢所有帮助!



创建数据库时,可以提供如下字符集和排序规则:CREATE DATABASE db_name CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
Max Peng

Answers:


145

您所拥有的EXTRATERRESTRIAL ALIEN (U+1F47D)BROKEN HEART (U+1F494)不属于基本的多语言平台。他们不能在Java作为一个字符来表示,甚至,"👽💔".length() == 4。它们绝对不是空字符,如果您不使用支持它们的字体,则会看到正方形。

MySQL的utf8只支持基本多文种平面,你需要使用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:如何将4字节UTF8,utf8mb4与Connector / J一起使用?

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

调整列和数据库:

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

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


看看我其他相关的文章:stackoverflow.com/questions/13748170/…。如果您能回答,那么您也会回答这个问题。另一篇文章详细介绍了我所做的事情。
CodeKingPlusPlus

1
@CodeKingPlusPlus是否已将数据库中的所有内容都更改为utf8mb4,好像您仍在使用utf8_general_ci..
Esailija 2012年

1
:不要做“SET名称”与连接器/ J dev.mysql.com/doc/connector-j/en/... Do not issue the query set names with Connector/J, as the driver will not detect that the character set has changed, and will continue to use the character set detected during the initial connection setup.
bcoughlan

1
如果你只想摆脱人物从BMP外面,而不是处理改变你的DB的乱七八糟的,在这里看到:stackoverflow.com/questions/4035562/...
Indigenuity

2
我有同样的问题,请按照上述步骤操作,但直到解决了C:\ ProgramData \ MySQL \ MySQL Server 5.7 \ my.ini
fattah.safa中

16

总而言之,要保存需要4个字节的符号,您需要更新characher-set和collat​​ion 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属性。


15

奇怪的是,我发现&characterEncoding=UTF-8从删除中JDBC url也有类似问题,这对我来说是成功的窍门。

根据我的属性,

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

我认为这支持@Esailija所说的内容,即我的MySQL(实际上是5.5)正在弄清自己喜欢的UTF-8编码风格。

(注意,我还指定了InputStream我正在从UTF-8Java代码中读取内容,这可能不会造成伤害)...


也许useUnicode=true甚至不需要?在我的情况下,唯一起作用的是character_set_server=utf8mb4在服务器上全局设置(RDS参数组),并且在JDBC URL中没有任何characterEncoding。
约书亚·戴维斯

6

我如何解决我的问题。

我有

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

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


太好了,如果您不需要该索引的列并且它相对较小,但是我可以为我所有的列做这个技巧
shareef

3

将该行追加useUnicode=true&amp;characterEncoding=UTF-8到您的jdbc网址。

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


我该如何附加呢?在我的连接字符串?如果有帮助,我正在使用Netbeans。
CodeKingPlusPlus 2012年

您如何创建连接?
JHS 2012年

DriverManager.getConnection(“ jdbc:mysql:// localhost:#### / [dbName]”,[用户名],[密码]);
CodeKingPlusPlus 2012年

这样做-DriverManager.getConnection(“ jdbc:mysql:// localhost:#### / [dbName]?useUnicode = true&amp; characterEncoding = UTF-8”,[用户名],[密码]);
JHS 2012年

1
从头开始,我忘记了“?” 但是现在我又回到了与原始帖子相同的错误……
CodeKingPlusPlus,2012年

3

我遇到了同样的问题,并通过将每一列的Collat​​ion设置为utf8_general_ci来解决了该问题。


2

我猜MySQL不相信这是有效的UTF8文本。我在具有相同列定义的测试表上尝试了插入(mysql客户端连接也是UTF8),尽管执行了插入操作,但是我使用MySQL CLI客户端以及JDBC检索的数据未正确检索值。为确保UTF8能够正常工作,我为奥巴马插入了“ö”而不是“ 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错误。也许已经有关于这种情况的错误报告了。


顺便说一下,字符串中的字符甚至都无法在OSX上的Firefox和Chrome中正确显示。它们确实正确显示在我的iTerm应用程序中。我认为这取决于字体。
Friek

1

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


1

执行

show VARIABLES like "%char%”;

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

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

vim /etc/my.cnf

加一行

character_set_server = utf8mb4

最后重启mysql


1
character_set_server是选项,不是character-set-server
Arun SR

0

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

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


您能否在答案中添加更多详细信息?(代码,通讯员等)
aBnormaLz

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.