最近项目开发的时候发现插入emoji表情的时,会报如下错误:
Caused by; com. ibatis。common. j dbc。except ion .NestedSQLExcept ion:
The error occurred while applying a parameter map.
Check the MS -RESERVATION RECORD UPDATE- InlinePa raneterMap。
Check the statement ( update fai Led) .
Cause: java. sql. SQL Exception: Incorrect string value: '\xF0\x9F\x98\x93\xF0\x9F...' for column
查看DB实例的时候charactor_ser_server=utf8mb4,经测试数据库是支持emoji表情的,通过命令行的方式插入emoji表情都是正常的,但是通过应用服务器插入数据就是失败。
通过以上定位出现问题在应用服务器与DB的连接问题。
理所当然的最优解决方案
既然是DB连接问题,那么在连接中设置指定编码,就可以了,在connectionProperties中添加参数
newConnectionSQL=set names utf8mb4
不仅这个业务问题,整个服务器的emoji问题都解决了。
但是这个方式有个缺点,影响范围大,虽说utf8mb4编码是utf8的超级,但是一个应用服务器上跑着N多个服务,稍有问题就是全局大问题,而且无法降级,回滚风险高。
这种方式适合业务不多或者有充分的时间进行回归的场景。
其他解决方案
- 通过URL编码,在插入的时候进行encode,查询后进行decode操作,当然缺点也很明显,encode后数据长度边长,读取时必须要转换,不利于后期维护。而且历史数据还需要处理
- 序列化后存储,操作类似"通过URL编码",但是序列化后必须要通过编码的方式进行decode,维护成本也高,而且历史数据还需要处理
- 替换emoji表情,因为emoji表情基本固定在一个编码范围内,在保存数据的时候将emoji识别出来,并且通过URL编码进行替换,在emoji数据添加固定前缀和后缀,在读取的时候将emoji解码出来即可,当然前缀和后缀选择时最好是用户基本不可能会输入的分隔符。
最终方案
经过最终选择,还是选择了替换emoji表情的方案,其他方案的优劣还是很明显的,要么是成本高,要么是风险高。
在技术方案选择时可降级,可回滚需要摆在最高位置。
替换的方案是参照 https://www.cnblogs.com/shihaiming/p/5833244.html 文章上的方式
在git上还有一个emoji转换的库,https://github.com/vdurmont/emoji-java 在生产项目中很少会使用个人开发的库,而且这里自己动手成本也低,无需要引入其他库!