SimpleJdbcCall 忽略 JdbcTemplate 获取大小

Posted

技术标签:

【中文标题】SimpleJdbcCall 忽略 JdbcTemplate 获取大小【英文标题】:SimpleJdbcCall ignoring JdbcTemplate fetch size 【发布时间】:2011-01-25 07:44:55 【问题描述】:

我们通过 Spring SimpleJdbcCall 调用 pl/sql 存储过程,在 JdbcTemplate 上设置的 fetchsize 被 SimpleJdbcCall 忽略。尽管我们已将 jdbctemplate fetchsize 设置为 200,但 rowmapper 结果集获取大小设置为 10。知道为什么会发生这种情况以及如何解决它吗?

已经在下面的代码 sn-p 中的 rowmapper 中打印了结果集的 fetchsize - 一旦它是 200,其他时候它是 10,即使我在这两种情况下都使用相同的 JdbcTemplate。

这种通过 jdbctemplate 直接执行在行映射器中返回 fetchsize 200

    jdbcTemplate = new JdbcTemplate(ds);
    jdbcTemplate.setResultsMapCaseInsensitive(true);
    jdbcTemplate.setFetchSize(200);

    List temp = jdbcTemplate.query("select 1 from dual", new ParameterizedRowMapper() 
        public Object mapRow(ResultSet resultSet, int i) throws SQLException 
            System.out.println("Direct template : " + resultSet.getFetchSize());
            return new String(resultSet.getString(1));
        
    );

通过 SimpleJdbcCall 执行的这个执行总是在 rowmapper 中返回 10 的 fetchsize

jdbcCall = new SimpleJdbcCall(jdbcTemplate).withSchemaName(schemaName)
                .withCatalogName(catalogName).withProcedureName(functionName);
jdbcCall.returningResultSet((String) outItValues.next(), new        ParameterizedRowMapper<Map<String, Object>>() 
                public Map<String, Object> mapRow(ResultSet rs, int row) throws SQLException 
                   System.out.println("Through simplejdbccall " + rs.getFetchSize());
                    return extractRS(rs, row);
                
            );
outputList = (List<Map<String, Object>>) jdbcCall.executeObject(List.class, inParam);

【问题讨论】:

【参考方案1】:

我不确定ResultSet 上的getFetchSize() 方法有多少可信度。 JdbcTemplateStatement 上调用 setFetchSize(),并假设 JDBC 驱动程序会用它做正确的事情,包括将它传播到所有 ResultSet 对象。在这种情况下,Oracle JDBC 驱动程序似乎不是。

您从这两种方法获得不同行为的原因是执行简单的SELECTJdbcTemplate 是简单的 JDBC,而您从SimpleJdbcCall 返回的ResultSet 是作为调用的 OUT 参数获得的.后者更复杂,似乎信息正在丢失。

作为一种解决方法,您是否尝试过自己致电ResultSet.setFetchSize()?它可能行不通,但值得一试。您也可以向http://jira.springsource.org/ 提交问题,看看他们是否认为 Spring 的 JDBC 层可以透明地解决它。

【讨论】:

在 RowMapper 类的 mapRow 方法中设置 ResultSet 的获取大小对我来说是一种享受。谢谢大佬! mapRow 为结果集中的每一行调用,它不是正确的位置。应该在调用 rs.next() 之前设置获取大小【参考方案2】:

如果你想限制 Oracle 返回的行数,你应该使用子选择查询并像这样指定开始和停止行号:

SELECT * FROM (SELECT ROWNUM as id, demo.* FROM DEMO_TABLE demo)
WHERE id >= startRowNumber AND id <= stopRowNumber; 

如果您不想要任何 Oracle 特定代码,则应考虑使用 JPA 而不是 JDBC:

Query selectQuery = entityManager.createQuery(queryString);
selectQuery.setMaxResults(maxNumberOfElements);
selectQuery.setFirstResult(startRowNumber);
List demoList = entityManager.getResultList(queryString);

【讨论】:

SimpleJdbcCall 用于调用存储的过程和函数,客户端对 sql 不可见。【参考方案3】:

不是一个直接的答案,但我认为这是一件有用的事情。当您手动创建 Spring 类的对象时,大多数人往往会忘记调用 afterPropertiesSet() 方法(由 Spring 调用以执行任何初始化)。

我检查了 jdbcTemplate.afterPropertiesSet() 它似乎只设置了异常转换器和数据源。

【讨论】:

以上是关于SimpleJdbcCall 忽略 JdbcTemplate 获取大小的主要内容,如果未能解决你的问题,请参考以下文章

SimpleJdbcCall - 执行 oracle 程序时出错

将 simplejdbccall 结果集转换为 java 对象

SimpleJDBCCall 类参数传递

带有 JdbcTemplate 自动装配的 SimpleJdbcCall 的 Junit

SimpleJdbcCall 找不到存储过程

如何使用 simpleJdbcCall 在存储过程中获取 XML 输出参数