mysql emojo 其他方案_mysql支持emoji方案? 升级or业务实现

mysql的文本(varchar,

text),对emoji表情符号不是很好的支持,在5.5之前的版本,varchar和text都是不支持存储emoji表情符号的(即使是utf8)的编码模式。原因在于mysql的utf8是规定了每一个utf8字符按照3个字节来存储,而一个emoji(最初来自苹果系统,现在流行于各种移动操作系统)却需要4个字节来存储。这就导致了如果强制将emoji存储到varchar,text等字段上的时候,mysql会抛出异常,认为emoji是个“不正确”的文本。

ERROR 1366 (HY000): Incorrect string value:

‘\xF0\x9F\x91\xBD\xF0\x9F…’ for column ‘name’ at row 31

所幸,mysql在5.5之后的版本,针对四个字节的utf8字符推出了一种新的兼容的编码,叫

utf8mb4。utf8mb4比utf8支持的字符集更广,可以支持utf8以及四个字节的字符集,关于utf8mb4和utf8的区别可以这篇官方文档

简而言之就是:“utf8mb4

is a superset of

utf8” ,utf8mb4是utf8的超集,utf8是utf8mb4的子集。utf8mb4理论上是兼容utf8.

所以如果你的项目需要支持存储emoji表情,同时mysql的版本是5.5以上的版本,那么就可以把字段的charset改为

utf8mb4就可以完美支持emoji了。

那如果当前mysql版本不支持utf8mb4编码怎么办?

解决方法:

1. 升级mysql版本到5.5.3以上的 :)

2. 把需要支持emoji表情存储的字段改成 blob的。(这是针对mysql升级有限制的情况)

blob类型一般是用来存储二进制文件的,当时用来存储文本其实也是可以的,只不过存进去之前,把文本变成byte数据就可以了。已java为例,使用String.getBytes(charset)方法,可以把字符串转化成二进制,然后存储到数据库中。如果你有很多字段都要这么搞的话,估计都得疯了。怎么办?用orm框架~

已ibatis为例,如果你的对象字段是String文本,存储的字段确实blob,其实是没有关系的,不需要写特殊的代码,直接支持写入。但是读出来的时候就需要做转换,否则出来的是乱码。所以这里需要借助ibatis的typehandler和resultMap来解决这个问题。ORM框架的好处就是你不用一直重复劳动,可以在各种地方留着钩子(hook),随时让你在需要的时候可以插点东西到关键的地方上去。好了,废话不多说,看看这个typeHandler怎么实现:(这里是ibatis2.3.*的版本,如果是myBatis,可能报名和接口参数不太一样,但实现方式是一样的)

public class

BlobStringTypeHandler extends BaseTypeHandler { //charset private

static final String DEFAULT_CHARSET = "utf-8"; @Override public

void setParameter(PreparedStatement ps, int i, Object parameter,

String jdbcType) throws SQLException { ByteArrayInputStream bis;

String param = (String) parameter; try { //###把String转化成byte流 bis =

new ByteArrayInputStream(param.getBytes(DEFAULT_CHARSET)); } catch

(UnsupportedEncodingException e) { throw new RuntimeException("Blob

Encoding Error!"); } ps.setBinaryStream(i, bis, param.length()); }

@Override public Object getResult(ResultSet rs, String columnName)

throws SQLException { Blob blob = rs.getBlob(columnName); byte[]

returnValue = null; if (null != blob) { returnValue =

blob.getBytes(1, (int) blob.length()); } try { //###把byte转化成string

return new String(returnValue, DEFAULT_CHARSET); } catch

(UnsupportedEncodingException e) { throw new RuntimeException("Blob

Encoding Error!"); } } @Override public Object getResult(ResultSet

rs, int columnIndex) throws SQLException { Blob blob =

rs.getBlob(columnIndex); byte[] returnValue = null; if (null !=

blob) { returnValue = blob.getBytes(1, (int) blob.length()); } try

{ //###把byte转化成string return new String(returnValue,

DEFAULT_CHARSET); } catch (UnsupportedEncodingException e) { throw

new RuntimeException("Blob Encoding Error!"); } } @Override public

Object getResult(CallableStatement cs, int columnIndex) throws

SQLException { Blob blob = cs.getBlob(columnIndex); byte[]

returnValue = null; if (null != blob) { returnValue =

blob.getBytes(1, (int) blob.length()); } try { return new

String(returnValue, DEFAULT_CHARSET); } catch

(UnsupportedEncodingException e) { throw new RuntimeException("Blob

Encoding Error!"); } } @Override public Object valueOf(String s) {

try{ return s.getBytes(DEFAULT_CHARSET); }catch (Exception e){

return null; } } }

重点看几个getResult方法,就是从ResultSet中拿到blob字段数据(byte[]),然后把byte数组转化成string就OK了。

怎么使用?

在sqlMap文件定义resultmap, 对需要转换的字段指定这个typeHandler就可以了:

<resultMap

id=“EntityMap" class=“your.pack.Entity">

<result

property="name"

column="name"

jdbcType="BLOB"

javaType="java.lang.String"

typeHandler=“your.BlobStringTypeHandler">result>

resultMap>

注意select的statement语句返回使用resultMap指定这个resultMap

<select

id=“EntityDAO.getByXXX" parameterClass="java.util.Map"

resultMap="EntityMap">

select

name

from

your_table

where

...

limit

1

select>

OK,

mysql支持emoji了:)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值