【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

相关文章

Java对异常的认识与异常的处理小结

《Java对异常的认识与异常的处理小结》Java程序在运行时可能出现的错误或非正常情况称为异常,下面给大家介绍Java对异常的认识与异常的处理,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参... 目录一、认识异常与异常类型。二、异常的处理三、总结 一、认识异常与异常类型。(1)简单定义-什么是

SpringBoot项目配置logback-spring.xml屏蔽特定路径的日志

《SpringBoot项目配置logback-spring.xml屏蔽特定路径的日志》在SpringBoot项目中,使用logback-spring.xml配置屏蔽特定路径的日志有两种常用方式,文中的... 目录方案一:基础配置(直接关闭目标路径日志)方案二:结合 Spring Profile 按环境屏蔽关

Java使用HttpClient实现图片下载与本地保存功能

《Java使用HttpClient实现图片下载与本地保存功能》在当今数字化时代,网络资源的获取与处理已成为软件开发中的常见需求,其中,图片作为网络上最常见的资源之一,其下载与保存功能在许多应用场景中都... 目录引言一、Apache HttpClient简介二、技术栈与环境准备三、实现图片下载与保存功能1.

canal实现mysql数据同步的详细过程

《canal实现mysql数据同步的详细过程》:本文主要介绍canal实现mysql数据同步的详细过程,本文通过实例图文相结合给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的... 目录1、canal下载2、mysql同步用户创建和授权3、canal admin安装和启动4、canal

SpringBoot排查和解决JSON解析错误(400 Bad Request)的方法

《SpringBoot排查和解决JSON解析错误(400BadRequest)的方法》在开发SpringBootRESTfulAPI时,客户端与服务端的数据交互通常使用JSON格式,然而,JSON... 目录问题背景1. 问题描述2. 错误分析解决方案1. 手动重新输入jsON2. 使用工具清理JSON3.

java中long的一些常见用法

《java中long的一些常见用法》在Java中,long是一种基本数据类型,用于表示长整型数值,接下来通过本文给大家介绍java中long的一些常见用法,感兴趣的朋友一起看看吧... 在Java中,long是一种基本数据类型,用于表示长整型数值。它的取值范围比int更大,从-922337203685477

SQL中JOIN操作的条件使用总结与实践

《SQL中JOIN操作的条件使用总结与实践》在SQL查询中,JOIN操作是多表关联的核心工具,本文将从原理,场景和最佳实践三个方面总结JOIN条件的使用规则,希望可以帮助开发者精准控制查询逻辑... 目录一、ON与WHERE的本质区别二、场景化条件使用规则三、最佳实践建议1.优先使用ON条件2.WHERE用

MySQL存储过程之循环遍历查询的结果集详解

《MySQL存储过程之循环遍历查询的结果集详解》:本文主要介绍MySQL存储过程之循环遍历查询的结果集,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录前言1. 表结构2. 存储过程3. 关于存储过程的SQL补充总结前言近来碰到这样一个问题:在生产上导入的数据发现

java Long 与long之间的转换流程

《javaLong与long之间的转换流程》Long类提供了一些方法,用于在long和其他数据类型(如String)之间进行转换,本文将详细介绍如何在Java中实现Long和long之间的转换,感... 目录概述流程步骤1:将long转换为Long对象步骤2:将Longhttp://www.cppcns.c

SpringBoot集成LiteFlow实现轻量级工作流引擎的详细过程

《SpringBoot集成LiteFlow实现轻量级工作流引擎的详细过程》LiteFlow是一款专注于逻辑驱动流程编排的轻量级框架,它以组件化方式快速构建和执行业务流程,有效解耦复杂业务逻辑,下面给大... 目录一、基础概念1.1 组件(Component)1.2 规则(Rule)1.3 上下文(Conte