问题:姓名中的生僻字查询显示问号?

再现环境:

  • 数据库:Oracle Database 12c
  • 后端:JDK 1.8,mybatis
  • 姓名字段使用的是VARCHAR2

保存生僻字,数据库可视化工具显示为?,mybatis查询出来同样显示?

解决方法(已验证)

  1. 修改保存姓名的字段类型为NVARCHAR2
alter table xxx表 modify NAME NVARCHAR2(500);
  1. 为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);
    }
}

  1. 在 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
  1. 修改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注解。


经验证可以正确存取生僻字。

标签: Java, 数据库

添加新评论