【BUG记录】Cause: java.sql.SQLException: Incorrect string value: '\xF0\x9F\x90\xA6' for column 'name' at row 1

本文涉及的产品
RDS MySQL DuckDB 分析主实例,基础系列 4核8GB
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
RDS AI 助手,专业版
简介: 在MySQL中遇到`Incorrect string value`错误通常是因为尝试插入的字符串包含不被数据库字符集支持的字符,如表情符号。错误根源是MySQL默认的utf8不支持4字节的UTF-8字符(如Emoji)。

大家好呀,我是summo,这次的文章标题是一个Mysql数据库的SQL错误,遇到的同学自然懂,没遇到的同学希望你永远也不要遇到。

一、错误说明

Cause: java.sql.SQLException: Incorrect string value: '\xF0\x9F\x90\xA6' for column 'name' at row 1这个错误通常是由于数据库列的字符集设置不支持某些特殊字符(例如表情符号),导致在插入或更新数据时失败。根源就是MySQL使用的是utf8编码,utf8编码默认每个字符3个字节,而Emoji表情使用的Unicode编码占4个字节,所以写入数据库的时候会写入失败并报错。

二、错误分析

1. 分析表的字符集

有设计表结构经验的同学应该都知道MySQL的存储引擎,如InnoDB和MyISAM,但表的字符集不知道大家清不清楚。简单来说表的字符集(Character Set)决定了表中可以存储的字符类型及其编码方式。最适合存储表情符号的字符集是utf8mb4,所以遇到这个错误时首先检查一下错误表的字符集。

(1)查看 MySQL 的系统变量,以确认 MySQL 实例的默认字符集

SHOW VARIABLES LIKE 'character_set%';

image.png

(2)查看表的创建语句,从中可以看到表和列的字符集设置信息

SHOW CREATE TABLE sample_table;

image.png

如果检查后数据库字符集和表字符集都是utf8mb4,但是添加表情符号还是失败的话,那么跟数据库就没有关系了。

2. 确认数据库连接配置是否支持utf8mb4

这一步也简单,就是确认spring.datasource.url中是否也包含 utf8mb4配置,如果没有的话,就加上useUnicode=true&characterEncoding=utf8mb4,如:

spring.datasource.url=jdbc:mysql://localhost:3306/your_database_name?useUnicode=true&characterEncoding=utf8mb4

网上搜索的文章大部分都是这两个解决思路,有些甚至会让你去看MySQL的配置,修改后重新启动MySQL,但最终可能却并不能解决这个问题。如果你确定字符集是对的,数据库连接配置也是对的,但报错还是存在,那么就在执行SQL之前执行一次set names utf8mb4语句。

3. set names utf8mb4怎么加?

(1)没有使用连接池

如果你没有使用连接池,那么在调用SQL之前,需要手动执行一次set names utf8mb4语句,如下:

conn = DriverManager.getConnection(url, user, password);
stmt = conn.createStatement();
stmt.execute("SET NAMES utf8mb4");

(2)Druid连接池

使用Druid连接池的话,那么可以直接加一行配置就行了,如下:

spring.datasource.druid.connection-init-sqls=set names utf8mb4

(3)Hikari连接池

同Druid连接池,加一行配置就行了,如下:

spring.datasource.hikari.connection-init-sql=SET NAMES utf8mb4

其他连接池我就不列举了,大同小异。

三、原理解释

set names utf8mb4 通过确保客户端、连接和服务器之间的数据传输在同一字符集下进行,从根本上避免了字符集不匹配的问题,所以执行该命令能够解决你插入表情符号时报错的问题。

当你执行 set names utf8mb4 语句时,它实际上做了以下几件事情:

  • 设置客户端字符集:
    使MySQL客户端的字符集为utf8mb4,这意味着客户端(也就是你的应用程序)发送给MySQL服务器的数据将被解释为utf8mb4格式。

  • 设置连接字符集:
    使数据库连接层(也叫连接字符集)的编码为utf8mb4。这保证了当数据在客户端和服务器之间传输时,被正确地编码和处理。

  • 设置结果字符集:
    使MySQL服务器返回给客户端的查询结果(比如SELECT语句的结果)都使用utf8mb4编码。

