java.sql.SQLException:错误的string值:'\ xF0 \ x9F \ x91 \ xBD \ xF0 \ x9F …'
我有以下string值:“沃尔玛奥巴马👽💔”
我正在使用MySQL和Java。
我得到以下exception:`java.sql.SQLException:不正确的string值:'\ xF0 \ x9F \ x91 \ xBD \ xF0 \ x9F …'
这是我想要插入的variables:
var1 varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL`
我试图插入“沃尔玛奥巴马👽💔”的Java代码是一个preparedStatement。 所以我使用setString()
方法。
看起来问题是值的编码。 我该如何解决这个问题? 以前我使用的是Derby SQL,值刚好是两个sqaure(我认为这是空字符的表示)
所有的帮助非常感谢!
你有什么是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
,拼接需要为utf8mb4
。 对于java来说,它仍然只是"utf-8"
,但是MySQL需要一个区别。
我不知道你正在使用什么驱动程序,但是驱动程序不可知的方式来设置连接字符集是发送查询:
SET NAMES 'utf8mb4'
进行连接后。
另请参阅连接器/ J :
23.3.15.15:如何在连接器/ J上使用4字节的UTF8,utf8mb4?
要使用带有Connector / J的4字节UTF8,请使用character_set_server = utf8mb4configurationMySQL服务器。 只要连接string中没有设置characterEncoding ,Connector / J就会使用该设置。 这相当于字符集的自动检测。
调整您的列和数据库以及:
var1 varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL
再一次,你的MySQL版本需要相对最新的utf8mb4支持。
总而言之,要保存需要4个字节的符号,您需要更新utf8mb4的characher-set和collation:
- 数据库表/列:
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
参数,因为它将覆盖configuration的服务器编码:
要覆盖客户端自动检测到的编码,请使用用于连接到服务器的URL中的characterEncoding属性。
奇怪的是,我发现从JDBC url中删除&characterEncoding = UTF-8对我来说也有类似的问题。
从我的属性,
jdbc_url=jdbc:mysql://localhost:3306/dbName?useUnicode=true
我认为这支持@Esailija上面所说的,也就是说,我的MySQL确实是5.5,正在计算出它自己最喜欢的UTF-8编码。
(注意,我还指定了我正在读取的InputStream,作为UTF-8在Java代码,可能不会伤害)…
我如何解决我的问题。
我有
?useUnicode=true&characterEncoding=UTF-8
在我的hibernate jdbc连接url中,我将string数据types更改为数据库中的longtext,这是varchar之前的版本。
将useUnicode=true&characterEncoding=UTF-8
行附加到您的jdbcurl。
在你的情况下,数据不是使用UTF-8
编码发送的。
我猜MySQL不相信这是有效的UTF8文本。 我尝试了与列定义相同的testing表插入(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应用程序testing:
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连接相同的插入,并且抛出了相同的exception。 我相信这是一个MySQL的错误。 也许有关于这种情况的错误报告已经..
我遇到了同样的问题,并通过将Collation设置为每列的utf8_general_ci来解决此问题。
我遇到了同样的问题,经过认真对待所有的字符集,发现他们都是正确的,我意识到,我在我的课被错误的属性被注释为@Column而不是@JoinColumn(javax.presistence;hibernate)和它把一切都打破了。