文章目录

  • 1. 解决Mybatis3.3中NVARCHAR2生僻字乱码
    • 1.1. 注意
    • 1.2. 解决方法
      • 1.2.1. 第一步、数据库的varchar2字段修改为nvarchar2
      • 1.2.2. 第二步、mybatis中原来的`jdbcType=VARCHAR`修改为`jdbcType=NVARCHAR`
      • 1.2.3. 第三步、重写NVARCHAR的类型处理
      • 1.2.4. 注意,还需要在mybatis-config.xml中配置一下
    • 1.3. 总结

1. 解决Mybatis3.3中NVARCHAR2生僻字乱码

在数据库中原来的字符串类型都是用varchar2类型存储,现在发现生僻字乱码,遂改为NVARCHAR2,但是依然生僻字乱码。

1.1. 注意

  1. 使用的mybatis版本是3.3,不知道再其它版本中是否有同样问题
  2. 这里的乱码和前后端文件等编码无关,即所有中文存入varchar2,只有生僻字乱码,其它正常

1.2. 解决方法

1.2.1. 第一步、数据库的varchar2字段修改为nvarchar2

  因为varchar2和数据库的字符集有关系,而数据库在ZHS16GBK(应该是等同于GBK吧?!)编码下,不包含生僻字;修改为AL32UTF8后mybatis居然把所有从数据库查出的中文显示为乱码了。。。所以只能使用nvarchar2。由此可以总结出:varchar2与数据库字符集有关,而nvarchar2则与数据库字符集无关(可以在varchar2和nvarchar2字段中手动输入生僻字即可看到证据)

1.2.2. 第二步、mybatis中原来的jdbcType=VARCHAR修改为jdbcType=NVARCHAR

  如果不修改的话,mybatis的类型处理器,默认会使用StringTypeHandler来处理,StringTypeHandler源码如下,可以看出使用的依然是setString

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//package org.apache.ibatis.type;import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;public class StringTypeHandler extends BaseTypeHandler<String> {public StringTypeHandler() {}public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {ps.setString(i, parameter);}public String getNullableResult(ResultSet rs, String columnName) throws SQLException {return rs.getString(columnName);}public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {return rs.getString(columnIndex);}public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {return cs.getString(columnIndex);}
}

再来看NStringTypeHandler

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//package org.apache.ibatis.type;import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;public class NStringTypeHandler extends BaseTypeHandler<String> {public NStringTypeHandler() {}public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {ps.setString(i, parameter);}public String getNullableResult(ResultSet rs, String columnName) throws SQLException {return rs.getString(columnName);}public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {return rs.getString(columnIndex);}public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {return cs.getString(columnIndex);}
}

看上去和StringTypeHandler一样呀,调试了几个小时才调好,方法是重写NStringTypeHandler,如下第三步

1.2.3. 第三步、重写NVARCHAR的类型处理

如下,暂时只处理了set方法(即改为setNString),因为get出来的结果生僻字没问题,所以没有修改。

package com.ufgov.util.mybatis;import org.apache.ibatis.type.*;import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;/*** NVARCHAR汉字生僻字乱码问题。* 主要是NStringTypeHandler中,没有setNString()*/
@MappedJdbcTypes(JdbcType.NVARCHAR)
public class NVarcharTypeHandler extends BaseTypeHandler<String> {@Overridepublic void setParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {if(parameter == null) {if(jdbcType == null) {throw new TypeException("JDBC requires that the JdbcType must be specified for all nullable parameters.");}try {ps.setNull(i, jdbcType.TYPE_CODE);} catch (SQLException var7) {throw new TypeException("Error setting null for parameter #" + i + " with JdbcType " + jdbcType + " . " + "Try setting a different JdbcType for this parameter or a different jdbcTypeForNull configuration property. " + "Cause: " + var7, var7);}} else {try {this.setNonNullParameter(ps, i, parameter, jdbcType);} catch (Exception var6) {throw new TypeException("Error setting non null for parameter #" + i + " with JdbcType " + jdbcType + " . " + "Try setting a different JdbcType for this parameter or a different configuration property. " + "Cause: " + var6, var6);}}}/*** 这里使用setNString而不是setString* @param ps* @param i* @param parameter* @param jdbcType* @throws SQLException*/@Overridepublic void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {ps.setNString(i, parameter);}@Overridepublic String getNullableResult(ResultSet rs, String columnName) throws SQLException {return rs.getString(columnName);}@Overridepublic String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {return rs.getString(columnIndex);}@Overridepublic String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {return cs.getString(columnIndex);}
}

1.2.4. 注意,还需要在mybatis-config.xml中配置一下

<typeHandlers><typeHandler handler="com.ufgov.util.mybatis.NVarcharTypeHandler"/></typeHandlers>

1.3. 总结

  1. 数据库字符集,utf8比gbk范围更大,gbk无法现在生僻字。
  2. varchar2与数据库字符集有关,nvarchar与数据库字符集无关
  3. 也许mybatis对NVARCHAR的处理有bug,在NStringTypeHandler中居然没有setNString
  4. 由此可见,PreparedStatementsetStringsetNString实现也是不同的,可以看看源码。

