ResultSet-Ausnahme - vor dem Start der Ergebnismenge

76

Ich habe Probleme beim Abrufen von Daten von einem ResultSetObjekt. Hier ist mein Code:

    String sql = "SELECT type FROM node WHERE nid = ?";
    PreparedStatement prep = conn.prepareStatement(sql);
    int meetNID = Integer.parseInt(node.get(BoutField.field_meet_nid));
    prep.setInt(1, meetNID);

    ResultSet result = prep.executeQuery();
    result.beforeFirst();
    String foundType = result.getString(1);

    if (! foundType.equals("meet")) {
        throw new IllegalArgumentException(String.format("Node %d must be of type 'meet', but was %s", meetNID, foundType));
    }

Die Fehlersuche:

Exception in thread "main" java.sql.SQLException: Before start of result set
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1072)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:986)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:981)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:926)
    at com.mysql.jdbc.ResultSetImpl.checkRowPos(ResultSetImpl.java:841)
    at com.mysql.jdbc.ResultSetImpl.getStringInternal(ResultSetImpl.java:5656)
    at com.mysql.jdbc.ResultSetImpl.getString(ResultSetImpl.java:5576)
    at nth.cumf3.nodeImport.Validator.validate(Validator.java:43)
    at nth.cumf3.nodeImport.Main.main(Main.java:38)

Was mache ich hier falsch?

Nick Heiner
quelle

Antworten:

164

Grundsätzlich positionieren Sie den Cursor vor der ersten Zeile und fordern dann Daten an. Sie müssen den Cursor in die erste Zeile bewegen.

 result.next();
 String foundType = result.getString(1);

Es ist üblich, dies in einer if-Anweisung oder einer Schleife zu tun.

if(result.next()){
   foundType = result.getString(1);
}
Vincent Ramdhanie
quelle
Wäre es sicher, result.next () oder result.first () zu verwenden, wenn eine einfache COUNT-Abfrage ausgeführt wird, da sie niemals null sein sollte und immer nur ein Ergebnis sein wird.
jDub9
2
Vielleicht result.first()für dieses Szenario verwenden.
Vincent Ramdhanie
Es stellt sich heraus, dass zuerst ein Boolescher Wert zurückgegeben wird, nicht das erste Ergebnis, wie ich ursprünglich dachte. Scheint, als könnte ich dies nicht in einer Zeile tun, wie ich es versucht habe, und musste die obige Logik verwenden, um die Abfrage auszuführen, dann weiter und dann getInt (1). Naja.
jDub9
11

Jede Antwort verwendet .next()oder verwendet .beforeFirst()und dann .next(). Aber warum nicht das:

result.first();

Sie setzen also einfach den Zeiger auf den ersten Datensatz und gehen von dort aus. Es ist seit Java 1.2 verfügbar und ich wollte dies nur für jeden erwähnen, der ResultSetvon einem bestimmten Datensatz existiert.

MmynameStackflow
quelle
Die Verwendung von first()erfordert eine scrollbare Ergebnismenge. Die API erfordert, dass eine Ausnahme ausgelöst wird, wenn die Ergebnismenge lautet TYPE_FORWARD_ONLY.
Mark Rotteveel
6

Sie müssen eine result.next () ausführen, bevor Sie auf das Ergebnis zugreifen können. Es ist eine sehr verbreitete Redewendung

ResultSet rs = stmt.executeQuery();
while (rs.next())
{
   int foo = rs.getInt(1);
   ...
}
Paul Tomblin
quelle
3

Sie müssen aufrufen, next()bevor Sie Werte aus der ersten Zeile lesen können. beforeFirstsetzt den Cursor vor die erste Zeile, sodass keine Daten zu lesen sind.

Dan
quelle
2

Es ist besser, wenn Sie eine Klasse erstellen, die alle Abfragemethoden einschließlich in einem anderen Paket enthält. Anstatt den gesamten Prozess in jeder Klasse einzugeben, rufen Sie einfach die Methode aus dieser Klasse auf.

Pedro
quelle
1

Sie müssen den Zeiger in die erste Zeile bewegen, bevor Sie nach Daten fragen:

result.beforeFirst();
result.next();
String foundType = result.getString(1);
Ryanprayogo
quelle