- 締切済み
do - while文
こんにちは、tomokooです。 下記の様にソースを書きました。 rsはResultSetです。 ---------------------------- while(条件A){ 処理; rs.next(); } while(rs.next()){ 処理; } ---------------------------- うまくプログラムは動いたのですが 結果を見て1行飛ばされることに気づきました。 だから ---------------------------- while(条件A){ 処理; rs.next(); } do{ 処理; }while(rs.next()}; ---------------------------- としたところ、処理の中の rs.getString(i); //iは初期化済み で落ちてしまいます。 whileでよくてdo-whileでだめなことってあるんですか? 結構困ってます。 ご存知の方はよろしくお願いします。
- みんなの回答 (3)
- 専門家の回答
みんなの回答
- hameggs
- ベストアンサー率38% (8/21)
amajunさんのおっしゃる通りです。 識者の方々におこられるのを承知で簡単に言うと・・・・ 1:データベースのカーソルは最初は一番最初の行の真上にいる。 ↓ 2:next()をおこなうと、カーソルが一つ下に移動する ↓ 3:行が存在していればtureが返り、rsが値を取得できる って感じに考えてはどうでしょ(・w・? (あぅ、怒られそうだ・・・^^;)
- m_hagizo
- ベストアンサー率65% (31/47)
do{ 処理; } while(rs.next()); とした場合、rs.next()の評価を行う前に「処理」が実行されることに注意してください。つまり、最終レコードになったときに、最終レコードであることの判定が後に来てしまうために、rs.getString(i)で落ちている、ということです。 このロジックでこれを回避するためには、Statementを作るときに、「スクロール可能な」状態にしておく必要があるでしょう。修正すると、こんな感じです。 // スクロール可能なカーソルを作る Statement stmt = connection.createStatement( ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); : : while(条件A){ 処理; rs.next(); } rs.beforeFirst(); // カーソルを先頭行の手前に移動する while(rs.next()){ 処理; }
do-whileでは、ループ中の処理を実行した後に条件判断されます。つまり、どんな条件であろうが処理は必ず1回は実行されます。だからループの最初の1回では「条件に合わないが処理してしまう」ことがありえます。 また、ResultSetの初期状態では、どのレコードも指していません。この状態でrs.getString()すると例外になります。rs.next()を実行して(trueが返れば)初めて1番目のレコードを指すようになり、getString()できるようになります。 以上から、do-whileの中のrs.getString()で例外が起こり得ます。 というわけで、すなおに while(rs.next()) { 処理 } と書くのがよいです。条件Aが絡むのであれば // 条件Aが満たされなければ、以降のレコードは無視する while(条件A && rs.next()) { 処理 } または // 条件Aを満たすレコードだけを拾う while(rs.next()) { if(条件A) { 処理 } } となるでしょう。
お礼
みなさん、ありがとうございます。 問題解決しました! 問題は別のところにありました。。。 どこがいけなかったかというと、while(条件A)文の最後のデータαとdo文の最初のデータβは同じで、その同じ行同じ列のデータをそれぞれwhile(条件A)文とdo文でgetStringしてたんです! 同じ行の同じ列を2度getStringすると落ちるんですねー。 知らなかった。。。 そんなこんなでロジックを組みなおし、すっかり動くようになりました。 どうもお騒がせしました&ありがとうございました!