解决Mybatis3.3中NVARCHAR2生僻字乱码相关推荐

  1. PB中生僻字乱码问题得以解决

    遇到过pb中出现生僻字时,显示的是乱码,查明原因原来是解析不到生僻字,只需将 pos-改成posw,mid-改成midw函数即可

  2. Oracle 生僻字乱码问题

    就一般情况来说,Oracle存储中英文的字段用varchar2类型就可以了,但有些时候,遇到生僻字就不行了. 需求描述: 在默认字符集环境下,实现Oracle储存生僻字: 㛃.䶮.....(使用nva ...

  3. java mysql 生僻字 乱码_JAVA生僻字乱码问题

    我先把数据从数据库中查出来,然后输出到EXCEL表格中,但是表格中显示的是乱码.数据库中的数据是正常的,没有问题,程序有个查询功能,一个导出功能,查询功能是调用润乾展示报表,没有乱码.... 我先把数 ...

  4. jsoup 生僻字乱码问题解决

    jsoup 简介 Java 程序在解析 HTML 文档时,相信大家都接触过 htmlparser 这个开源项目,我曾经在 IBM DW 上发表过两篇关于 htmlparser 的文章,分别是:从 HT ...

  5. oracle 生僻字 转码,Oracle 生僻字乱码解决方案

    Oracle生僻字乱码解决方案 ""(此+夕)[suǒ]字乱码,无法正常显示(变成问号); 生僻字""(此+夕)(suo)在ZHS16GBK字符集下默认无法正常 ...

  6. sqlserver中文生僻字乱码问题

    sqlserver中文生僻字乱码问题解决 场景:前端输入生僻字,e.g. 㙍.㮾,存入到数据库为乱码(㙍/-). 解决:修改会存生僻字的字段(一般地址字段)的数据类型为nvarchar,在插入或更新s ...

  7. 生僻字html乱码,Tomcat 5.5.X及以上版本的生僻字乱码解决办法

    软件环境:Tomcat5.5.X 问题描述: 1)一般的汉字正常,如:中国,任务,管理. 2)生僻字出现乱码.如:喆,璟. 解决过程: 1.前言.在Tomcat4中,GET和POST使用相同的处理方式 ...

  8. 解决jacob用wps将word转html的时候个别生僻字乱码的问题

    原创文章,转载请注明出处 用jacob将wps转html的时候,Java读入转后的html,发现有个别生僻字出现乱码, 解决方法: 因为WPS默认转成html是gb2312编码的,而gb2312不支持 ...

  9. was中奇怪的生僻字乱码案例

    问题描述 这个今天早上提供的一个生产问题.大体是说,改资料的时候,有个客户的名字有生僻字,叫"刘",保存之后就乱码了,变成"刘?" 分析过程 乱码需要确认数据 ...

最新文章

  1. 编写程序,输出所有3位数的水仙花数
  2. 类的加载顺序和对象的实例化
  3. 2020华南理工计算机考研分数线,华南理工大学2020考研复试分数线已公布
  4. 【企业管理】高效会议关注点
  5. React学习小结(二)
  6. 排序算法之快速排序详解
  7. 构建java ut运行环境
  8. 通达OA2017恢复数据库Access denied for user 'root'@'localhost' (using password: YES)报错的解决办法
  9. hadoop学习之azkaban(5.1):azkaban的使用及示例 标签: 任务调度hadoopazkaban脚本
  10. 计算机组成原理 存储单元、存储字、存储字长、存储容量的区分
  11. unity剩余高度自适应实现办法
  12. 交集♂差集♂并集♂和其他集合的内置方法
  13. android仿网易云音乐引导页、仿书旗小说Flutter版、ViewPager切换、风扇叶片效果等源码...
  14. SEO优化与SEM(竞价)区别在哪?
  15. jQuery 流星雨特效
  16. 翻译质量评估的标准与方法
  17. GMSL高带宽视频数据接入的方法
  18. Python最简单的图形编程
  19. 运动APP软件开发具有什么好处?
  20. 加州大学河滨分校计算机科学排名,2019加州大学河滨分校排名(USNews排名)

热门文章

  1. 【机器学习实战】KNN
  2. 键盘钢琴html代码,Flash键盘钢琴 电脑键盘钢琴附键盘钢琴谱
  3. 2022年高处安装、维护、拆除操作证考试题库及答案
  4. Mac安装与配置jmeterjmeter的使用jmeter生成性能测试报告
  5. win10电脑pppoe拨号模块损坏_WIN10系统提示拨号连接已阻止的解决方法
  6. 计算机网络的五层模型和七层模型
  7. 矽杰微 X8M2101 单片机
  8. 在种子轮中,如何区分风险投资、种子投资和天使投资?
  9. 海康威视SDK控制台程序consoleDemo将实时码流保存为视频文件mp4
  10. BAT脚本打开重复打开软件