我有以下字符串值:“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(我认为这是空字符的表示)
非常感谢所有帮助!
答案 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
的字符集和校对:
alter table <some_table> convert to character set utf8mb4 collate utf8mb4_unicode_ci
在我的#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&characterEncoding=UTF-8
在我的hibernate jdbc连接url中,我将字符串数据类型更改为数据库中的longtext,之前是varchar。
答案 4 :(得分:3)
我遇到了同样的问题,并通过为每列设置整理 utf8_general_ci 解决了这个问题。
答案 5 :(得分:2)
将行useUnicode=true&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安装。