【MySQL】java.sql.SQLException: Incorrect string value: '\xF0\x9F\x92\x9' for column 插入国外文字失败解决方案

本文主要是介绍【MySQL】java.sql.SQLException: Incorrect string value: '\xF0\x9F\x92\x9' for column 插入国外文字失败解决方案,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

【引言】

线上问题,Excel导入某字段是印度文,导入报错,插入Mysql失败,具体错误如下:

Caused by: java.sql.SQLException: Incorrect string value: '\xF0\x9F\x92\x95 V...' for column '***' at row 1
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:965)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3973)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3909)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2527)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2680)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2484)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1858)
at com.mysql.jdbc.PreparedStatement.executeUpdateInternal(PreparedStatement.java:2079)
at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:1756)
... 60 more

【问题缘由】

由于mysql默认编码为utf-8,最大只占3个字节,一些非常见字符,比如该例子中“\xF0\x9F\x92\x95 V…”占4个字节,这样往数据表里插入4个字节的数据就会出错。

【解决方案】

找到问题原因,就想到之前解决过微信中存储emoji表情的问题,微信小程序中使用emoji表情,所以,很快找到了解决办法。

要么从代码中编码存入,解码取出;要么修改数据库字符集,且mysql版本必须5.5以上。

由于是旧系统,涉及到此字段的地方也很多,从代码中改,是行不通的,遗漏一个地方就会出问题,而目前使用的mysql版本是5.7,所以,决定采取第二种方案。

【解决过程】

  • 第一次尝试:修改数据库字段的字符集

先尝试了一把仅修改那一个字段的字符集为utf8mb4,结果导入失败。

  • 第二次尝试:修改整张表的字符集

尝试把整个表的字符集都改为utf8mb4,结果还是导入失败。

以为知道了解决办法,可以很快完成任务,结果并不是这样,两次失败,又回到起点。

查了些文章,了解到数据库的字符集分为server、client、connection、database、system和result六个级别
1、client是客户端使用的字符集,相当于网页中的字符集设置如下

<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

2、connection是连接数据库的字符集设置类型,如果没有指明连接数据库使用的字符集类型就按照服务器端默认的字符集设置。

3、database是数据库服务器中某个库使用的字符集设定,如果建库时没有指明,将使用服务器安装时指定的字符集设置。

4、results是数据库给客户端返回时使用的字符集设定,如果没有指明,使用服务器默认的字符集。

5、server是服务器安装时指定的默认字符集设定。

6、system是数据库系统使用的字符集设定。

system一般默认是utf-8字符集,server是最高的字符集设定,database没有单独设定就按照server的字符集设定,其他都是按照server的设定设置字符集。还有,数据库内的每个表和字段也都有字符集的概念,一般都是根据上一级结构决定自身的字符集,比如表就根据database库的设定决定自己的字符集,字段根据表来决定自己的字符集。

所以,我查了下数据库目前的字符集,sql如下:

show global variables like '%character%'; 
show global variables like '%collation%';

结果如下:

Variable_nameValue
character_set_clientutf8mb4
character_set_connectionutf8mb4
character_set_databaseutf8mb4
character_set_filesystemutf8mb4
character_set_resultsutf8mb4
character_set_serverutf8
character_set_systemutf8
collation_connectionutf8mb4_general_ci
collation_databaseutf8mb4_general_ci
collation_serverutf8_general_ci

除了server和system级的编码是utf8,其他编码已经是utf8mb4.因为知道server级是最高级别,就猜想是不是需要把server设置成utf8mb4的字符集格式,开始第三次尝试。

  • 第三次尝试:修改server的字符集

尝试把mysql server的字符集改为utf8mb4,结果还是导入失败。

回到起点,又继续查,查到有篇文章写到与数据库连接驱动也有关系,换到这个思路,又开始了新的尝试,所以开始去官网相关文档上查。

在mysql官方文档关于连接驱动Using Character Sets and Unicode章节内容中写道:

All strings sent from the JDBC driver to the server are converted automatically from native Java Unicode form to the client character encoding, including all queries sent using Statement.execute(), Statement.executeUpdate(), Statement.executeQuery() as well as all PreparedStatement and CallableStatement parameters with the exclusion of parameters set using setBytes(), setBinaryStream(), setAsciiStream(), setUnicodeStream(), and setBlob().

大致含义是指所有从JDBC发起的字符串链接驱动发送至server端后,会自动地转化为java客户端编码字符集格式,包括所有的查询,执行execute(),executeUpdate()及executeQuery()等方法。

另外,在Setting the Character Encoding相关内容中写道:
The character encoding between client and server is automatically detected upon connection (provided that the Connector/J connection properties characterEncoding and connectionCollation are not set). You specify the encoding on the server using the system variable character_set_server (for more information, see Server Character Set and Collation). The driver automatically uses the encoding specified by the server.

大致含义是指对于数据库连接驱动来说,client和server端的字符集是可以自动转化的(假如连接时没有设置字符集格式)。我们可以通过设置character_set_server这一变量来设置server的编码格式,从而就会使用server级的编码格式。

