为什么我的存储过程 return 在堆 space 之外只有一个整数 return 代码 运行?

Why is my stored procedure that returns only a single integer return code running out of heap space?

我正在重构一些以前 java 5 & JDBC 调用的代码,以使用 java 8 & Spring 4。对于我创建的存储过程调用class 扩展 org.springframework.jdbc.object.StoredProcedure 的元素。构造函数设置参数,execute 将 2 个参数放在输入 map 上,并使用输入参数 map.

在 super class 上调用 execute

存储过程 运行 有一段时间了,但它 return 唯一的东西是单个数字 return 代码。它调用其他存储过程在数据库中移动数据。但似乎我的调用正在泄漏内存,因为如果我 运行 针对足够大的数据集,它会开始抛出 java.lang.OutOfMemoryError: java heap space.

关键是存储过程没有变化,旧代码可以处理使用相同数量的数据调用存储过程而不会 运行 内存不足。我猜我在 StoredProcedure class 中遗漏或设置了一些东西导致了这个问题,但我不确定是什么,因为我对这个框架还是很陌生。

存储过程class:

public class Extract extends StoredProcedure {
    private static final String PARAM_1 = "@PARAM_1";
    private static final String PARAM_2 = "@PARAM_2";

    public Extract(DataSource dataSource, String sprocName) {
        super(dataSource, sprocName);
        declareParameter(new SqlOutParameter(Constants.STORED_PROC_RETURN_CODE, Types.VARCHAR, null,
            new SqlReturnType() {
                public Object getTypeValue(CallableStatement cs, int paramIndex, int sqlType, String typeName)
                        throws SQLException {
                    final Integer retCode = cs.getInt(paramIndex);
                    return retCode;
                }
            }));
        declareParameter(new SqlParameter(PARAM_1, Types.NUMERIC));
        declareParameter(new SqlParameter(PARAM_2, Types.NUMERIC));
        setFunction(true);
        compile();
    }

    public Map<String, Object> execute(Util util, CustomLogger logger)     {
        String params = util.EXTRACT_PARAMS;
        String arr[] = params.split(",");
        logger.writeLine("Extract SP Params are " + arr[0] + ":" + arr[1]);
        int firstParam = Integer.parseInt(arr[0]);
        int secondParam = Integer.parseInt(arr[1]);
        Map<String, Object> inputs = new HashMap<String, Object>();
        inputs.put(PARAM_1, firstParam);
        inputs.put(PARAM_2, secondParam);
        return super.execute(inputs);
    }
}

调用存储过程的代码:

public int executeExtractSP() throws Exception {
      int returnCode = -1;
      try {
            Extract extractSP = new Extract(getDataSource(), util.EXTRACT_SP);
            long t1 = System.currentTimeMillis();
            returnCode = (Integer) extractSP.execute(util, customLogger).get(Constants.STORED_PROC_RETURN_CODE);
            long t2 = System.currentTimeMillis() - t1;
            customLogger.writeLine("Extract procedure finished running in " + t2 + " milliseconds, return code is " + returnCode);
      } catch (Exception ex) {
                  throw ex;
      }
      return returnCode;
}

重构前调用存储过程的旧代码:

callStm = con.prepareCall(util.EXTRACT_SP);
callStm.registerOutParameter(1, java.sql.Types.INTEGER);
callStm.setInt(2, firstParam);
callStm.setInt(3, secondParam);
long t1 = System.currentTimeMillis();
boolean flag = callStm.execute();
long t2 = System.currentTimeMillis() - t1;
returnCode = callStm.getInt(1);
logger.writeLine("Extract procedure finished running in " + t2 + " milliseconds, return code is " + returnCode);

我得到的内存错误堆栈跟踪:

Thu Dec 17 20:48:56 2015: Extract SP Params are 1:2
Thu Dec 17 21:05:16 2015: java.lang.OutOfMemoryError: Java heap space
        at java.lang.String.<init>(String.java:469)
        at org.springframework.jdbc.core.JdbcTemplate.extractReturnedResults(JdbcTemplate.java:1193)
        at org.springframework.jdbc.core.JdbcTemplate.doInCallableStatement(JdbcTemplate.java:1141)
        at org.springframework.jdbc.core.JdbcTemplate.doInCallableStatement(JdbcTemplate.java:1130)
        at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:1078)
        at org.springframework.jdbc.core.JdbcTemplate.call(JdbcTemplate.java:1130)
        at org.springframework.jdbc.object.StoredProcedure.execute(StoredProcedure.java:142)
        at com.company.job.storedprocs.Extract.execute(Extract.java:49)
        at com.company.job.utils.DBUtil.executeExtractSP(DBUtil.java:456)
        at com.company.job.extract.JobExtract.processExtract(JobExtract.java:376)
        at com.company.job.Process.main(Process.java:60)
Thu Dec 17 21:05:16 2015: Exiting with code of 8

参数的SQL类型为varchar。我认为这应该是 Types.INTEGER.

此外,您正在使用 SqlReturnType 将其转换为整数。我觉得没必要。

检查从扩展 StoredProcedure 的提取 class 中的执行行中拉出的映射显示了一个包含超过 30000 个条目的映射,包括来自存储过程的所有消息和更新计数条目调用的存储过程进行的每次更新,以及调用初始存储过程的辅助存储过程。

我需要添加的方法是在调用执行方法之前,跳过未声明的结果。这将地图减少到只有 1 个条目,即我正在寻找的 return 代码编号。

super.getJdbcTemplate().setSkipUndeclaredResults(true);