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表示变长,长度可变.当插入字符串超出长度时,视情况来处理,如果是严格模式,则会拒绝插入并提示错误 ...
随机推荐
- HTTP请求头格式和响应格式
HTTP请求头格式 提示: 回车符 \r 换行符 \n 请求首行分析: 请求方式: GET 和 POST 方式: GET请求:地址栏访问.超链接访问都是get请求方式,get请求方式不安全,地址栏大小 ...
- 如何满足一个前端对 Mock 的全部幻想
前端的痛苦 作为前端,最痛苦的是什么时候? 每个迭代,需求文档跟设计稿都出来了,静态页面唰唰两天就做完了.可是做前端又不是简单地把后端吐出来的数据放到页面上就完了,还有各种前端处理逻辑啊. 后端接 ...
- k8s 初始化环境(1)
概念 k8s/kubernetes 容器化部署 解决容器编排问题,kubernetes为容器编排软件的佼佼者 kubernets为一组服务器集群 功能 自我修复 一个容器崩溃,另一个容器起来 弹性伸缩 ...
- Java学习day4
今天学习了String以及StringBuider 其中较为重点的除了用法以外,还有,String对象以""方式给出的字符串,只要字符序列相同(即顺序和大小写)无论在代码中重复几次 ...
- optimoptions requires Optimization Toolbox(optimoptions 需要 Optimization Toolbox)解决方法
问题:在下载版的matlab中做coursera的machine learning里的ex2,做到 1.2.3 Learning parameters using fminunc 时出现optimop ...
- Java函数的学习
函数的定义 - 定义的位置:定义在类的内部 - 组成部分: 函数修饰符 类型 函数名(形式参数){ 局部变量: 注释: 函数体: } 函数的调用 - 调用函数时使用 : `函数名():` - 函数在执 ...
- 前后端分离后台管理系统 Gfast v3.0 全新发布
GFast V3.0 平台简介 基于全新Go Frame 2.0+Vue3+Element Plus开发的全栈前后端分离的管理系统 前端采用vue-next-admin .Vue.Element UI ...
- Bugku CTF练习题---加密---凯撒部长的奖励
Bugku CTF练习题---加密---凯撒部长的奖励 flag:SYC{here_Is_yOur_rEwArd_enjOy_It_Caesar_or_call_him_vIctOr_is_a_Exc ...
- FreeRTOS --(8)任务管理之创建任务
转载自https://blog.csdn.net/zhoutaopower/article/details/107034995 在<FreeRTOS --(7)任务管理之入门篇>文章基本分 ...
- mysql中的date、datetime、timestamp你还不知道怎么使用吗
在后端开发中经常会碰到涉及数据库的场景,不知道屏幕前的你有这样的疑惑没有,每每在遇到时间.日期字段总是让人头疼,分不清到底是选date还是datetime,亦或是timestamp,真是抓耳挠腮啊,怎 ...