如何在Spring JDBC ResultSetExtractor中检查ResultSet是否为空?

And*_*niy 0 java spring jdbc java-8

似乎ResultSet空的标准检查在Spring的JDBC中不起作用ResultSetExtractor。我通过以下方式使用它:

    return jdbcTemplate.query(sql, ps -> {
        ps.setLong(1, fooParam1);
        ps.setLong(2, fooParam2);
    }, rs -> {
        return rs.getLong(1);
    });
Run Code Online (Sandbox Code Playgroud)

那么ResultSet在这种模式下检查空度的正确方法是什么?

Hol*_*ger 5

接口的作用似乎有些混乱,我看了一些教程做错了。接口RowMapperRowCallbackHandler负责提供相应的值。每行产生一个副作用。

因此,它们不负责调用,next()因为框架将负责前进到下一行,并且不会调用回调,一旦next()返回false,即使前进到第一行(在这种情况下ResultSet为空)也可能发生。在后一种情况下,query(… RowMapper<T>)将在List不调用RowMapper和的情况下返回空值,并且query(… RowCallbackHandler)只会执行任何操作。

相反,ResultSetExtractor负责处理整个 ResultSet,包括next()适当调用。因此,您的问题的前提(“ ...的每个呼叫extractData都会给我新的一行。”)是错误的。所有JDBC操作的标准行为ResultSet是在第一行之前返回一个being,以便第一次next()调用会将当前行指针移动到第一行,或者false如果ResultSetas为空则返回。因此,如果您期望最多一行,那么查询应该看起来像

return jdbcTemplate.query(sql, ps -> {
        ps.setLong(1, fooParam1);
        ps.setLong(2, fooParam2);
   }, rs -> rs.next()? rs.getLong(1): null);
Run Code Online (Sandbox Code Playgroud)

编辑:此解决方案进行了测试,并且可以在标准MySQLPostgresql实例/ Andremoniy /上正常工作。

编辑2:此解决方案绝对正确,并且可以在任何地方正常工作。但是应该注意,类中有两种不同的方法JdbcTemplate

  1. public <T> T query(String sql, PreparedStatementSetter pss, ResultSetExtractor<T> rse) -这是在本例中使用,它返回0rs.getRows()始终,确实如此。提供的解决方案对于这种情况是正确的。

  2. public void query(String sql, PreparedStatementSetter pss, RowCallbackHandler rch) 它具有另一种类型的3rd参数,以及类似的代码:

    jdbcTemplate.query(sql, ps -> { ps.setLong(1, fooParam1); ps.setLong(2, fooParam2); }, rs -> { System.out.println(rs.getRow()); });

将以不同的方式工作:rs.getRow()将返回处理行的数量,并且如果不存在行,processRow则将永远不会调用方法(第二个方法引起了我的困惑)。/ 安德鲁尼 /

  • 当然,它每次都为您提供** new **`ResultSet`。如何证明已在`ResultSet`上调用过`next()`?它实际上证明了我所说的内容,该回调负责*处理整个结果集*,因为下次调用它时,它将收到一个新的。 (2认同)
  • 显然,您混淆了* row *和`RowSet`。“行集”可以具有任意数量的行,并且“为每行一次”调用“行映射器”时,换句话说,每次调用都会获得新的“行”,而“结果集提取器”则不会。“ ResultSetExtractor”(按结果一次)被调用,由一个新的“ ResultSet”表示。由于每个调用代表一个全新的查询,因此对上一个查询的“ ResultSet”(同时已关闭)调用“ next()”的频率(或是否)无关紧要。 (2认同)