2016-05-25 5 views
0

ResultSetの標準チェックが空のJDBCのJDBC ResultSetExtractorでは動作しないようです。私は、次の方法でそれを使用します。Spring JDBC ResultSetExtractor内の空のResultSetを確認するには?

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

だから、正しい方法は、このようなパターンでResultSet虚しさを確認する何ですか?

+0

なぜrs.hasNext()を使用しないのですか? –

+0

@RadhakrishnaSharmaGorenta 'ResultSet'クラスにそのようなメソッドがありません – Andremoniy

+0

もちろん、最初のパラメータ' sql'は既に 'next()'を呼び出す 'PreparedStatementCreator'実装である可能性がありますが、あなたの質問にコードを載せずにAPIに矛盾する何かを使っているときは、 'List'を返す' query'オーバーロードの1つで設定を試すことができます。最初の行が含まれているか不足していますか?すでに実証済みのように、Springは 'resultSetExtractor'の実装で' next() 'を呼び出します。 – Holger

答えて

4

インターフェイスの役割が混乱しているようですが、チュートリアルでは間違ったことがあります。インターフェイスRowMapperおよびRowCallbackHandlerは、値を提供する責任があります。行ごとに副作用を起こします。

したがって、それらは次の行に進むと、コールバックを呼び出すことではないの世話をするフレームワークとしてnext()を呼び出すための責任を負うものではなく、一度next()は、最初の行に進むときにも起こり得るfalseを、返された場合にResultSetは空です。後者の場合、query(… RowMapper<T>)は、RowMapperを呼び出さずに空のListを返し、単にquery(… RowCallbackHandler)は何もしません。対照的に

ResultSetExtractor適切next()を呼び出す含む全体ResultSetを処理する責任があります。だからあなたの質問の前提( "... の各呼び出しは私に新しい行を与えます。")が間違っています。すべてのJDBC操作の標準的な動作は、最初の行の前にあるResultSetを返すことで、最初のnext()呼び出しは現在の行ポインタを最初の行に移動するか、ResultSetが空の場合はfalseを返します。このソリューションはテストの結果、標準MySQLPostgresqlインスタンス/ Andremoniy /上で正常に動作します:あなたは最大1つの行を期待するのであれば、あなたのクエリは、むしろEDIT

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

のようになります。

EDIT-2:このソリューションは、どこでも正しく動作し、正しく動作します。それがこの例で使用され、それは確かに、常にrs.getRows()ため0返す -

  1. public <T> T query(String sql, PreparedStatementSetter pss, ResultSetExtractor<T> rse):しかし、それは、JdbcTemplateクラスに2つの異なる方法があることに気づいたでなければなりません。この場合、提供された解決策は正しいです。

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

異なる動作をします:rs.getRow()処理行の数を返し、何行が存在しない場合、processRow方法を別の3番目のパラメータの種類、及び同様のコードを有する

  • public void query(String sql, PreparedStatementSetter pss, RowCallbackHandler rch)呼び出されることはありません(この2番目の方法は私の混乱の原因となります)。/Andremoniy/

  • +0

    私は申し訳ありませんが、私はあなたに同意できません。 'ResultSetExractor'は、新しい' ResultSet'オブジェクトのたびに 'extractData'を返します。したがって、内部的に' next'を呼び出します。さらに、 'extractData()'の中で 'next()'を何回か呼び出すと、前進し、キュー結果全体の処理が中断されます。あなたの評価に関して私はあなたの答えを下降させませんが、間違っているようです。残念です – Andremoniy

    +2

    もちろん、新しい** ResultSetを提供します。それは 'next()'が 'ResultSet'で呼び出されたことをどのように証明しますか?これは実際に私が言ったことを証明しています。このコールバックは、次回コールされるときに結果セット全体を処理する責任があります*新しいコールを受け取ります。 – Holger

    +2

    あなたは* rows *と 'RowSet'を混同しているようです。 'RowSet'は任意の数の行を持つことができ、' RowMapper'は各行*に対して1回呼び出されます。つまり、各呼び出しで新しい**行**を取得しますが、ResultSetExtractorはありません。 'ResultSetExtractor'は新しく' ResultSet'で表される結果*ごとに1回*呼び出されます。それぞれの呼び出しはまったく新しいクエリを表しているので、以前のクエリの 'ResultSet'(その間に閉じられていた)で' next() 'を呼び出す頻度や重要性は問われません。 – Holger

    関連する問題