数据库字符集处理
背景:
老数据库(oracle 10g)存储数据,字符集:AMERICAN_AMERICA.US7ASCII
系统也是使用的老模式,需要在数据库中插入和读取数据
最终发现只需要处理中文,数字和英文是不需要处理的!
网上或者是AI的话,都是建议换掉,因为数据库版本和字符集都太陈旧了,但是没有办法,不能换。只能处理转换
1.插入数据
/** 存入数据库前转码 */ public static String chineseEncode(String parm) throws UnsupportedEncodingException { if(parm==null || parm.isEmpty()){ return new String(""); } return new String(parm.getBytes("gbk"), "ISO-8859-1"); }
2.查询取出
/** * 将字节数组按 GBK 字符集解码为 Java String。 * 私有工具方法,被上述三个 getNullableResult 方法复用。 * * @param bytes 数据库返回的字节数组(可能为 null) * @return 解码后的字符串;若输入为 null,则返回 null * @throws SQLException 如果 GBK 解码失败(如字节序列不符合 GBK 规范) */ private String convertFromBytes(byte[] bytes) throws SQLException { if (bytes == null) { return null; } try { // 使用 GBK 字符集将字节数组转换为字符串 return new String(bytes, GBK); } catch (UnsupportedEncodingException e) { log.error("查询时转码异常:",e); // 理论上 GBK 总是可用,但此处仍做异常处理并包装为 SQLException throw new SQLException("GBK decoding failed", e); } }
3.最终使用
3.1 字段上增加注解
这里使用的mybatis plus的注解
/** 卖方名称 */ @Excel(name = "卖方名称") @ApiModelProperty("卖方名称") @TableField(typeHandler = GbkBlobTypeHandler.class) private String dwmc;
3.2 BaseTypeHandler处理器实现,代码AI生成
package com.luan.avs.handle; import lombok.extern.slf4j.Slf4j; import org.apache.ibatis.type.BaseTypeHandler; import org.apache.ibatis.type.JdbcType; import org.apache.ibatis.type.MappedJdbcTypes; import org.apache.ibatis.type.MappedTypes; import java.io.UnsupportedEncodingException; import java.sql.CallableStatement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; /** * 自定义 MyBatis TypeHandler,用于处理 Java String 类型与数据库 BLOB/VARBINARY 类型之间的转换, * 转换时使用 GBK 字符集进行编码/解码。 * <p> * 适用场景: * - 对接遗留系统或第三方数据库,其中文本字段以 GBK 编码的字节形式存储在 BLOB/RAW 类型列中。 * - 需要确保读取和写入时字符编码一致性,避免乱码问题。 * <p> * 注意:该 TypeHandler 会全局影响所有使用该字段的查询和插入操作, * 如果只需要对特定数据源生效,建议配合独立的 SqlSessionFactory 使用。 * * @author yxg * @since 2026-03-24 */ @Slf4j @MappedTypes(String.class) // 指定处理的 Java 类型为 String @MappedJdbcTypes({JdbcType.VARCHAR, JdbcType.BLOB, JdbcType.VARBINARY, JdbcType.NVARCHAR}) public class GbkBlobTypeHandler extends BaseTypeHandler<String> { /** * GBK 字符集名称常量。 * GBK 是中文 Windows 系统常用的扩展字符集,支持简体中文。 */ private static final String GBK = "GBK"; /** * 设置非空参数:将 Java String 转换为 GBK 编码的字节数组,并设置到 PreparedStatement 中。 * * @param ps PreparedStatement 对象 * @param i 参数索引(从 1 开始) * @param parameter 要设置的 Java String 参数值(非 null) * @param jdbcType 参数的 JDBC 类型(由 MyBatis 自动推断,此处未直接使用) * @throws SQLException 如果发生数据库访问错误,或 GBK 编码转换失败(包装为 SQLException) */ @Override public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException { try { // 将 Java String 按 GBK 编码转换为字节数组 String str = chineseEncode(parameter); // 将字节数组设置到 PreparedStatement 中(对应数据库 BLOB/VARBINARY 类型) ps.setString(i, str); } catch (UnsupportedEncodingException e) { log.error("插入时转码异常:",e); // 理论上 GBK 字符集在所有 Java 平台均受支持,但为了健壮性仍进行异常处理 throw new SQLException("GBK encoding not supported when setting parameter at index " + i, e); } } /** 存入数据库前转码 */ public static String chineseEncode(String parm) throws UnsupportedEncodingException { if(parm==null || parm.isEmpty()){ return new String(""); } return new String(parm.getBytes("gbk"), "ISO-8859-1"); } /** * 从 ResultSet 中根据列名获取值,并将数据库中的字节数组按 GBK 解码为 Java String。 * * @param rs ResultSet 对象 * @param columnName 列名 * @return 解码后的 Java String;如果数据库值为 null,则返回 null * @throws SQLException 如果发生数据库访问错误,或 GBK 解码失败(包装为 SQLException) */ @Override public String getNullableResult(ResultSet rs, String columnName) throws SQLException { byte[] bytes = rs.getBytes(columnName); return convertFromBytes(bytes); } /** * 从 ResultSet 中根据列索引获取值,并将数据库中的字节数组按 GBK 解码为 Java String。 * * @param rs ResultSet 对象 * @param columnIndex 列索引(从 1 开始) * @return 解码后的 Java String;如果数据库值为 null,则返回 null * @throws SQLException 如果发生数据库访问错误,或 GBK 解码失败(包装为 SQLException) */ @Override public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException { byte[] bytes = rs.getBytes(columnIndex); return convertFromBytes(bytes); } /** * 从 CallableStatement 中根据列索引获取值(用于存储过程输出参数), * 并将数据库中的字节数组按 GBK 解码为 Java String。 * * @param cs CallableStatement 对象 * @param columnIndex 列索引(从 1 开始) * @return 解码后的 Java String;如果数据库值为 null,则返回 null * @throws SQLException 如果发生数据库访问错误,或 GBK 解码失败(包装为 SQLException) */ @Override public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { byte[] bytes = cs.getBytes(columnIndex); return convertFromBytes(bytes); } /** * 将字节数组按 GBK 字符集解码为 Java String。 * 私有工具方法,被上述三个 getNullableResult 方法复用。 * * @param bytes 数据库返回的字节数组(可能为 null) * @return 解码后的字符串;若输入为 null,则返回 null * @throws SQLException 如果 GBK 解码失败(如字节序列不符合 GBK 规范) */ private String convertFromBytes(byte[] bytes) throws SQLException { if (bytes == null) { return null; } try { // 使用 GBK 字符集将字节数组转换为字符串 return new String(bytes, GBK); } catch (UnsupportedEncodingException e) { log.error("查询时转码异常:",e); // 理论上 GBK 总是可用,但此处仍做异常处理并包装为 SQLException throw new SQLException("GBK decoding failed", e); } } public static void main(String[] args) throws Exception { String shrmc = "营销总公司"; System.out.println(chineseEncode(shrmc)); } }
4.数据库连接参数调整(这里使用的是Navicat 15)

主要设置: 客户端字符集,编码

这样设置之后查询出来的中文就不是乱码了

浙公网安备 33010602011771号