Ngoại lệ ResultSet - trước khi bắt đầu tập kết quả


78

Tôi đang gặp sự cố khi lấy dữ liệu từ một ResultSetđối tượng. Đây là mã của tôi:

    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));
    }

Dấu vết lỗi:

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)

Tôi làm gì sai ở đây?

Câu trả lời:


167

Về cơ bản, bạn đang định vị con trỏ trước hàng đầu tiên và sau đó yêu cầu dữ liệu. Bạn cần di chuyển con trỏ đến hàng đầu tiên.

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

Thông thường thực hiện điều này trong câu lệnh if hoặc vòng lặp.

if(result.next()){
   foundType = result.getString(1);
}

Có an toàn không khi sử dụng result.next () hoặc result.first () khi thực hiện một truy vấn COUNT đơn giản vì nó không bao giờ được rỗng và sẽ chỉ là 1 kết quả.
jDub9

2
Có thể sử dụng result.first()cho kịch bản này.
Vincent Ramdhanie

Hóa ra đầu tiên trả về một Boolean không phải là kết quả đầu tiên như tôi nghĩ ban đầu. Có vẻ như tôi không thể làm điều này trên 1 dòng như tôi đang cố gắng làm và phải sử dụng logic trên để thực hiện truy vấn, sau đó tiếp theo, rồi getInt (1). Ồ tốt.
jDub9

11

Mọi câu trả lời đều sử dụng .next()hoặc sử dụng .beforeFirst()và sau đó .next(). Nhưng tại sao không phải cái này:

result.first();

Vì vậy, bạn chỉ cần đặt con trỏ đến bản ghi đầu tiên và đi từ đó. Nó có sẵn kể từ java 1.2 và tôi chỉ muốn đề cập đến điều này cho bất kỳ ai có ResultSettồn tại một bản ghi cụ thể.


Việc sử dụng first()yêu cầu một tập hợp kết quả có thể cuộn được. API yêu cầu rằng một ngoại lệ được ném ra nếu tập kết quả là TYPE_FORWARD_ONLY.
Mark Rotteveel

6

Bạn phải thực hiện một result.next () trước khi có thể truy cập kết quả. Đó là một thành ngữ rất phổ biến để làm

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

3

Bạn phải gọi next()trước khi có thể bắt đầu đọc các giá trị từ hàng đầu tiên. beforeFirstđặt con trỏ trước hàng đầu tiên, vì vậy không có dữ liệu nào để đọc.


2

Sẽ tốt hơn nếu bạn tạo một lớp có tất cả các phương thức truy vấn, bao gồm, trong một gói khác, vì vậy thay vì nhập tất cả quá trình trong mọi lớp, bạn chỉ cần gọi phương thức từ lớp đó.


1

Bạn cần di chuyển con trỏ đến hàng đầu tiên, trước khi yêu cầu dữ liệu:

result.beforeFirst();
result.next();
String foundType = result.getString(1);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.