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

时间:2012-11-30 21:51:41

标签: java mysql encoding character-encoding sqlexception

我有以下字符串值:“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,最后只有两个sqaures(我认为这是空字符的表示)

非常感谢所有帮助!

11 个答案:

答案 0 :(得分:127)

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

MySQL's utf8 only supports basic multilingual plane, and you need to use utf8mb4 instead

  

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

因此,要支持这些字符,您的MySQL需要为5.5+,并且您需要在任何地方使用utf8mb4。连接编码需要为utf8mb4,字符集必须为utf8mb4,并且拼贴需要为utf8mb4。对于java,它仍然只是"utf-8",但MySQL需要区分。

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

SET NAMES 'utf8mb4'

建立连接后。

See also this for Connector/J

  

14.14:如何使用带有Connector / J的4字节UTF8,utf8mb4?

     

使用带有Connector / J的4字节UTF8配置MySQL服务器   被character_set_server = utf8mb4。然后,Connector / J将使用该设置   只要characterEncoding在连接中设置即可   串。这相当于自动检测字符集。

调整列和数据库:

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

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

答案 1 :(得分:14)

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

根据我的属性,

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

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

(注意,我还在java代码中指定InputStream我正在读UTF-8,这可能不会受到伤害)......

答案 2 :(得分:14)

总而言之,要保存需要4个字节的符号,您需要更新utf8mb4的字符集和校对:

  1. 数据库表/列: alter table <some_table> convert to character set utf8mb4 collate utf8mb4_unicode_ci
  2. 数据库服务器连接(see
  3. 在我的#2开发环境中,我更喜欢在启动服务器时在命令行上设置参数: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci

    顺便说一下,SET NAMES 'utf8mb4'注意Connector/J behavior

      

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

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

      

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

答案 3 :(得分:6)

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

我有

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

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

答案 4 :(得分:3)

我遇到了同样的问题,并通过为每列设置整理 utf8_general_ci 解决了这个问题。

答案 5 :(得分:2)

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

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

答案 6 :(得分: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错误。也许已经有关于这种情况的错误报告..

答案 7 :(得分:1)

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

答案 8 :(得分:1)

执行

show VARIABLES like "%char%”;

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

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

vim /etc/my.cnf

添加一行

character-set-server = utf8mb4

最后一次重启mysql

答案 9 :(得分:0)

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

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

答案 10 :(得分:-1)

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