oracle字符集NLS_CHARACTERSET为ZHS16GBK,类文件编码为UTF-8,java运行时文件编码也为UTF-8(java -Dfile.encoding=UTF-8 Test),java中字符串getByte字节数大于4000,仍然可以插入oracle数据库varchar2(4000)字段。
System.out.println(System.getProperty("file.encoding"));
//=UTF-8
System.out.println("好".getBytes().length);
//=3字节,参考jdk源码Charset.defaultCharset()使用默认字符集file.encoding
System.out.println("好".getBytes("UTF-8").length);
//=3字节,确认使用默认字符集
System.out.println("好".getBytes("GBK").length);
//=2字节,在GBK字符集中只使用两个字节
StringBuilder sb = new StringBuilder();//2000个“好”字
for (int i = 0; i < 2000; i++) {
sb.append("好");// UTF8格式3个字节
}
System.out.println(sb.toString().getBytes().length);
//=6000字节(2000个字,每个字3字节)
//sb.append("a");
加一个字节将抛出异常 java.sql.SQLException: ORA-01704: 字符串文字太长
stmt.executeUpdate("insert into t_clob(col2)values(‘" + sb.toString() + "‘)");
没有异常,可正常插入,数据库只允许4000字节,为什么6000字节居然能插进去?
猜测:jdbc底层判断当前会话连接使用的字符编码(select userenv(‘language‘) from dual),进行转换后再通过网络传输给oracle服务处理。
System.out.println(sb.toString().getBytes("GBK").length);
//=4000字节
System.out.println(new String(sb.toString().getBytes(), "GBK")); //乱码
System.out.println(new String(sb.toString().getBytes("GBK"))); //乱码
System.out.println(new String(sb.toString().getBytes("GBK"), "GBK")); //正常