mysql中Incorrect string value乱码问题解决方案
mysql中Incorrect string value乱码问题解决方案
你是否遇到过类似以下错误?
java.sql.SQLException: Incorrect string value: '\xF0\x9F\x92\x9C' for column 'content' at row 1.
产生这种异常的原因在于,mysql中的utf8编码最多会用3个字节存储一个字符,如果一个字符的utf8
编码占用4个字节(最常见的就是ios中的emoji表情字符),那么在写入数据库时就会报错。
mysql从5.5.3版本开始,才支持4字节的utf8编码,编码名称为utf8mb4(mb4的意思是max bytes 4),这种编码方式最多用4个字节存储一个字符。
要想证明这个问题,可以执行以下sql:
select * from
information_schema.CHARACTER_SETS
where CHARACTER_SET_NAME like 'utf8%'
结果如图:

因此,要解决上述异常的发生,需要使用utf8mb4编码。
解决数据库编码后,还需要解决客户端Connection连接对象使用的编码问题。
调用创建的Connection对象执行以下sql:
conn.createStatement().execute("SET names 'utf8mb4'");
如果项目中使用了DataSource数据源,只需要对数据源进行相关配置即可,这里以apache的DBCP数据源为例讲解,在spring框架下配置如下:
<!-- 数据源 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://${${data-source.prefix}.data-source.host-name}:3306/${${data-source.prefix}.data-source.db-name}?characterEncoding=utf8&autoReconnect=true&failOverReadOnly=false&maxReconnects=10&allowMultiQueries=true" />
<property name="username" value="${${data-source.prefix}.data-source.username}" />
<property name="password" value="${${data-source.prefix}.data-source.password}" />
<property name="maxActive" value="150" />
<property name="maxIdle" value="2" />
<property name="testOnBorrow" value="true" />
<property name="testOnReturn" value="true" />
<property name="testWhileIdle" value="true" />
<property name="validationQuery" value="select 1" />
<!-- 此配置用于在创建Connection对象时执行指定的初始化sql -->
<property name="connectionInitSqls">
<list>
<value>set names 'utf8mb4'</value>
</list>
</property>
</bean>
以下解释引用自mysql参考手册:
SET NAMES 'charset_name'
SET NAMES显示客户端发送的SQL语句中使用什么字符集。
因此,SET NAMES 'utf8mb4'语句告诉服务器:“将来从这个客户端传来的信息采用字符集utf8mb4”。它还为服务器发送回客户端的结果指定了字符集。(例如,如果你使用一个SELECT语句,它表示列值使用了什么字符集。)
SET NAMES 'x'语句与这三个语句等价:
mysql> SET character_set_client = x;
mysql> SET character_set_results = x;
mysql> SET character_set_connection = x;
执行完此sql语句后,通过此连接对象后续创建的Statement都会成功地执行了。
讲到这里,问题已经得到完美解决,但是我又联想到一个新的问题:
jvm虚拟机运行时,内存中的字符串采用utf-16编码,对于ios中的emoji表情这种用4字节utf-8编码存储的字符,在java运行时又是怎样存储的呢?
于是,我找了一个emoji字符(4个字节的值分别为0xf0,0x9F,0x92,0x9c),做了以下试验。
byte[] bytes = new byte[] { (byte) 0xf0, (byte) 0x9F, (byte) 0x92, (byte) 0x9c };
String s = new String(bytes, Charset.forName("utf-8"));
System.out.println("length:"+s.length());
for (int i=0;i<s.length();i++) {
int ch = s.charAt(i);
System.out.println("0x"+Integer.toHexString(ch));
}
执行结果如下:

由结果可以看出,unicode值(也叫codePoint码点,后面介绍API会用到)大于0xffff的单个字符,jvm内部占用2个char的长度(也就是4个字节)存储。
所有大于0xffff的字符,全都在UTF编码表的辅助平面内(域辅助平台对应的是基础平面,简称BMP)。因此对于String中的某个char,是基础平面字符,还是辅助平面字符的一部分,也很好做出判断。下面介绍java.lang.Character中的一些API:
以下描述中,码点即是字符的unicode值
| Character中API | 描述 |
| isValidCodePoint(int codePoint):boolean | 判断输入码点是否是有效的,所有属于UTF定义平面的码点都是有效的 |
| isBmpCodePoint(int codePoint):boolean | 判断输入码点是否属于基础平面,即:0x0000~0xffff |
| isSupplementaryCodePoint(int codePoint):boolean | 判断输入码点是否属于辅助平面,即:码点>0xffff |
| isSurrogate(char ch):boolean | 判断输入的字符是否辅助平面字符的一部分 |
获取String中某个字符的码点也很容易,调用String.codePointAt(int index):int即可。
最后,关于unicode、UCS-2、UCS-4、UTF-8、UTF-16编码之间的关系,请读者自行百度。文章太多了,在此就不多做介绍了。
参考资料:
mysql utf8mb4与emoji表情:
http://my.oschina.net/wingyiu/blog/153357
关于 MySQL UTF8 编码下生僻字符插入失败/假死问题的分析
mysql中Incorrect string value乱码问题解决方案的更多相关文章
- mysql插入表数据中文乱码问题解决方案
一.问题 开发中遇到将其它数据库数据插入到mysql数据库表中一直会报类似如下错误: Incorrect string value: '\xE6\x88\x91' for column 'name' ...
- mysql异常Incorrect string value: '\xE6\xB5\x8B\xE8\xAF\x95' for column 'region_name'
Incorrect string value: '\xE6\xB5\x8B\xE8\xAF\x95' for column 'region_name' insert语句加的该字段有汉字,乱码造成的 解 ...
- Mysql之Incorrect string value: '\xF0\x9F\x98\x89 \xE6... 保存emoji表情
错误信息如下: Incorrect string value: '\xF0\x9F\x98\x89 \xE6...' 问题产生的原因是字符串不兼容4字节的unicode导致的,一般我们常见的表情编码等 ...
- MySQL的Incorrect string value错误
用以下SQL语句向表2中插入数据: insert into 表2 select * from 表1 结果出现Incorrect string value错误: 打开表2一看,里面全是问号: 后来才发现 ...
- MySQL (1366, "Incorrect string value: '\\xF0\\x9F\\x8E\\xAC\\xE5\\x89...' for column 'description' at row 1")
(1366, "Incorrect string value: '\\xF0\\x9F\\x8E\\xAC\\xE5\\x89...' for column 'description' at ...
- Mysql中经常出现的乱码问题
Mysql中执行SET NAMES utf8这条SQl的作用 1)首先,Mysql服务器的编码和数据库的编码在配置文件my.ini中设置: 用记事本打开配置文件,修改代码:default-charac ...
- 在rails 中使用mysql 出现Mysql::Error: Incorrect string value: 的问题
这是因为你在做数据库的操作中有非英文的问题,之后gem mysql2 处理中文必须要数据库也指定是utf-8 才比较好处理 解决的方法很简单,将数据库每张表都转化成utf-8即可,如果数据库没有什么重 ...
- java向mysql中写入中文出现乱码
乱码的原因有很多,我遇到的原因是url配置的问题,解决方案: 将: jdbc.url=jdbc:mysql://localhost:3306/XXXX?useUnicode=true&char ...
- SpringMVC中返回JSON时乱码的解决方案
springMVC中返回JSON会出现乱码,解决如下: produces = "text/html;charset=UTF-8" @ResponseBody @RequestMap ...
随机推荐
- ios界面笔记(一)
基于一个简单视图的view解析
- iOS 5 does not allow to store downloaded data in Documents directory? ios5.0及以后的版本对于下载的文件存储路径有了改变
I have made an application for my client by keeping target iOS as 4. But since the application still ...
- Android性能优化第(二)篇---Memory Monitor检测内存泄露
上篇说了一些性能优化的理论部分,主要是回顾一下,有了理论,小平同志又讲了,实践是检验真理的唯一标准,对于内存泄露的问题,现在通过Android Studio自带工具Memory Monitor 检测出 ...
- linuxshell编程之变量
变量分类: 用户自定义变量:局部变量 定义格式:变量名=变量值(*等号左右不能有空格,加了空格会报错) 调用格式:echo $变量名(调用的是变量名等效的值) 变量叠加:$x=123,y=" ...
- Andriod 自动化测试研究方向
前言 孔子曰:"工欲善其事,必先利其器",我来云:"工欲利其器,必先知其理".我们无论学习任何新事物,都要尽量做到"知其然知其所以然",对于 ...
- leetcode笔记:Ugly Number II
一. 题目描写叙述 Write a program to find the n-th ugly number. Ugly numbers are positive numbers whose prim ...
- XML基础知识学习
概念: XML 指可扩展标记语言 XML 是一种标记语言,非常类似 HTML ,文本文件. XML 的设计宗旨是数据传输,而非显示数据 .存储和传输复杂的关系模型数据 XML 标签没有被提前定义 使用 ...
- Android常用资源
Eclipse ADT http://developer.android.com/sdk/installing/installing-adt.html https://dl-ssl.google.co ...
- 转 FreeBSD通过PORTS安装软件的几个常用命令
1.怎样找到我想安装的包路径:# cd /usr/ports# make search name=mysql2.仅仅下载源码包,而不安装:# cd /usr/ports/directory# make ...
- spring-struts-mybatis整合错误集锦
尽管三大框架特别特别的好用,可是,当我第一次把这三个框架用maven整合到一起的时候.各种错误接踵而至,以下来做一下三大框架整合的总结: 首先是在导入三大框架的各种依赖包的时候,由于我用的是j2ee ...