最后,在备注中写道:
For Connector/J 5.1.46 and earlier:
In order to use the utf8mb4 character set for the connection, the server MUST be configured with character_set_server=utf8mb4; if that is not the case, when UTF-8 is used for characterEncoding in the connection string, it will map to the MySQL character set name utf8, which is an alias for utf8mb3.

For Connector/J 5.1.47 and later:
When UTF-8 is used for characterEncoding in the connection string, it maps to the MySQL character set name utf8mb4.

也就是说在连接驱动5.1.46版本以前,想要使用utf8mb4的字符集格式连接,则server端必须配置为utf8mb4;如果没有设置,当使用utf8设置连接时,则连接的字符集格式还是utf8格式,也就是只能存放3个字节的字符集格式。

在5.1.47版本以后,当使用utf8连接时,则会自动匹配到utf8mb4字符集格式。

看了下项目中的数据库连接驱动jar包,版本是5.1.45-bin。所以,the server MUST be configured with character_set_server=utf8mb4,server必须设置utf8mb4,否则还是会匹配到utf8字符集类型。
但其实在第三次尝试办法中,已经设置了server级别的字符集为utf8mb4,但是还是失败。

  • 最后的尝试:升级mysql-connector-java jar版本

将原来的5.1.45-bin版本,替换为5.1.47版本,并且将该字段的编码格式改为utf8mb4。最终结果,导入成功。

【总结】

遇到问题,有了解决办法,有时候能顺利解决问题,有时候又并不能解决问题,可能是具体环境不一样,还需要具体分析。

刚开始可能并不知道问题缘由,一顿瞎试,这过程中可能又会有了其他思路,最终才得以解决问题。

这篇关于【MySQL】java.sql.SQLException: Incorrect string value: '\xF0\x9F\x92\x9' for column 插入国外文字失败解决方案的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1106326

相关文章

Spring Security+JWT如何实现前后端分离权限控制

《SpringSecurity+JWT如何实现前后端分离权限控制》本篇将手把手教你用SpringSecurity+JWT搭建一套完整的登录认证与权限控制体系,具有很好的参考价值,希望对大家... 目录Spring Security+JWT实现前后端分离权限控制实战一、为什么要用 JWT?二、JWT 基本结构

java解析jwt中的payload的用法

《java解析jwt中的payload的用法》:本文主要介绍java解析jwt中的payload的用法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Java解析jwt中的payload1. 使用 jjwt 库步骤 1:添加依赖步骤 2:解析 JWT2. 使用 N

springboot项目如何开启https服务

《springboot项目如何开启https服务》:本文主要介绍springboot项目如何开启https服务方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录springboot项目开启https服务1. 生成SSL证书密钥库使用keytool生成自签名证书将

Java实现优雅日期处理的方案详解

《Java实现优雅日期处理的方案详解》在我们的日常工作中,需要经常处理各种格式,各种类似的的日期或者时间,下面我们就来看看如何使用java处理这样的日期问题吧,感兴趣的小伙伴可以跟随小编一起学习一下... 目录前言一、日期的坑1.1 日期格式化陷阱1.2 时区转换二、优雅方案的进阶之路2.1 线程安全重构2

Java中的JSONObject详解

《Java中的JSONObject详解》:本文主要介绍Java中的JSONObject详解,需要的朋友可以参考下... Java中的jsONObject详解一、引言在Java开发中,处理JSON数据是一种常见的需求。JSONObject是处理JSON对象的一个非常有用的类,它提供了一系列的API来操作J

SpringBoot多数据源配置完整指南

《SpringBoot多数据源配置完整指南》在复杂的企业应用中,经常需要连接多个数据库,SpringBoot提供了灵活的多数据源配置方式,以下是详细的实现方案,需要的朋友可以参考下... 目录一、基础多数据源配置1. 添加依赖2. 配置多个数据源3. 配置数据源Bean二、JPA多数据源配置1. 配置主数据

将Java程序打包成EXE文件的实现方式

《将Java程序打包成EXE文件的实现方式》:本文主要介绍将Java程序打包成EXE文件的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录如何将Java程序编程打包成EXE文件1.准备Java程序2.生成JAR包3.选择并安装打包工具4.配置Launch4

SpringBoot内嵌Tomcat临时目录问题及解决

《SpringBoot内嵌Tomcat临时目录问题及解决》:本文主要介绍SpringBoot内嵌Tomcat临时目录问题及解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录SprinjavascriptgBoot内嵌Tomcat临时目录问题1.背景2.方案3.代码中配置t

SpringBoot使用GZIP压缩反回数据问题

《SpringBoot使用GZIP压缩反回数据问题》:本文主要介绍SpringBoot使用GZIP压缩反回数据问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录SpringBoot使用GZIP压缩反回数据1、初识gzip2、gzip是什么,可以干什么?3、Spr

Windows Docker端口占用错误及解决方案总结

《WindowsDocker端口占用错误及解决方案总结》在Windows环境下使用Docker容器时,端口占用错误是开发和运维中常见且棘手的问题,本文将深入剖析该问题的成因,介绍如何通过查看端口分配... 目录引言Windows docker 端口占用错误及解决方案汇总端口冲突形成原因解析诊断当前端口情况解