【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

相关文章

springboot集成easypoi导出word换行处理过程

《springboot集成easypoi导出word换行处理过程》SpringBoot集成Easypoi导出Word时,换行符n失效显示为空格,解决方法包括生成段落或替换模板中n为回车,同时需确... 目录项目场景问题描述解决方案第一种:生成段落的方式第二种:替换模板的情况,换行符替换成回车总结项目场景s

SpringBoot集成redisson实现延时队列教程

《SpringBoot集成redisson实现延时队列教程》文章介绍了使用Redisson实现延迟队列的完整步骤,包括依赖导入、Redis配置、工具类封装、业务枚举定义、执行器实现、Bean创建、消费... 目录1、先给项目导入Redisson依赖2、配置redis3、创建 RedissonConfig 配

SpringBoot中@Value注入静态变量方式

《SpringBoot中@Value注入静态变量方式》SpringBoot中静态变量无法直接用@Value注入,需通过setter方法,@Value(${})从属性文件获取值,@Value(#{})用... 目录项目场景解决方案注解说明1、@Value("${}")使用示例2、@Value("#{}"php

SpringBoot分段处理List集合多线程批量插入数据方式

《SpringBoot分段处理List集合多线程批量插入数据方式》文章介绍如何处理大数据量List批量插入数据库的优化方案:通过拆分List并分配独立线程处理,结合Spring线程池与异步方法提升效率... 目录项目场景解决方案1.实体类2.Mapper3.spring容器注入线程池bejsan对象4.创建

线上Java OOM问题定位与解决方案超详细解析

《线上JavaOOM问题定位与解决方案超详细解析》OOM是JVM抛出的错误,表示内存分配失败,:本文主要介绍线上JavaOOM问题定位与解决方案的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录一、OOM问题核心认知1.1 OOM定义与技术定位1.2 OOM常见类型及技术特征二、OOM问题定位工具

基于 Cursor 开发 Spring Boot 项目详细攻略

《基于Cursor开发SpringBoot项目详细攻略》Cursor是集成GPT4、Claude3.5等LLM的VSCode类AI编程工具,支持SpringBoot项目开发全流程,涵盖环境配... 目录cursor是什么?基于 Cursor 开发 Spring Boot 项目完整指南1. 环境准备2. 创建

Python一次性将指定版本所有包上传PyPI镜像解决方案

《Python一次性将指定版本所有包上传PyPI镜像解决方案》本文主要介绍了一个安全、完整、可离线部署的解决方案,用于一次性准备指定Python版本的所有包,然后导出到内网环境,感兴趣的小伙伴可以跟随... 目录为什么需要这个方案完整解决方案1. 项目目录结构2. 创建智能下载脚本3. 创建包清单生成脚本4

Spring Security简介、使用与最佳实践

《SpringSecurity简介、使用与最佳实践》SpringSecurity是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架,本文给大家介绍SpringSec... 目录一、如何理解 Spring Security?—— 核心思想二、如何在 Java 项目中使用?——

SpringBoot+RustFS 实现文件切片极速上传的实例代码

《SpringBoot+RustFS实现文件切片极速上传的实例代码》本文介绍利用SpringBoot和RustFS构建高性能文件切片上传系统,实现大文件秒传、断点续传和分片上传等功能,具有一定的参考... 目录一、为什么选择 RustFS + SpringBoot?二、环境准备与部署2.1 安装 RustF

springboot中使用okhttp3的小结

《springboot中使用okhttp3的小结》OkHttp3是一个JavaHTTP客户端,可以处理各种请求类型,比如GET、POST、PUT等,并且支持高效的HTTP连接池、请求和响应缓存、以及异... 在 Spring Boot 项目中使用 OkHttp3 进行 HTTP 请求是一个高效且流行的方式。