起因

mybatis-plus 通过Mapper 查询数据,映射出来的BLOB字段中的yml数据中文是乱码的

---
DefaultValue: ''
Formula: ''
HintContent: ''
HintType: ''
OptionsColor:
处理: ''
外ä¿ä¸­: ''
åŒæˆ: ''
接单: ''
新建: ''
评价: ''
转信息科: ''
转总务科: ''
转è¾å¤‡ç§‘: ''
OptionsIcon:
处理: ''
外ä¿ä¸­: ''
åŒæˆ: ''
接单: ''
新建: ''
评价: ''
转信息科: ''
转总务科: ''
转è¾å¤‡ç§‘: ''
PossibleComments:
处理: ''
外ä¿ä¸­: ''
åŒæˆ: ''
接单: ''
新建: ''
评价: ''
转信息科: ''
转总务科: ''
转è¾å¤‡ç§‘: ''
PossibleValues:
处理: 处理
外ä¿ä¸­: 外ä¿ä¸­
åŒæˆ: åŒæˆ
接单: 接单
新建: 新建
评价: 评价
转信息科: 转信息科
转总务科: 转总务科
转è¾å¤‡ç§‘: 转è¾å¤‡ç§‘
Regex: ''
RegexHint: ''
TreeView: '0'
Unique: '0'

我们看一下正常的数据是长下面这样的

---
DefaultValue: ''
Formula: ''
HintContent: ''
HintType: ''
OptionsColor:
处理: ''
外修中: ''
完成: ''
接单: ''
新建: ''
评价: ''
转信息科: ''
转总务科: ''
转设备科: ''
OptionsIcon:
处理: ''
外修中: ''
完成: ''
接单: ''
新建: ''
评价: ''
转信息科: ''
转总务科: ''
转设备科: ''
PossibleComments:
处理: ''
外修中: ''
完成: ''
接单: ''
新建: ''
评价: ''
转信息科: ''
转总务科: ''
转设备科: ''
PossibleValues:
处理: 处理
外修中: 外修中
完成: 完成
接单: 接单
新建: 新建
评价: 评价
转信息科: 转信息科
转总务科: 转总务科
转设备科: 转设备科
Regex: ''
RegexHint: ''
TreeView: '0'
Unique: '0'

在来看看这个字段在数据库中存储的样子:

排查过程

一开始想到的就是经典的乱码问题。所以尝试了如下方法

1、url 属性排查

检查数据库 url 链接上有没有添加 characterEncoding=UTF-8,这里查看是没有问题的,因为用的是nacos,担心是覆盖出了问题。我还特意在代码中打印出来了。

    @Value("${spring.datasource.druid.url}")
String dateURL; log.info("数据库连接配置 url 属性为: "+dateURL);

结果如下:


2、IDEA 编码排查

排查是否是 IDEA 问题,虽然概率小,但是也要排查一下,排查结果还是没有问题

排查路径:Setting--->Editor--->File Encodings

3、mybatis xml文件排查

这里主要是看 xml 有时候是手写或者网上复制过来的话,也可能会造成乱码。排查结果也是没有问题


4、排查数据库中的数据是否乱码

这个时候,我们在查询步骤中基本上都排查完了,现在怀疑是不是插入时,数据库本身存储就是乱码的

直接去数据库中查找改字段,并把数据放到 Notepad++ 或者其他编辑器里面,可以确定数据库中存的数据是正常的


5、排查查询其他中文字段是否会出现乱码

直接写SQL去查询其他中文字段,查出来的结果是正常的,这就证明了问题确实是出现在 BLOB 这个字段里面了

解决办法

到这里,基本上排查的方法都用上了,其实上面的排查过程还是比较消耗时间的,这里我就不做过多繁琐的描述了,还有一些其他的排查方式。比如换机器,换配置文件的等也都一一试过,但是环境这方面的排查,我就不讲述了,实在是无聊又耗时间。最后确定问题出现在BLOB类型之后,参考网上的文章做了如下的解决方案。