四、小结一下

最初,我的记录方式更偏向简单的笔记,后来发现笔记太乱,为了提高查阅效率,我开始给每个部分加上标题和段落,这样它们就演变成了短文。随着时间的推移,我逐渐增加了内容的层次,加入了前因、详细的分析过程以及小结,这些改进使我的记录更加完善,最终变成了结构化的文章。

不过,在文章标题的选择上,我有些犹豫。尽管起一个吸引人的标题能让文章更有吸引力,但如果将来遇到类似的问题时,因为标题花哨、不明确而导致找不到解决方案,那就得不偿失了。

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
目录
相关文章
|
JSON Java 关系型数据库
Java更新数据库报错:Data truncation: Cannot create a JSON value from a string with CHARACTER SET 'binary'.
在Java中,使用mybatis-plus更新实体类对象到mysql,其中一个字段对应数据库中json数据类型,更新时报错:Data truncation: Cannot create a JSON value from a string with CHARACTER SET 'binary'.
1480 4
Java更新数据库报错:Data truncation: Cannot create a JSON value from a string with CHARACTER SET 'binary'.
|
数据安全/隐私保护
作用域通信对象:session用户在登录时通过`void setAttribute(String name,Object value)`方法设置用户名和密码。点击登录按钮后,跳转到另外一个页面显示用户
该博客文章通过示例演示了如何使用session对象的`setAttribute`和`getAttribute`方法在不同页面间传递和显示用户的用户名和密码信息,并说明了如何设置会话的有效期。
作用域通信对象:session用户在登录时通过`void setAttribute(String name,Object value)`方法设置用户名和密码。点击登录按钮后,跳转到另外一个页面显示用户
|
存储 Java
构造String问题之在JDK 9及更高版本中,直接访问String对象的coder和value属性,如何实现
构造String问题之在JDK 9及更高版本中,直接访问String对象的coder和value属性,如何实现
207 0
### Cause: java.sql.SQLException: Field ‘id‘ doesn‘t have a default value; Field ‘id‘ doesn‘t have
### Cause: java.sql.SQLException: Field ‘id‘ doesn‘t have a default value; Field ‘id‘ doesn‘t have
|
SQL Java 数据库连接
Cause: java.sql.SQLException: Field ‘id‘ doesn‘t have a default value; Field ‘id‘ doesn‘t have a de
Cause: java.sql.SQLException: Field ‘id‘ doesn‘t have a default value; Field ‘id‘ doesn‘t have a de
|
安全 Java
Java StringBuffer 和 StringBuilder 类
Java StringBuffer 和 StringBuilder 类
117 0
|
API C# 开发者
WPF图形绘制大师指南:GDI+与Direct2D完美融合,带你玩转高性能图形处理秘籍!
【8月更文挑战第31天】GDI+与Direct2D的结合为WPF图形绘制提供了强大的工具集。通过合理地使用这两种技术,开发者可以创造出性能优异且视觉效果丰富的WPF应用程序。在实际应用中,开发者应根据项目需求和技术背景,权衡利弊,选择最合适的技术方案。
1114 1
|
安全 Java
【Java基础面试二十七】、说一说StringBuffer和StringBuilder有什么区别
这篇文章介绍了Java中StringBuffer和StringBuilder的区别:StringBuffer是线程安全的,而StringBuilder是非线程安全的,因此在单线程环境下优先推荐使用StringBuilder以获得更好的性能。
|
安全 Java API
Java系类 之 String、StringBuffer和StringBuilder类的区别
这篇文章讨论了Java中`String`、`StringBuffer`和`StringBuilder`三个类的区别,其中`String`是不可变的,而`StringBuffer`是线程安全的可变字符串类,`StringBuilder`是非线程安全的可变字符串类,通常在单线程环境下性能更优。
Java系类 之 String、StringBuffer和StringBuilder类的区别