Oracle 生僻字处理(mybatis、mybatis-plus、通用mapper)
问题:姓名中的生僻字查询显示问号?
再现环境:
- 数据库:Oracle Database 12c
- 后端:JDK 1.8,mybatis
- 姓名字段使用的是
VARCHAR2
保存生僻字䶮
,数据库可视化工具显示为?
,mybatis查询出来同样显示?
解决方法(已验证)
- 修改保存姓名的字段类型为
NVARCHAR2
:
alter table xxx表 modify NAME NVARCHAR2(500);
- 为mybatis添加
NVARCHAR2
的类型处理器:
NVarcharTypeHandler类
package com.power.isolated.aop;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
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> {
/**
* 重点,使用 setNString 设置
* @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);
}
}
- 在 mybatis 配置文件
mybatis-config.xml
中配置类型处理器:
<typeHandlers>
<typeHandler handler="com.power.isolated.aop.NVarcharTypeHandler"/>
</typeHandlers>
注意标签的顺序,顺序不正可能导致启动出错。
mybatis配置文件标签顺叙
properties-->settings-->typeAliases-->typeHandlers-->objectFactory-->objectWrapperFactory-->reflectorFactory-->plugins-->environments-->databaseIdProvider-->mappers
- 修改mapper.xml文件中字段的类型,即 resultMap 中的 jdbcType 和参数中的 jdbcType:
例如:
<result column="NAME" property="isolatedName" jdbcType="NVARCHAR"/>
或者
select * from xxx
where NAME = #{name, jdbcType=NVARCHAR}
mybatis-plus
mybatis-plus 除了需要上面的步骤以外,还需要修改实体类的注解:
/**
* 姓名
*/
@TableField(value = "NAME",
jdbcType = JdbcType.NVARCHAR,
typeHandler = NVarcharTypeHandler.class)
private String name;
通用mapper
通用mapper类似,修改实体类的注解:
/**
* 姓名
*/
@ColumnType(column = "NAME",
jdbcType = JdbcType.NVARCHAR,
typeHandler = NVarcharTypeHandler.class)
private String name;
注:原本的@Column
注解是javax.persistence
包下面的,需要修改为tk.mybatis.mapper.annotation
包下面的@ColumnType
注解。
经验证可以正确存取生僻字。