Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/360.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java PreparedStatement Java.lang.OutOfMemoryError:超出GC开销限制_Java_Oracle_Jdbc_Prepared Statement - Fatal编程技术网

Java PreparedStatement Java.lang.OutOfMemoryError:超出GC开销限制

Java PreparedStatement Java.lang.OutOfMemoryError:超出GC开销限制,java,oracle,jdbc,prepared-statement,Java,Oracle,Jdbc,Prepared Statement,我知道类似的问题以前已经被问过很多次了,但是即使尝试了很多给出的解决方案,我仍然看到这个问题 我们的应用程序允许技术用户创建参数化原始SQL查询,以从数据库中提取数据,并将其下载到excel电子表格中 对于较小的数据集,这很好,但是,当文件大小开始接近10mb+时,我开始遇到这个问题 数据集可能有10万行或80-90mb大小。如果可能的话,我不想增加JVM堆的大小 希望我的代码中有一个我没有发现的明显错误。resultSet.next()循环似乎是问题的根源。有没有更有效的方法来写这个来停止占用

我知道类似的问题以前已经被问过很多次了,但是即使尝试了很多给出的解决方案,我仍然看到这个问题

我们的应用程序允许技术用户创建参数化原始SQL查询,以从数据库中提取数据,并将其下载到excel电子表格中

对于较小的数据集,这很好,但是,当文件大小开始接近10mb+时,我开始遇到这个问题

数据集可能有10万行或80-90mb大小。如果可能的话,我不想增加JVM堆的大小

希望我的代码中有一个我没有发现的明显错误。resultSet.next()循环似乎是问题的根源。有没有更有效的方法来写这个来停止占用堆空间

非常感谢您的帮助。谢谢

/*
*
 * query is a raw sql query that takes parameters (using Mybatis)
 * criteriaMap the arguments that we subsitute into the query
 * 
*/

