在数据入库的时候,我们经常需要判断入库的字符串是否超长。如果字符串长度超长,需要分割字符串再存入数据库中。
这本是很正常的逻辑,但是在使用Java写入字符串到Oracle中在一种坑:如果你的Oracle表中使用了varchar类型,且单位是byte。那么使用Java进行字符串长度判断 及 字符串分割时,也需要按照 字节 的方式来进行处理,而不是 字符 的方式。
举例如下:
- 错误方式
// 按照字符方式进行判断及分割
String remark = "人工处理成失败";
if (remark.length() > 8) {
remark = remark.substring(0, 8);
}
System.out.println(remark);
- 正确方式
// 按照字节方式进行判断及分割
String remark = "人工处理成失败";
byte[] bytes = remark.getBytes();
if (bytes.length > 8) {
remark = new String(Arrays.copyOfRange(bytes, 0,8));
}
System.out.println(remark);
如果使用上述的错误方式进行操作的话,可能会超过Oracle表设置的字节长度大小的,从而导致业务异常。
究其原因,还是因为Oracle数据库字段的定义 与 代码实现的基准不一致导致的。如果Oracle中varchar用byte作为基准进行存储,我们的Java代码中也要按照字节来进行计算,这样才能符合我们的预期。
可以看到,Java中String的字符及字节长度是有区别的:
String remark = "人工处理成失败";
// 字符长度为7
System.out.println(remark.length());
// 字节长度为21
System.out.println(remark.getBytes().length);
当然,如果你运行上面正确方式的代码,会发现结果中包含了乱码。这是因为Java中以3个字节组成一个字符(UTF-8),所以如果你不想乱码的话,截取的时候,将分割的长度设置为3的倍数就行了。