把查出来的数据,作为字节数组,保留最完整的原始性,在把 byte[] 强转为 UTF-8 的 String 类型。

此时就去String中尝试查找是否纯在此类。万幸的是找到了

    public String(byte bytes[], String charsetName)
throws UnsupportedEncodingException {
this(bytes, 0, bytes.length, charsetName);
}

最后是使用这个方法实现了转换

new String( dynamicFieldConfig字段值 , "utf-8" );

但是我们项目中,很多地方都用到了这个字段。


此时想到mybatis的结果集拦截器,我们可以在结果集拦截器中对这个字段进行拦截,并对他做语言转换处理。

最后实现的效果:

package com.dt.cloud.tools;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import java.io.ByteArrayInputStream;
import java.io.UnsupportedEncodingException;
import java.sql.*; /**
* @Description:
* @author: zch
* @Date: 2022/6/23 16:36
* @Version 1.0
*/
public class ConvertBlobTypeHandler extends BaseTypeHandler<String> { private static final String DEFAULT_CHARSET = "utf-8"; @Override
public void setNonNullParameter(PreparedStatement ps, int i,
String parameter, JdbcType jdbcType) throws SQLException {
ByteArrayInputStream bis;
try {
bis = new ByteArrayInputStream(parameter.getBytes(DEFAULT_CHARSET));
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("Blob Encoding Error!");
}
ps.setBinaryStream(i, bis, parameter.length());
} @Override
//rs 为返回结果集,columnName 就是我们需要处理的字段名,当我们根据字段名在返回结果集中找出的这个字段就是 longblob 类型的数据了
public String getNullableResult(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 {
// 核心代码,把结果集拦截下来,并且强制转换为utf-8格式
return new String(returnValue, DEFAULT_CHARSET);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("Blob Encoding Error!");
}
} @Override
public String getNullableResult(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 String getNullableResult(ResultSet arg0, int arg1)
throws SQLException { return null;
}
}

在我们的 mapper 文档中需要拦截的 resultMap 中的字段中增加一个 typeHandler 类型拦截器,这个 typeHandler 的值就是我们 ConvertBlobTypeHandler 类的地址

最后总结:数据库中的存储使用的就是 longblob 类型,这个类型在查询出来的时候如果不进行处理的话就会出现乱码问题。简单的处理方式就是在 Mybatis 查询数据库的时候增加一个拦截器,给这个类型的字段改变一下编码方式。

mybatis查询mysql 数据库中 BLOB字段,结果出现乱码的更多相关文章

  1. MySQL数据库中tinyint字段值为1,读取出来为true的问题

    原文:https://blog.csdn.net/shuyou612/article/details/46788475 MySQL数据库中tinyint字段值为1,读取出来为true的问题   今天在 ...

  2. mybatis查询mysql数据库tinyint(1)变为boolean类型

    mybatis查询mysql数据库对象转化为Map,tinyint(1)被转化为boolean类型,可以t通过避免使用tinyint(1)来解决.

  3. Java读取oracle数据库中blob字段数据文件保存到本地文件(转载)

    转自:https://www.cnblogs.com/forever2698/p/4747349.html package com.bo.test; import java.io.FileOutput ...

  4. 在用mybatis向MySQL数据库中插入时间时报错:Incorrect datetime value: &#39;&#39; for column &#39;&#39; at row 1

    问题说明:使用的MySQL是5.1.37版本,用的mysql-connector-java-5.0.4.jar版本,在java文件中定义的字段是Date类型,MySQL中定义的字段类型是datetim ...

  5. MySql数据库中敏感字段加密处理方案

    比如数据表中有一个手机号码字段是敏感字段,不想明文存储,可以是用MySQL的自带的函数处理 Table 12.17 Encryption Functions Name Description AES_ ...

  6. mysql数据库中某字段一部分乱码