public List<Map<String, Object>> queryForJsonWithoutMapping(final String query, final Map<String, Object> criteriaMap){

SqlSession sqlSession = getSqlSessionInstance();

    String sql = "";
    Connection connection = null;
    PreparedStatement pstmt = null;
    ResultSet resultSet = null;

    try {

        final Configuration configuration = getSqlSessionInstance().getConfiguration();

        SqlSourceBuilder builder = new SqlSourceBuilder(configuration);

        SqlSource src = builder.parse(query, Map.class, null);

        BoundSql boundSql = src.getBoundSql(criteriaMap);

        sql = boundSql.getSql();

        List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();

        connection = sqlSession.getConnection();

        pstmt = connection.prepareStatement(sql, java.sql.ResultSet.TYPE_FORWARD_ONLY,  java.sql.ResultSet.CONCUR_READ_ONLY);

        // this function subs the params into the preparedStatement query
        buildParams(parameterMappings, criteriaMap, pstmt);

        resultSet = pstmt.executeQuery();

        // the while loop inside this function is where things start to hang
        List<Map<String, Object>> results = getObjectFromResultSet(resultSet);

        return results;

    } catch (Exception e) {
        LOG.error(e.getMessage(), e);
        LOG.error(ExceptionUtils.getStackTrace(e));
        throw new IllegalStateException(sql + " " + e.getMessage(), e);
    } finally {
        try{
            connection.close();
            pstmt.close();
            resultSet.close();
        }catch (SQLException e){
            e.printStackTrace();
        }
        sqlSession.close();
    }

private List<Map<String, ?>> getEntitiesFromResultSet(ResultSet resultSet) throws SQLException {
        ArrayList<Map<String, ?>> entities = new ArrayList<>(resultSet.getFetchSize());
        int index = 0;
        Map<String, Object> jsonObject;
        while (resultSet.next()) {
            jsonObject = getEntityFromResultSet(resultSet);
            entities.add(index, jsonObject);
            index ++;
        }
        resultSet.close();
        return entities;
    }

    private List<Map<String, Object>> getObjectFromResultSet(ResultSet resultSet) throws SQLException {
        ArrayList<Map<String, Object>> entities = new ArrayList<>(resultSet.getFetchSize());
        int index = 0;
        Map<String, Object> jsonObject;
        while (resultSet.next()) {
            jsonObject = getEntityFromResultSet(resultSet);
            entities.add(index, jsonObject);
            index ++;
        }
        resultSet.close();
        return entities;
    }
/*
*
*查询是采用参数的原始sql查询(使用Mybatis)
*Criteria将我们替代的参数映射到查询中
* 
*/
JsonWithoutMapping的公共列表查询(最终字符串查询,最终映射标准映射){
SqlSession SqlSession=getSqlSessionInstance();
字符串sql=“”;
连接=空;
PreparedStatement pstmt=null;
ResultSet ResultSet=null;
试一试{
最终配置=getSqlSessionInstance().getConfiguration();
SqlSourceBuilder=新的SqlSourceBuilder(配置);
SqlSource src=builder.parse(查询,Map.class,null);
BoundSql BoundSql=src.getBoundSql(标准映射);
sql=boundSql.getSql();
List parameterMappings=boundSql.getParameterMappings();
connection=sqlSession.getConnection();
pstmt=connection.prepareStatement(sql,java.sql.ResultSet.TYPE_FORWARD_ONLY,java.sql.ResultSet.CONCUR_READ_ONLY);
//此函数将参数细分到preparedStatement查询中
buildParams(参数应用、标准地图、pstmt);
resultSet=pstmt.executeQuery();
//此函数中的while循环是开始挂起的地方
列表结果=getObjectFromResultSet(resultSet);
返回结果;
}捕获(例外e){
LOG.error(e.getMessage(),e);
LOG.error(ExceptionUtils.getStackTrace(e));
抛出新的非法状态异常(sql+“”+e.getMessage(),e);
}最后{
试一试{
connection.close();
pstmt.close();
resultSet.close();
}捕获(SQLE异常){
e、 printStackTrace();
}
sqlSession.close();
}
私有列表getEntitiesFromResultSet(ResultSet ResultSet)引发SQLException{
ArrayList entities=新的ArrayList(resultSet.getFetchSize());
int指数=0;
映射jsonObject;
while(resultSet.next()){
jsonObject=getEntityFromResultSet(resultSet);
添加(索引,jsonObject);
索引++;
}
resultSet.close();
返回实体;
}
私有列表getObjectFromResultSet(ResultSet ResultSet)引发SQLException{
ArrayList entities=新的ArrayList(resultSet.getFetchSize());
int指数=0;
映射jsonObject;
while(resultSet.next()){
jsonObject=getEntityFromResultSet(resultSet);
添加(索引,jsonObject);
索引++;
}
resultSet.close();
返回实体;
}

DB是oracle

在这种设计中,如果查询结果返回大量数据,您将不可避免地在某个时候耗尽内存,因为您正在将整个结果集加载到内存中。相反,您可以简单地声明getXXXFromResultSet API在数据量方面有一个阈值。对于每一行,您都计算其大小并决定是否可以将其添加到JSON文档中。如果已超过阈值,则停止并关闭结果集(这将取消服务器上的执行)。另一个选项可能涉及对结果进行流式处理,但这更为复杂。

在这种设计中,如果查询结果返回大量数据,您将不可避免地在某个时候耗尽内存,因为您正在将整个结果集加载到内存中。相反,您可以简单地声明getXXXFromResultSet API中有一个阈值数据量。对于每一行,计算其大小并决定是否可以将其添加到JSON文档中。如果超过阈值,则停止并关闭结果集(这将取消服务器上的执行)。另一个选项将涉及流式处理结果,但这更复杂。

一次性获取和处理DB表中的所有行是一个坏主意。您需要实现分页的一般想法,即一次读取和处理一页(n=页面大小行)

您的页面大小应该足够优化,这样您就不会有太多的数据库点击,同时也不会在内存中有太多的记录

Spring批处理API实现了这个概念

请参阅本文,了解有关JDBC分页的更多想法

除此之外,您不应该不断增加映射结果的大小。您需要循环刷新此映射


希望这能有所帮助!!

一次性获取和处理数据库表中的所有行是个坏主意。您需要实现分页的一般思想,即一次读取和处理一页(n=页面大小行)

您的页面大小应该足够优化,这样您就不会有太多的数据库点击,同时也不会在内存中有太多的记录

Spring批处理API实现了这个概念

请参阅本文,了解有关JDBC分页的更多想法

除此之外,您不应该不断增加映射结果的大小。您需要循环刷新此映射

希望这有帮助!!

看起来像是传统的“rea”