起因

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: '' for column '' 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表示变长,长度可变.当插入字符串超出长度时,视情况来处理,如果是严格模式,则会拒绝插入并提示错误 ...

随机推荐

  1. linux三剑客试题汇总

    1.找出/proc/meminfo文件中以s开头的行,至少用三种方式忽略大小写 [root@localhost ~]# grep -E '^[sS]' /proc/meminfo [root@loca ...

  2. 学习打卡——docker部署

    1. 部署mysql 拉取对应版本的mysql,不加版本号默认当前最新版 docker pull mysql:8.0.26 创建目录,可以换成你自己想把它存放的目录,后续同理 mkdir ~/mysq ...

  3. Dubbo-admin启动问题

    在Github上down了Dubbo-admin的最新文件,使用cmd命令打包完成后启动出现了问题,输出找不到2181端口的error. 百度只查询到是Dubbo-admin配置中的Zookeeper ...

  4. android软件简约记账app开发day08-时间对话框的书写+改bug,改bug

    android软件简约记账app开发day08-时间对话框的书写+改bug,改bug 绘制对话跨页面 在添加记账信息功能中,我提供了用户添加备注添加事件的功能,设计是点击时间会弹出一个时间对话框供用户 ...

  5. Divan and bitwise operations

    这是一道比较综合的数学题目,光是吧题目看懂就花了我好一会儿时间,先看看题目吧: 题目分析:对于m段给定连续段的或值,要求出n个数的序列子序列的异或值之和: 题解: 这道题,我们先不要把它当作一个数一个 ...

  6. 01. 树莓派初始配置——ssh连接使用root用户登录

    ssh连接使用root用户登录 普通的"pi"用户没有权限访问某些文件夹,或者对它们只有只读功能.部分操作需要在每条命令前都要加上"sudo",非常不方便.切换 ...

  7. Markdown学习-Typora

    author:涂勇军 标题 (#加一个空格)一级标题 (##加一个空格)二级标题 (###加一个空格)三级标题 (####加一个空格)四级标题 字体 加粗:** hello,World **(快捷键是 ...

  8. C语言超全学习路线(收藏让你少走弯路)

    刚入门是否觉得C语言很难?那可能是你还没找到正确的C语言学习路线,收藏以防找不到,让你少走弯路. 基本语法 选择控制语句 if,swith 循环控制语句 while,for 控制语句相关关键字分析 变 ...

  9. 1.6 为什么要学Linux,它比Windows好在哪里?

    早在 20 世纪 70 年代,UNIX 系统是开源而且免费的,但是在 1979 年时,AT&T 公司宣布了对 UNIX 系统的商业化计划,随之开源软件业转变成了版权式软件产业,源代码被当作商业 ...

  10. 用NetworkX生成并绘制(带权)无向图

    NetworkX是一个非常强大的网络科学工具,它封装了图的数据结构和许多经典图算法,也内置了许多可视化函数可供调用. 1. 随机图生成 最经典的随机图当属我们在上一篇博客<Erdos-Renyi ...