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()
方法有多少可信度。 JdbcTemplate
在 Statement
上调用 setFetchSize()
,并假设 JDBC 驱动程序会用它做正确的事情,包括将它传播到所有 ResultSet
对象。在这种情况下,Oracle JDBC 驱动程序似乎不是。
您从这两种方法获得不同行为的原因是执行简单的SELECT
到JdbcTemplate
是简单的 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 对象