我是靠谱客的博主 暴躁板栗,最近开发中收集的这篇文章主要介绍解决Mybatis3.3中NVARCHAR2生僻字乱码1. 解决Mybatis3.3中NVARCHAR2生僻字乱码,觉得挺不错的,现在分享给大家,希望可以做个参考。
概述
文章目录
- 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. 注意
- 使用的mybatis版本是3.3,不知道再其它版本中是否有同样问题
- 这里的乱码和前后端文件等编码无关,即所有中文存入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> {
@Override
public 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
*/
@Override
public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
ps.setNString(i, parameter);
}
@Override
public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
return rs.getString(columnName);
}
@Override
public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
return rs.getString(columnIndex);
}
@Override
public 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. 总结
- 数据库字符集,utf8比gbk范围更大,gbk无法现在生僻字。
- varchar2与数据库字符集有关,nvarchar与数据库字符集无关
- 也许mybatis对NVARCHAR的处理有bug,在NStringTypeHandler中居然没有
setNString
- 由此可见,
PreparedStatement
的setString
和setNString
实现也是不同的,可以看看源码。
最后
以上就是暴躁板栗为你收集整理的解决Mybatis3.3中NVARCHAR2生僻字乱码1. 解决Mybatis3.3中NVARCHAR2生僻字乱码的全部内容,希望文章能够帮你解决解决Mybatis3.3中NVARCHAR2生僻字乱码1. 解决Mybatis3.3中NVARCHAR2生僻字乱码所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复