mysql/Java服务端对emoji的支持

如果UTF8字符集且是Java服务器的话,当存储含有emoji表情时,会抛出类似如下异常:

java.sql.SQLException: Incorrect string value: ‘\xF0\x9F\x92\x94‘ for column ‘name‘ at row 1  
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1073)  
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3593)  
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3525)  
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1986)  
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2140)  
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2620)  
    at com.mysql.jdbc.StatementImpl.executeUpdate(StatementImpl.java:1662)  
    at com.mysql.jdbc.StatementImpl.executeUpdate(StatementImpl.java:1581)

这就是字符集不支持的异常。因为UTF-8编码有可能是两个、三个、四个字节,其中Emoji表情是4个字节,而Mysql的utf8编码最多3个字节,所以导致了数据插不进去。

升级前需要考虑的问题:

如果你的项目要进行移动产品的用户文本的存储,将你的DB字符集从UTF8/GBK等传统字符集升级到utf8mb4将是势在必行。你可以通过应用层面转换emoji等特殊字符,以达到原DB的兼容,我认为可行,但是你可能走了弯路。

utf8mb4作为utf8的super set,完全向下兼容,所以不用担心字符的兼容性问题。切换中需要顾虑的主要影响是mysql需要重新启动(虽然mysql官方文档说可以动态修改配置,但是经过数次测试,还是需要重启才可生效),对于业务可用率的影响是需要考虑的大问题,这里就暂时不展开讨论了。

升级步骤:

1.utf8mb4的最低mysql版本支持版本为5.5.3+,若不是,请升级到较新版本。

mysql版本查看命令请看:查看mysql版本的四种方法;mysql安装步骤请看:Linux中升级Mysql到Mysql最新版本的方法
2.修改database、table和column字符集。参考以下语句:
ALTER DATABASE database_name CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE table_name CHANGE column_name VARCHAR(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
3.修改mysql配置文件my.cnf(windows为my.ini)

my.cnf一般在etc/mysql/my.cnf位置。找到后请在以下三部分里添加如下内容:

[client]
default-character-set = utf8mb4

[mysql]
default-character-set = utf8mb4

[mysqld]
character-set-client-handshake = FALSE
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
init_connect=‘SET NAMES utf8mb4‘

4.重启 MySQL Server、检查字符集

1.)重启命令参考:/etc/init.d/mysql restart

2.)输入命令:mysql,进入mysql命令行(如果提示没权限,可以尝试输入mysql -uroot -p你的密码)

3.)在mysql命令行中输入:SHOW VARIABLES WHERE Variable_name LIKE ‘character_set_%‘ OR Variable_name LIKE ‘collation%‘;

检查是否如下:

+--------------------------+--------------------+
| Variable_name            | Value              |
+--------------------------+--------------------+
| character_set_client    | utf8mb4            |
| character_set_connection | utf8mb4            |
| character_set_database  | utf8mb4            |
| character_set_filesystem | binary            |
| character_set_results    | utf8mb4            |
| character_set_server    | utf8mb4            |
| character_set_system    | utf8              |
| collation_connection    | utf8mb4_unicode_ci |
| collation_database      | utf8mb4_unicode_ci |
| collation_server        | utf8mb4_unicode_ci |
+--------------------------+--------------------+
rows in set (0.00 sec)

特别说明下:collation_connection/collation_database/collation_server如果是utf8mb4_general_ci,没有关系。但必须保证character_set_client/character_set_connection/character_set_database/character_set_results/character_set_server为utf8mb4。关于这些字符集配置是干什么用的,有什么区别,请参考:深入Mysql字符集设置

5.如果你用的是java服务器,升级或确保你的mysql connector版本高于5.1.13,否则仍然无法使用utf8mb4
这是mysql官方release note,大家可以查看说明,并下载最新的mysql connector for java的jar包。
这里为大家提供一个:mysql-connector-java-5.1.31-bin.jar
同时记得修改pom配置哦~

6.检查你服务端的db配置文件:

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/database?useUnicode=true&characterEncoding=utf8&autoReconnect=true&rewriteBatchedStatements=TRUE
jdbc.username=root
jdbc.password=password

特别说明其中的jdbc.url配置:如果你已经升级好了mysql-connector,其中的characterEncoding=utf8可以被自动被识别为utf8mb4(当然也兼容原来的utf8),而autoReconnect配置我强烈建议配上,我之前就是忽略了这个属性,导致因为缓存缘故,没有读取到DB最新配置,导致一直无法使用utf8mb4字符集,多么痛的领悟!!

感谢这位仁兄的分享,顺利的帮助我解决了问题,但是我直接拿maven下载的驱动5.1.31还是不好用,后来修改成5.1.13后就没有问题了。

转自:http://segmentfault.com/blog/ilikewhite/1190000000616820

时间: 2024-12-16 05:21:26

mysql/Java服务端对emoji的支持的相关文章

现代Java服务端开发核心技术之开发工具箱

