2011-01-12 38 views
5

Thay vì có các truy vấn SQL phức tạp, cố gắng, bắt và kết thúc ở mọi nơi trong mã, tôi có phương thức execute(SQL, up to three inputs) tuy nhiên nếu cố gắng truy cập vào ResultSet lỗi:Java Sử dụng phương thức SQL Execute nhưng có thể truy cập các kết quả

"Operation not allowed after ResultSet closed" 

Đó là vì khi bạn đóng PreparedStatement nó đóng ResultSetToo (và dường như không có cách nào xung quanh nó).

Có cách nào để sửa lỗi này không? Điều duy nhất tôi có thể nghĩ ra được chuyển đổi nó vào một mảng được lưu trữ

Rất cám ơn cho thời gian của bạn,

Trả lời

9

Tôi đã gặp phải vấn đề tương tự trong quá khứ. Bây giờ tôi sử dụng phương pháp này:

public ArrayList<Map<String, String>> getListOfMapsFromSQL(String sql) throws SQLException { 
    con = DriverManager.getConnection(url,user,pass); 
    stmt = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE); 
    ArrayList<Map<String, String>> list = new ArrayList<Map<String, String>>(); 

    rs = stmt.executeQuery(sql); 
    ResultSetMetaData rsmd = rs.getMetaData(); 

    while(rs.next()){ 
     Map<String, String> fieldsMap = new HashMap<String, String>(); 
     for(int i=1; i<=rsmd.getColumnCount(); i++){ 
      fieldsMap.put(rsmd.getColumnLabel(i), rs.getObject(i).toString()); 
     } 
     list.add(fieldsMap); 
    } 

    list.trimToSize(); 
    stmt.close(); 
    con.close(); 
    return list; 
} 

, nó trả về danh sách Bản đồ (mỗi một đại diện cho 1 hàng). Chuỗi đầu tiên là nhãn cột và cột thứ hai là giá trị của cột. Tôi hy vọng nó sẽ giúp. :-)

+0

Bạn nên trả về một 'Bản đồ ' để tránh mất thông tin về các kiểu dữ liệu thực tế được trả về. Và 'rs.getObject (1) .toString()' sẽ ném ra với NullPointerException nếu bảng chứa giá trị NULL. –

+0

Tất cả các loại JDBC được ánh xạ đều có phương thức toString(). Và về null, tôi đã không có bất kỳ vấn đề. SELECT * Từ một trong các bảng của tôi, trong đó có trường DATE với giá trị null, in ra "null" trên bảng điều khiển. – athspk

+0

Tất nhiên họ có phương thức toString(). Nhưng việc chuyển đổi chuỗi trở lại thành "thực" có thể là một vấn đề.Làm thế nào để bạn biết được họ nên chuyển đổi đối tượng nào? Điều gì về định dạng mặc định phụ thuộc vào ngôn ngữ (dấu phân cách thập phân, định dạng ngày và vv). Điều này giống như lưu trữ tất cả mọi thứ trong một cột varchar trong cơ sở dữ liệu ... –

4

when you close the PreparedStatement it closes the ResultsSetToo

đúng. Vì vậy, có thể không đóng PreparedStatement cho đến khi bạn đã xử lý kết quả.

Tôi sẽ xác định giao diện, ví dụ: ResultConsumer hoặc một cái gì đó tương tự mà người gọi thực hiện() có thể thực hiện. Sau đó, bên trong phương thức execute() của bạn, bạn chỉ cần chuyển Resultet tới người tiêu dùng.

 
public Interface ResultConsumer 
{ 
    void processResult(ResultSet rs); 
} 

Sau đó bạn thực hiện() có thể trông như thế này

 
public void execute(String SQL, ResultConsumer consumer, ... other parameters) 
{ 
    PreparedStatement stmt = ... 
    ResultSet rs = stmt.executeQuery(); 
    consumer.processResult(rs); 
    rs.close(); 
    stmt.close(); 
} 

(Tôi đã gỡ bỏ tất cả các kiểm tra lỗi và xử lý ngoại lệ cho rõ ràng, tất nhiên bạn sẽ cần để đối phó với điều đó)

+0

Đi qua một đóng cửa như vậy là một cách tuyệt vời để xử lý việc này. Nếu bạn vẫn muốn giữ dữ liệu xung quanh, bạn có thể viết một đóng chung để ném kết quả vào một Danh sách hoặc một cái gì đó để đọc nó sau này, nếu bạn muốn. – jricher

4

Một số thời gian trở lại, tôi đã cùng một vấn đề để đối phó với. Sau khi cân nhắc về thiết kế này, chúng tôi quyết định làm như sau.

public static Properties execute(String string, String[] columnames) throws Exception { 

    Properties resulProperties = er.executeQuery(string, columnames); 

    return resulProperties; 

} 

Đối với một số lý do cụ thể, tôi đã tạo ra một lĩnh vực trong lớp học của tôi là đưa ra dưới đây

private static ExecuteRequest er = new ExecuteRequest(); 

Trong ExecuteRequest lớp dưới đây đang được sử dụng.

public Properties executeQuery(String sqlstatement, String[] columnNames) throws Exception { 
    Properties prop = new Properties(); 
    try { 
     prop = creteProperty(sqlstatement, columnNames); 
    } catch (Exception e) { 
     mlogger.report("Error executing sql statement"); 
     throw (e); 
    } 

    return prop; 

} 

public Properties creteProperty(String sqlstatement, String[] columnNames) throws Exception { 
    Properties prop = new Properties(); 

    try { 
     PreparedStatement stmt = ConnectionManager.getInstance().prepareStatement(sqlstatement); 
     ResultSet rs = stmt.executeQuery(); 
     if (rs.next()) { 
      for (int i = 0; i < columnNames.length; i++) { 
       String key = columnNames[i]; 
       if (rs.getObject(key) != null) { 
        String value = (rs.getObject(key).toString()); 
        prop.setProperty(key, value); 
       } else { 
        String value = ""; 
        prop.setProperty(key, value); 
       } 

      } 
     } 
     rs.close(); 
    } catch (Exception e) { 
     mlogger.report("Error executing sql statement"); 
     throw (e); 
    } 
    return prop; 

} 

Bạn có thể sử dụng phương pháp này làm giải pháp.

Các vấn đề liên quan