- データベース
ResultSet not positioned properlyの直し方|JDBC
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期連続の黒字決算。