java - Oracle驱动在PreparedStatement中setFetchSize时出现OutOfMemoryError

标签 java oracle jdbc prepared-statement ojdbc

我有这段代码,这段代码基本上在 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)

知道为什么在 Oracle 中会发生这种情况吗?在数据库级别有什么事情要做吗?

最佳答案

与您的想法相反,setFetchSize 不限制检索的记录数量,它确定(或提示)驱动程序应预取和缓存多少记录。 MySQL 是个异常(exception),它总是预取所有记录,除非您将获取大小设置为 Integer.MIN_VALUE

驱动程序只是简单地检索了太多行,以至于内存耗尽。

关于java - Oracle驱动在PreparedStatement中setFetchSize时出现OutOfMemoryError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21159263/

相关文章:

oracle - sqoop和oracle问题?

sql - 如何修复 Ora-01427 单行子查询在 select 中返回多行?

Java 访问修饰符最佳实践

java - 如何使用一个 Singleton 并行执行 2 个浏览器(Chrome 和 Firefox)而不会出现错误?是否可以?

java - 您可以在自动配置的 Spring Boot H2 测试数据库上设置兼容模式吗?

Oracle - 如何删除空格?

java - Tomcat 8.5 JDBC Realm 带有摘要加盐密码 : authentication fails

ssl - 如何在谷歌应用程序脚本中使用 SSL 连接到数据库?

java - Spring @Transactional 注释被忽略

java - 在线程中使用同步