org.postgresql.util.PSQLException: ResultSet not positioned properly, perhaps you need to call next. は、ResultSet のカーソル(今読んでいる行の印)が、行の上にないときに getString() などで値を読もうとしたときのエラーです。 メッセージのとおり、多くは rs.next() を呼んでいないか、呼んだ結果(false)を確かめていないのが原因です。

原因 直し方
next() を呼ぶ前に読んだ 最初に rs.next() を呼ぶ
0件なのに読んだ(next() が false) if (rs.next()) で確かめてから読む
ループ(while (rs.next()))が終わったあとに読んだ ループの中で読む

確認環境:OpenJDK 21、PostgreSQL 16.15 と pgJDBC 42.7.2、MySQL 8.0.46 と MariaDB Connector/J 2.7.6 で再現しました(確認日 2026年10月11日)。

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「ResultSet not positioned properlyの直し方|JDBC」

カーソルの位置

             ┌────────────────┐
(最初)→     │ 最初の行の前    │  ← executeQuery の直後。ここで読むとエラー
             ├────────────────┤
next() → true│ 1行目 山田      │  ← 読める
next() → true│ 2行目 佐藤      │  ← 読める
             ├────────────────┤
next() → false│ 最後の行の後   │  ← ここで読むとエラー
             └────────────────┘

Java の公式ドキュメント(ResultSet)では、カーソルは最初は最初の行の前にあり、next() で次の行に進み、行が無くなると false を返して最後の行の後に置かれると説明されています。ResultSet が読めるのは、next() が true を返したあとだけです。

再現

書いたコード PostgreSQL(pgJDBC 42.7.2) MySQL(MariaDB Connector/J 2.7.6)
next() を呼ばずに rs.getString(1) ResultSet not positioned properly, perhaps you need to call next. Current position is before the first row
0件の SQL で rs.next()(false)のあと getString 同じ Current position is after the last row
while (rs.next()) {} のあと getString 同じ Current position is after the last row
rs.next() ? rs.getString(1) : "(該当なし)"(0件) (該当なし) (該当なし)

PostgreSQL のドライバは、「最初の行の前」でも「最後の行の後」でも、同じメッセージでした。 MariaDB Connector/J は、どちら側かをメッセージで区別していました。

よくある形①:1件だけ取るときに next() を忘れる

ResultSet rs = ps.executeQuery();      // SELECT name FROM j_users WHERE id = ?
String name = rs.getString("name");    // ← next() を呼んでいない

1件しか返らない SQL でも、next() を1回呼んでから読みます。

try (ResultSet rs = ps.executeQuery()) {
    if (rs.next()) {
        return Optional.of(rs.getString("name"));
    }
    return Optional.empty();           // 0件
}

よくある形②:0件のときを考えていない

rs.next();                             // 戻り値を見ていない
String name = rs.getString("name");    // ← 0件ならエラー

テストのデータでは必ず1件あるので動き、本番で該当なしのときに初めてエラーになる形です。next() の戻り値は、必ず if か while で使います。

0件のときの扱い 書き方
「無い」ことがふつうにある Optional.empty()・null を返す
「無い」のはおかしい(データの不整合) 分かりやすいメッセージで例外を投げる("ユーザーが見つかりません: id=" + id)

よくある形③:ループの後で読む

String last = null;
while (rs.next()) {
    // 何もしない、または途中の処理だけ
}
last = rs.getString("name");           // ← ループが終わった時点で「最後の行の後」

while (rs.next()) のループが終わったとき、カーソルは最後の行の後にあります。 最後の行の値が欲しいなら、ループの中で変数に入れておきます。

String last = null;
while (rs.next()) {
    last = rs.getString("name");       // 毎回上書き → ループ後は最後の行の値
}

件数を数えたいとき

ResultSet を最後まで読んで数えるより、SQL の COUNT(*) を使います。

try (ResultSet rs = st.executeQuery("SELECT COUNT(*) FROM j_users")) {
    rs.next();                         // COUNT(*) は必ず1行返る
    int count = rs.getInt(1);
}

COUNT(*) は該当が0件でも、0 という値の1行を返すので、next() は true になります。

確認の手順(チェックリスト)

順番 確認すること 方法
1 getString の前に next() があるか 1件取得のコード
2 next() の戻り値を使っているか if (rs.next())・while (rs.next())
3 0件のときの動き 該当なしの ID で試す
4 ループの外で読んでいないか while の } のあと
5 ResultSet が閉じられていないか 別のエラー(This ResultSet is closed)

よくある質問

Q. 「This ResultSet is closed」は同じ原因ですか。 A. 違います。ResultSet そのものが閉じられたときのエラーです。関連記事の「ResultSet closedの直し方|Operation not allowed」で扱っています。

Q. 列の番号を間違えたときのエラーは。 A. The column index is out of range などになります。関連記事の「Parameter index out of rangeの直し方|JDBC」で扱っています。

まとめ

  • カーソルが行の上にないときに、値を読んだエラー
  • 最初は「最初の行の前」。next() が true を返してから読む
  • 0件のとき next() は false。if (rs.next()) で確かめる
  • ループの後は「最後の行の後」。必要な値はループの中で取っておく
  • 件数は COUNT(*)(0件でも1行返る)

参考・出典

確認日はいずれも 2026年10月11日です。

  • Java SE 21 API「ResultSet」:https://docs.oracle.com/en/java/javase/21/docs/api/java.sql/java/sql/ResultSet.html

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「ResultSet not positioned properlyの直し方|JDBC」

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?