    笔者问题:mysql表(表中数据就是乱码,可能是插入时编码问题,这个问题以后解决)导出excel时数据中有乱码(但是在页面上查看是正常的),我们希望能导出一份没有中文乱码的excel 根据热力站中一次 ...

  7. mysql的text字段长度?mysql数据库中text字段长度不够的问题

    类型是可变长度的字符串,最多65535个字符:     可以把字段类型改成MEDIUMTEXT(最多存放16777215个字符)或者LONGTEXT(最多存放4294967295个字符). MySQL ...

  8. 查询mysql数据库中所有用户及用户权限

    SELECT DISTINCT CONCAT('User: ''',user,'''@''',host,''';') AS query FROM mysql.user;

  9. MySQL数据库中的字段类型varchar和char的主要区别是什么?哪种字段查找效率要高?

    1,varchar与char的区别?(1)区别一,定长和变长,char表示定长,长度固定:varchar表示变长,长度可变.当插入字符串超出长度时,视情况来处理,如果是严格模式,则会拒绝插入并提示错误 ...

  10. 查询mysql数据库中所有表名

    查找所有表的语句 select table_name from information_schema.tables where table_schema='当前数据库';  

随机推荐

  1. Linux下lampp详解 (转)

    重要文件解释: ProFTPD:一个Unix平台上或是类Unix平台上(如Linux, FreeBSD等)的FTP服务器程序,它是在自由软件基金会的版权声明(GPL)下开发.发布的免费软件,可以随意修 ...

  2. usb设备驱动描述,王明学learn

    usb设备驱动 本章主要内容包含以下:USB总线介绍,USB协议分析,USB系统架构 一.USB总线介绍 1.1USB发展史 USB(Universal Serial Bus)通用串行总线,是一种外部 ...

  3. Pomelo实现最简单的通信-egret。

    昨天因为需要开始学习Pomelo 做H5游戏的服务端. 因为个人学习习惯,我从来不适合去跟着文档看.一般我直接是看下大概的API,但是Pomelo的API全部都是英文的. 昨天我就告诉自己用一下午时间 ...

  4. MVC4 教程

    http://blog.csdn.net/huangjihua0402/article/details/8507055 http://www.cnblogs.com/lc-chenlong/p/324 ...

  5. C#中的DBNull、Null、""和String.Empty

    1.对DBNull的解释:    该类用于指示不存在某个已知值(通常在数据库应用程序中).       在数据库应用程序中,空对象是字段的有效值.该类区分空值(空对象)和未初始化值(DBNull.Va ...

  6. 使用JSON JavaScriptSerializer 进行序列化或反序列化时出错。字符串的长度超过了为 maxJsonLength属性

    "/"应用程序中的服务器错误.使用 JSON JavaScriptSerializer 进行序列化或反序列化时出错.字符串的长度超过了为 maxJsonLength 属性设置的值. ...

  7. 黄聪:Windows2012-IIS8安装SSL证书

    开始菜单->右上角搜索按钮-> mmc 弹出窗口 关闭控制台会提示保存 打开iis新建站点,为了兼容不支持sni的浏览器,绑定默认https

  8. Android so注入(inject)和Hook技术学习(二)——Got表hook之导入表hook

    全局符号表(GOT表)hook实际是通过解析SO文件,将待hook函数在got表的地址替换为自己函数的入口地址,这样目标进程每次调用待hook函数时,实际上是执行了我们自己的函数. GOT表其实包含了 ...

  9. AtCoder Beginner Contest 120 D - Decayed Bridges(并查集)

    题目链接:https://atcoder.jp/contests/abc120/tasks/abc120_d 题意 先给m条边,然后按顺序慢慢删掉边,求每一次删掉之后有多少对(i,j)不连通(我应该解 ...

  10. HTML5新特性:FileReader 和 FormData

    连接在这里: HTML5新特性:FileReader 和 FormData