mybatis查询mysql 数据库中 BLOB字段,结果出现乱码
起因
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字段,结果出现乱码的更多相关文章
- MySQL数据库中tinyint字段值为1,读取出来为true的问题
原文:https://blog.csdn.net/shuyou612/article/details/46788475 MySQL数据库中tinyint字段值为1,读取出来为true的问题 今天在 ...
- mybatis查询mysql数据库tinyint(1)变为boolean类型
mybatis查询mysql数据库对象转化为Map,tinyint(1)被转化为boolean类型,可以t通过避免使用tinyint(1)来解决.
- Java读取oracle数据库中blob字段数据文件保存到本地文件(转载)
转自:https://www.cnblogs.com/forever2698/p/4747349.html package com.bo.test; import java.io.FileOutput ...
- 在用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 ...
- MySql数据库中敏感字段加密处理方案
比如数据表中有一个手机号码字段是敏感字段,不想明文存储,可以是用MySQL的自带的函数处理 Table 12.17 Encryption Functions Name Description AES_ ...
- mysql数据库中某字段一部分乱码
笔者问题:mysql表(表中数据就是乱码,可能是插入时编码问题,这个问题以后解决)导出excel时数据中有乱码(但是在页面上查看是正常的),我们希望能导出一份没有中文乱码的excel 根据热力站中一次 ...
- mysql的text字段长度?mysql数据库中text字段长度不够的问题
类型是可变长度的字符串,最多65535个字符: 可以把字段类型改成MEDIUMTEXT(最多存放16777215个字符)或者LONGTEXT(最多存放4294967295个字符). MySQL ...
- 查询mysql数据库中所有用户及用户权限
SELECT DISTINCT CONCAT('User: ''',user,'''@''',host,''';') AS query FROM mysql.user;
- MySQL数据库中的字段类型varchar和char的主要区别是什么?哪种字段查找效率要高?
1,varchar与char的区别?(1)区别一,定长和变长,char表示定长,长度固定:varchar表示变长,长度可变.当插入字符串超出长度时,视情况来处理,如果是严格模式,则会拒绝插入并提示错误 ...
随机推荐
- allure用法(一)-配置信息及基本用法
allure是一个轻量级的,灵活的,支持多语言的测试报告工具 优点: 可以为dev/qa 提供 详尽的测试报告.测试步骤.日志 可以为管理层提供更好的统计报告 Java语言开发的 可以集成到jenki ...
- ui-route的一般用法 ,比较简单。在平时项目也用到,但是我也要记下来,虽然是'借鉴的',取其精华
这是个啥? ui-router是一个web客户端的路由解决方案.我觉得它最大的作用是将web界面的设计分块了. 分块分层 最初的web访问模型,是这样的: 我们访问page1,然后访问page2... ...
- petite-vue源码剖析-沙箱模型
在解析v-if和v-for等指令时我们会看到通过evaluate执行指令值中的JavaScript表达式,而且能够读取当前作用域上的属性.而evaluate的实现如下: const evalCache ...
- 震惊!<string.h>、<cstring>和<string>竟然可以这么用!
为什么有这么多string相关的头文件呢,小编秦始皇今天带大家看一下: 1.[string.h] 定义如下:"C语言标准库中一个常用的头文件,在使用到字符数组时需要使用.[strin ...
- Es5 - 11 详解
一.ES简介 ECMAScript,欧洲计算机制造商协会 ES是一种标准,而JS是ES的一种实现 每年的ES版本中都会引入新特性 二.NRM的安装与使用 NRM是切换源的工具 ES6 2.1安装 wi ...
- 单列集合(Collection-List)
与数组的区别 ArrayList while循环快捷键itit 遍历方法2:增强for循环 快捷键大写的I List接口(少部分常用的) List三种遍历方式 注意事项 ArrrayList底层结构和 ...
- 详解MySQL索引
原文链接详解MySQL索引 索引介绍 索引是帮助MySQL高效获取数据的数据结构.在数据之外,数据库系统还维护着一个用来查找数据的数据结构,这些数据结构指向着特定的数据,可以实现高级的查找算法. 本文 ...
- 团队Beta2
队名:观光队 链接 组长博客 作业博客 组员实践情况 王耀鑫 **过去两天完成了哪些任务 ** 文字/口头描述 学习 展示GitHub当日代码/文档签入记录 接下来的计划 完成短租车,页面美化 **还 ...
- java基础4.20
1.是否可以从一个static方法内部发出对非static方法的调用? 不可以.因为非static方法是要与对象关联在一起的,必须创建一个对象后,才可以在该对象上进行方法调用,而static方法调用时 ...
- 为什么Redis要比Memcached更火?
关注「开源Linux」,选择"设为星标" 回复「学习」,有我为您特别筛选的学习资料~ 前言 我们都知道,Redis和Memcached都是内存数据库,它们的访问速度非常之快.但我们 ...