对于问题2:
在程序中的某处判断(原来是2048,不是600)
if (strbuf.length() > 600)
strbuf.delete(600, strbuf.length());另一处
String sql = "insert into CONTENT_TABLE"
+ "(CONTENT_ID,TITLE,CONTENT,CREATE_DATE) "
+ "values(" + CONTENT_SEQUENCE.NEXTVAL,?,?,SYSDATE)";
PreparedStatement ps = codb.getPreparedStatement(sql);
ps.setString(1, "Title"); // 没问题因为字符串短
ps.setString(2, strbuf); // 有时有问题,因为长
ps.executeUpdate();
ps.close();某次打印错误结果:
Error:java.sql.SQLException: Error in insertAfterCopy into CONTENT_TABLE:java.sql.SQLException: 数据大小超出此类型的最大值: 2254
在程序中的某处判断(原来是2048,不是600)
if (strbuf.length() > 600)
strbuf.delete(600, strbuf.length());另一处
String sql = "insert into CONTENT_TABLE"
+ "(CONTENT_ID,TITLE,CONTENT,CREATE_DATE) "
+ "values(" + CONTENT_SEQUENCE.NEXTVAL,?,?,SYSDATE)";
PreparedStatement ps = codb.getPreparedStatement(sql);
ps.setString(1, "Title"); // 没问题因为字符串短
ps.setString(2, strbuf); // 有时有问题,因为长
ps.executeUpdate();
ps.close();某次打印错误结果:
Error:java.sql.SQLException: Error in insertAfterCopy into CONTENT_TABLE:java.sql.SQLException: 数据大小超出此类型的最大值: 2254
strbuf.delete(600, strbuf.length());
这句写错了,应该是:
strbuf.delete(600, strbuf.length()-1);
试一试看看!
某次错误打印结果:
Exception in thread "main" java.lang.OutOfMemoryError
<<no stack trace available>>我还没有定位过程序在什么地方才出这个错,但似乎不太好定位,如果是一般的exception,它会告诉你哪个java文件的哪行,直接去那里找就可以了。to wyalchemy:
这句应该没有写错吧,jdk1.3的onlinehelp:
public StringBuffer delete(int start,
int end)
Removes the characters in a substring of this StringBuffer. The substring begins at the specified start and extends to the character at index end - 1 or to the end of the StringBuffer if no such character exists. If start is equal to end, no changes are made.Parameters:start - The beginning index, inclusive.
end - The ending index, exclusive.Returns:This string buffer.Throws:StringIndexOutOfBoundsException - if start is negative, greater than length(), or greater than end.Since: 1.2
strbuf.delete(599, strbuf.length()-1);
//strbuf.delete(600-1, strbuf.length()-1);
我相信这句没有写错,你是觉得delete没有正确操作,导致strbuf还是原来的长度?
可是现在是,如果如我所写的那样运行,就不会有sql异常了(因为已经截取的很短了),不信可以用length方法验证。length() - 1是对的(end - The ending index, exclusive.)
StringBuffer strbufTemp = new StringBuffer(s);
if( 6 < strbufTemp.length()){
strbufTemp.delete(6,strbufTemp.length());
System.out.println("s: " + s);
System.out.println("strbufTemp: " + strbufTemp);
}
得到的结果是:
s: 0123456789
strbufTemp: 012345
///////////////////
对于“
可是现在是,如果如我所写的那样运行,就不会有sql异常了(因为已经截取的很短了),
”
那我想是你的if条件有问题了吧,试试这样:
if (strbuf.length() >= 600)
或:
if (600 < strbuf.length() ) // 一般这样写。
sorry,刚才是笔误,应该是"length()是对的",而非"length() - 1是对的"
不理解你的意思。
对于问题2,我现在是采用“过份”减少字符长度的方法来解决的,程序运行很好,没有sql异常出现。
虽然问题是解决了,但是我还是不明白问题产生的原因,所以才会问的。
OutOfMemoryError是一个内存溢出Error、不是Excepion,你可以通过
try {
...
} catch (Error e) {
..
}
捕获到它。
出现这个错误的原因:新的对象需要空间,而JVM回收没用对象的速度不够快,又没有来得及申请更多的空间;或者程序中积累了太多的对象。两者都是程序编写的问题。问题2
即使是varchar2类型,有时也不能简单的用setString来完成插入操作,用JDBC的setString是有长度限制的。如果字符很长,就需要用JDBC的Long类型来操作。不知道这时不是你遇到的问题。
谢谢,如何理解"需要用JDBC的Long类型来操作",能否再详细些。
to haichuang:
如果是这个原因,好像还是不对,我曾经这样解释过,但是“膨胀”的倍数不是2倍,而是3.X倍,如果字串内容不一样,倍数还不是一个常量。
应该是"length()是对的",
///////////////////////////
问题产生的原因就是“你所用的oracle jdbc driver 的setString是有长度限制的”
所以建议你还是 用 new version of oracle jdbc driver 的好,
另外,
如果你确实需要较大的长度,不妨数据库字段用LONG或大字段BLOB。
对于LONG ,应该要保证你的一个表里只有一列为LONG型,可以用setString(),和getString() 方法来操作。
对于BLOB 则用流来操作。
对于第一个问题,我想maoxuguang的解释比较符合我的情况。但是除了我能够catch之外,似乎找不到别的解决方法了。JVM的内存使用空间是否可以设置?
2.JVM内存空间在其启动可以通过参数设定,但根据运行情况会不断的申请或释放内存,很难控制。在一个简单的Application中出现这个问题,最好还是检查一下你的代码,看一看是否有可能有隐含的指向无用对象的句柄或者输入的数据可能过大。
3.wyalchemy的建议也有道理,JDBC的Driver和数据库要保持同样的版本,尤其是Oracle.
4.对于比较长的字符串,使用setLong和getLong,象LOB类型一样进行流操作,使用方法可以你看一看JDK API文档。用setString或getString写或读出的字符有限制(大小忘记了)。
谢谢 wyalchemy