现代Java服务端开发核心技术之开发工具箱 现代Java服务端开发核心技术 2.1 开发工具概述 俗话说,工欲善其事必先利其器,掌握一些日常开中常用的工具软件能够大大提开发效率,工具本身的目的也是解放生产力.在安装各种软件时注意如果没有特殊需要不必使用最新版本,尤其是操作系统,例如当前(2018/10/12)最新版的macOS是10.14,但是运行在macOS之上的其他应用软件可能还没有及时做兼容新系统的版本,可能在系统升级之后无法正常使用,因此推荐在新系统正式推出半年后再升级最为稳妥. 而且软

现代Java服务端开发核心技术之分布式数据库中间件MyCAT入门

现代Java服务端开发核心技术之分布式数据库中间件MyCAT入门 现代Java服务端开发核心技术 MyCAT系统环境搭建 如下列表展示了搭建MyCAT运行时环境所需要的软件及其版本说明. 软件名称 软件版本 os centos7.5 JDK JDK1.8u191 MySQL MySQL5.7 Mycat Mycat1.6.5 Navicat Navicat12.08 在非集群的环境下,MyCAT仅仅依赖JDK就可以良好的运行在Windows,Linux,macOS等操作系统之上. CentOS7

现代Java服务端开发核心技术之数据库中间件MyCAT入门

现代Java服务端开发核心技术之数据库中间件MyCAT入门 现代Java服务端开发核心技术 MyCAT系统环境搭建 如下列表展示了搭建MyCAT运行时环境所需要的软件及其版本说明. 软件名称 软件版本 os centos7.5 JDK JDK1.8u191 MySQL MySQL5.7 Mycat Mycat1.6.5 Navicat Navicat12.08 SecureCRT Linux客户端 在非集群的环境下,MyCAT仅仅依赖JDK就可以良好的运行在Windows,Linux,macOS

Flex通信-Java服务端通信实例

Flex与Java通信的方式有很多种,比较常用的有以下方式: WebService:一种跨语言的在线服务,只要用特定语言写好并部署到服务器,其它语言就可以调用 HttpService:通过http请求的形式访问服务器 RmoteObject:通过AMF协议,以二进制的形式交互数据 Socket:套接字协议,服务器和客户端以IO的形式交互数据 上面几种各有个的优势:WebService常用于跨语言调用,不过解析协议需要花不少时间,运行速度不快:HttpService类似于Ajax:通常RmoteO

现代Java服务端开发核心技术栈

现代Java服务端开发核心技术栈 现代Java服务端开发核心技术 Java语言基础篇 互联网生态下的Java Java开发工具箱 Java基础项目搭建 Java数据存储 Java数据运算 Java程序流程控制 Java数组 Java面向对象程序设计 Java异常处理 Java枚举 Java注解 Java 泛型 Java集合 Java IO Java NIO Java操作数据库 Java日志 Java操作XML Java正则表达式 Java8新特性实战 Java9新特性实战 Java10新特性实战

现代Java服务端开发核心技术之CentOS7.5安装MySQL5.7

现代Java服务端开发核心技术之CentOS7.5安装MySQL5.7 现代Java服务端开发核心技术 1.首先检查系统中是否已经安装过MySQL,以下提供两种方式 [[email protected] Downloads]# yum list installed |grep mysql [[email protected] Downloads]# rpm -qa|grep mysql 如果已经安装过,可以使用如下命令删除 [[email protected] Downloads]# yum -

初识websocket及java服务端的简单实现

概念:WebSocket是一种在单个TCP连接上进行全双工通信的协议. WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据.在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输 背景:很多网站为了实现推送技术,所用的技术都是轮询.轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP请求,然后由服务器返回最新的数据给客户端的浏览器.这种传统的模式带来很明显的缺点,即浏览器需

RPC学习--C#使用Thrift简介,C#客户端和Java服务端相互交互

本文主要介绍两部分内容: C#中使用Thrift简介 用Java创建一个服务端,用C#创建一个客户端通过thrift与其交互. 其中使用到RPC学习----Thrift快速入门和Java简单示例,这篇文章创建的Java服务端. 一.C#中使用Thrift简介 关于rpc的简介,可以参考:RPC学习----Thrift快速入门和Java简单示例 1.下载thrift 1)点击下载:thrift-0.9.1.tar.gz(或者http://thrift.apache.org/download) 2)

android客户端和java服务端用aes加密

最近在公司做一个项目,老大让我们实现加解密的方法,我把工作直接推给了java服务端,他们也是直接在网上copy的代码,说我直接放到我的android代码中就可以了,不需要太多的更改.我就照做了,但是在真正的测试的时候,发现两边输入的密码一致,但是加密结果不一致.这可折磨我们了好久,最终解决了这个问题,加以记录. android和java加密结果不一样的原因,是因为他们的默认随机数序列不一致,所以解决他的办法是,不要使用默认的创建方法. 以下是正确的代码.android和java端的代码是一致的.