【发布时间】:2014-01-16 10:34:19
【问题描述】:
我有这段代码,这段代码基本上在PreparedStatement中设置了限制,以避免加载整个表数据。
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
pstmt = con.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
if (getDataSheet().isPagingEnabled()) {
pstmt.setFetchSize(getDataSheet().getPageSize() + 1);
}
if (getDataSheet().isDisableTotalRowsCount() && maxRecords >= 0) {
if (getDataSheet().isPagingEnabled()) {
pstmt.setMaxRows(getCurrentPageSize());
} else {
pstmt.setMaxRows(maxRecords);
}
}
//the rest of code.
} catch(Exception ex) {
//handle exception
}
此代码适用于所有数据库供应商,除了 Oracle 驱动程序中的一种情况,如果我在 PreparedStatement 中使用 setFetchSize,并且页面大小超过 20000,驱动程序会抛出 OutOfMemoryError
Caused by: java.lang.OutOfMemoryError: Java heap space
at oracle.jdbc.driver.PhysicalConnection.getCharBuffer(PhysicalConnection.java:7018)
at oracle.jdbc.driver.OracleStatement.prepareAccessors(OracleStatement.java:907)
at oracle.jdbc.driver.T4CTTIdcb.receiveCommon(T4CTTIdcb.java:261)
at oracle.jdbc.driver.T4CTTIdcb.receive(T4CTTIdcb.java:127)
at oracle.jdbc.driver.T4C8Oall.receive(T4C8Oall.java:992)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:194)
at oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:791)
at oracle.jdbc.driver.T4CPreparedStatement.executeMaybeDescribe(T4CPreparedStatement.java:866)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1186)
at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3387)
at oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:3431)
at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeQuery(OraclePreparedStatementWrapper.java:1203)
知道为什么甲骨文会发生这种情况吗?在数据库级别有什么想法吗? 提前致谢。
【问题讨论】:
-
为什么要一次性获取 20k 行? fetch size 的用途是获取一批行,对其进行处理,然后再获取另一批——从而限制了到数据库的往返次数。它不是意味着在一个大规模的内存批处理中获取所有行。
标签: java oracle jdbc prepared-statement ojdbc