问题背景:

项目中,MySql会保存来自微信的用户名,大家都知道微信用户名允许包含表情(如火星文,moji表情等),
通常的我们的数据库字符集会被设置为UTF8,那么此时就会出现入库的问题

MySql常用字符集设置:

  

微信小程序java获取微信昵称 java微信名_mysql

含有moji表情的昵称入库问题:

org.springframework.jdbc.UncategorizedSQLException: 
PreparedStatementCallback; uncategorized SQLException for SQL

SQL state [HY000]; error code [1366]; Incorrect string value: 
'\xF0\x9F\x8D\x89Ch...' for column 'nick_name' at row 1; 
nested exception is java.sql.SQLException: Incorrect string value: 
'\xF0\x9F\x8D\x89Ch...' for column 'nick_name' at row 1

问题分析:

从MySql抛出的异常来看,是由于数据库中存在一个叫做"nick_name"的String类型字段,
保存值为'\xF0\x9F\x8D\x89Ch...'时抛出异常UncategorizedSQLException

我们先不去了解这个什么异常,很明显,如果我们保存一个正常的String是没有问题的,
那为什么这个表情会被识别为'\xF0\x9F\x8D\x89Ch...' ,这到底是个什么鬼

下面我们基于硬件层和字库码表来分析一下:

1)先来说一下,为什么正常的String没有问题

不要以为计算机这么"聪明",其实他们只认识0和1,为什么他们认识"123",因为有字库和码表

2)那我们又得论一论字库码表是怎么来的了,当然这里还牵扯到字号和字体的问题我们不做过多讨论

这是之前写的一篇基于硬件层面介绍字库码表的博文: 字库码表原理

当然日后还会贴在这里一篇图片显示的原理,关于16进制RGB565的色值绘图 MARK:TODO

3)moji表情是字符,不是图片

是的,moji表情是字符,不是图片,属于unicode,是一种规范
无论是数据库或是前端显示都可以通过升级实现正常显示

MARK:TODO 
    - 这里以后还会贴一篇前端显示moji表情的解决方法

4)通俗的说,问题发生在数据库字符集设置上

数据库根本不认识'\xF0\x9F\x8D\x89Ch...',在字符集中没有匹配到,导致'\xF0\x9F\x8D\x89Ch...'直接入库,发生异常

应该显示成什么,所以我们要配置一个合适的字符集,使数据库识别(支持)这个字符

问题解决

1)首先修改数据字符集

  

微信小程序java获取微信昵称 java微信名_数据库_02

2)修改涉及此问题的表字段字符集

  

微信小程序java获取微信昵称 java微信名_数据库_03

3)修改数据库连接池配置

我们项目用的是阿里巴巴的DruidDataSource数据库连接池,贴一下修改位置

<bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource"
        ..... Add property.....
        <property name="connectionInitSqls" value="set names utf8mb4;" />
    </bean>

如果是apache的BasicDataSource

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
    ....        
    <!-- 此配置用于在创建Connection对象时执行指定的初始化sql -->
    <property name="connectionInitSqls" value="set names utf8mb4;" />
</bean>

4)jdbc连接串设置:

jdbc:mysql://localhost:3306/dbname?useUnicode=true&characterEncoding=utf8
建议删除useUnicode=true&characterEncoding=utf8,

5)其他问题:

1.MySQL版本要求:不低于5.5.3(不支持utf8mb4编码)
2.JDBC驱动版本要求:mysql connector版本高于5.1.13

修改记录:
20161223:修改代码段的显示样式