1.问题描述:
正式环境的旧系统使用的是oracle数据库,某表remarks备注字段最大长度是varchar2(4000),编码格式为UTF-8,可以存取4000字符和1333个中文字符串。上游系统推送的数据中,remarks的字符长度虽不超过4000字,但包含了中文字符,超过了4000,导致入库失败。经讨论过后,对不重要的字符进行截取入库处理。
2.解决方案:
截取超出的部分
if (StringUtils.lengthOfUTF8(obj.getRemarks()) >= 4000) {
logger.info(String.format("XX表的remarks字符串过长截取:%s", obj.getRemarks()));
obj.setRemarks(StringUtils.subOfUTF8Max(obj.getRemarks()));
}
xxxService.save(obj);
3.工具类
package com.test.common.utils;
/**
* 字符串工具类, 继承org.apache.commons.lang3.StringUtils类
*
* @author lmp
* @version
*/
public class StringUtils extends org.apache.commons.lang3.StringUtils {
/**
* 输出UTF8编码下的字节长度
*
* @param value
* @return
*/
public static int lengthOfUTF8(String value) {
int valueLength = 0;
if (value == null) {
return valueLength;
}
String chinese = "[\u0391-\uFFE5]";
/* 获取字段值的长度,如果含中文字符,则每个中文字符长度为3,否则为1 */
for (int i = 0; i < value.length(); i++) {
/* 获取一个字符 */
String temp = value.substring(i, i + 1);
/* 判断是否为中文字符 */
if (temp.matches(chinese)) {
/* 中文字符长度为3 */
valueLength += 3;
} else {
/* 其他字符长度为1 */
valueLength += 1;
}
}
return valueLength;
}
/**
* 输出UTF8编码下的限制最大字节长度的下标
*
* @param value
* @return
*/
public static int lengthOfUTF8MaxOfIndex(String value, int max) {
int valueLength = 0;
if (value == null) {
return valueLength;
}
String chinese = "[\u0391-\uFFE5]";
/* 获取字段值的长度,如果含中文字符,则每个中文字符长度为3,否则为1 */
for (int i = 0; i < value.length(); i++) {
/* 获取一个字符 */
String temp = value.substring(i, i + 1);
/* 判断是否为中文字符 */
if (temp.matches(chinese)) {
/* 中文字符长度为3 */
valueLength += 3;
} else {
/* 其他字符长度为1 */
valueLength += 1;
}
if (valueLength > max) {
return i;
}
}
return value.length();
}
/**
* 截取UTF8编码下的限制最大字节长度的
*
* @param value
* @return
*/
public static String subOfUTF8Max(String value, int max) {
if (value == null) {
return null;
}
return value.substring(0, lengthOfUTF8MaxOfIndex(value, max));
}
/**
* 截取UTF8编码下的限制最大字节长度的,默认4000(oracle库varchar2最大值)
*
* @param value
* @return
*/
public static String subOfUTF8Max(String value) {
if (value == null) {
return null;
}
return subOfUTF8Max(value, 4000);
}
}