从XML解析,插入到MySQL;字符导致java.sql.SQLException: Incorrect string value。

3

我正在解析一堆XML文件,并将从中获取的值插入到MySQL数据库中。 mysql表的字符集设置为utf8。我使用以下连接URL连接到数据库 - jdbc:mysql://localhost:3306/articles_data?useUnicode=false&characterEncoding=utf8

大多数带有Unicode字符的字符串值都可以正常输入(例如希腊字母等),但是对于某些具有数学符号的字符串则不行。特别是一个例子 - 当我尝试插入一个带有数学脚本大写字母g的字符串时(在www.ncbi.nlm.nih.gov/corehtml/pmc/pmcents/1D4A2.gif上的img)(http://graphemica.com/)(试图解析并插入文章),我会收到以下异常 -

java.sql.SQLException: Incorrect string value: '\xF0\x9D\x92\xA2 i...' for column 'text' at row 1
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1055)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:956)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3515)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3447)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1951)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2101)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2554)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1761)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2046)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1964)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1949)

如果我将连接URL更改为- jdbc:mysql://localhost:3306/articles_data,那么插入操作就可以工作,但所有常规的UTF8字符都会被替换为问号。
我正在尝试解决这个问题,有两种可能的方法,但都没有成功 -
1.在解析文章时,保持编码。我正在使用org.apache.xerces.parsers.DOMParser来解析xml文件,但无法弄清如何防止其解码(相关XML - <p>&#x1d4a2;是一个包含...</p>)。我可以重新编码它,但这似乎效率低下。
2.将数学符号插入数据库中。

请检查您的XML文件的编码格式。它也是UTF-8吗?您的应用程序运行在哪个操作系统上? - powerMicha
为什么在url中要使用useUnicode=false - Alex Gitelman
@Alex:我先尝试了 useUnicode=true,但并没有什么区别。我把它设为 false,希望它不会强制将其插入为 utf8 字符,并在不喜欢的地方回退到问号。 @powerMicha:我现在在 Windows 上测试它。XML 标头没有提供有关文件编码的任何信息,但是当我解析它时,它会将编码字符转换为(我认为是)UTF-8。我假设是这样,因为如果我将解析后的字符串输出到 NP++ 中,并使用 UTF-8 编码查看它,它就会正确显示。 - Shashank Agarwal
看起来 '\xF0\x9D\x92\xA2' 是 \U01d4a2 的正确 utf-8 编码,所以问题似乎出在 mysql 方面。你使用的 DB 和 jdbc 驱动程序版本是什么? - Jörn Horstmann
@Jörn:我正在使用服务器5.5.11。我正在使用“mysql-connector-java-5.1.7-bin.jar”进行连接。 - Shashank Agarwal
1个回答

6
MySQL在5.1版本之前似乎只支持基本多语言平面(BMP)中的Unicode字符,以utf-8编码时不超过3个字节。从版本5.1中有关Unicode支持的手册中可知:

MySQL 5.1支持两种用于存储Unicode数据的字符集:

  • ucs2,使用每个字符16位的Unicode字符集的UCS-2编码
  • utf8,使用每个字符1到3个字节的Unicode字符集的UTF-8编码
版本5.5中增加了一些新的字符集:

...

  • utf8mb4,使用每个字符1到4个字节的Unicode字符集的UTF-8编码

ucs2和utf8支持BMP字符。 utf8mb4、utf16和utf32支持BMP和补充字符。

因此,如果您使用的是mysql 5.1,则需要先升级。在较新的版本中,您必须将字符集更改为utf8mb4才能处理这些补充字符。
似乎jdbc连接器还需要进一步配置(来自Connector/J Notes and Tips):

要使用带有Connector/J的4字节UTF8,请配置MySQL服务器为character_set_server=utf8mb4。只要连接字符串中没有设置characterEncoding,Connector/J就会使用该设置。这相当于自动检测字符集。


1
@Shashank Agarwal,这个JDBC连接器的提示也可能与您相关:http://download.oracle.com/docs/cd/E17952_01/refman-5.1-en/connector-j-usagenotes-troubleshooting.html#qandaitem-21-3-5-3-1-15 - Jörn Horstmann
@ShashankAgarwal 你是如何解决 Unsupported character encoding 'utf8mb4' 这个问题的? - Luke
@Luke,这是一段时间以前的事情了,所以我不记得确切的工作方式,但在配置character_set_server=utf8mb4之后,不要在连接字符串中设置characterEncoding=utf8参数;例如,在我的情况下,连接字符串将变为jdbc:mysql://localhost:3306/articles_data - Shashank Agarwal
我赞同这个答案。必须在/etc/mysql/my.cnf中设置character_set_server属性。重启服务器,一切都正常工作。不需要在任何其他地方设置任何其他内容(在hibernate.cfg或任何创建数据库或表的SQL语句中没有任何字符属性的出现)。 - Torsten
1
@fattah.safa 我修复了链接(再次),该链接的解决方案已经在上面引用过了。 - Jörn Horstmann
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接