我有以下字符串值:"沃尔玛奥巴马">
我正在使用MySQL和Java。
我收到以下异常:"java.sql.SQLException:不正确的字符串值:"\xF0\x9F\x91\xBD\xF0\x9F...'
这是我尝试插入的变量:
var1 varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL`
我试图插入"沃尔玛奥巴马"的Java代码是一个准备好的语句。所以我正在使用setString()
方法。
看起来问题是值的编码.我该如何解决这个问题?以前我使用的是 Derby SQL,值最终只是两个平方(我认为这是空字符的表示)
非常感谢所有帮助!
你所拥有的是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'
建立连接后立即。
另请参阅连接器/J:
14.14: 如何将 4 字节 UTF8、utf8mb4 与连接器/J 一起使用?
要将 4 字节 UTF8 与连接器/J 一起使用,请使用 character_set_server=utf8mb4。然后,连接器/J 将使用该设置只要尚未在连接中设置字符编码 字符串。这等效于自动检测字符集。
同时调整列和数据库:
var1 varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL
同样,您的MySQL版本需要相对最新才能支持utf8mb4。
奇怪的是,我发现从JDBC url
中删除&characterEncoding=UTF-8
对我有类似问题的帮助。
根据我的属性,
jdbc_url=jdbc:mysql://localhost:3306/dbName?useUnicode=true
我认为这支持了@Esailija上面所说的,即我的 MySQL,实际上是 5.5,正在找出自己最喜欢的 UTF-8 编码风格。
(注意,我还在 java 代码中指定了我正在读取InputStream
UTF-8
,这可能没有坏处)......
总而言之,要保存需要 4 个字节的符号,您需要更新 characher-set 和排序规则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
顺便说一句,请注意连接器/J 的行为与SET NAMES 'utf8mb4'
:
不要使用 Connector/J 发出查询集名称,因为驱动程序不会检测到字符集已更改,并将继续使用在初始连接设置期间检测到的字符集。
并避免在连接 url 中设置characterEncoding
参数,因为它将覆盖配置的服务器编码:
若要覆盖客户端上自动检测到的编码,请在用于连接到服务器的 URL 中使用 characterEncoding 属性。
我如何解决我的问题。
我有
?useUnicode=true&characterEncoding=UTF-8
在我的休眠 jdbc 连接 url 中,我将数据库中的字符串数据类型更改为长文本,之前是 varchar。
将行useUnicode=true&characterEncoding=UTF-8
附加到您的 jdbc 网址。
在您的情况下,数据不是使用UTF-8
编码发送的。
我遇到了同样的问题,并通过将每列的排序规则设置为utf8_general_ci来解决它。
我猜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错误。也许已经有关于这种情况的错误报告了。
我遇到了同样的问题,在仔细检查所有字符集并发现它们都没问题之后,我意识到我在类中的错误属性被注释为@Column而不是@JoinColumn(javax.presistence;休眠),它破坏了一切。
执行
show VARIABLES like "%char%”;
如果不是 utf8MB4,请查找字符集服务器。
将其设置在您的 my.cnf 中,例如
vim /etc/my.cnf
添加一行
character_set_server = utf8mb4
终于重启MySQL
这个设置使用OldUTF8Behavior=true对我来说很好用。它没有给出不正确的字符串错误,但它将特殊字符(如 Ã)转换为多个字符并保存在数据库中。
为了避免这种情况,我从 JDBC 参数中删除了此属性,而是将列的数据类型转换为 BLOB。这很完美。
此外,数据类型可以使用 varchar 或文本的 blob 安装。