2011-01-12 5 views
5

코드에서 복잡한 SQL 쿼리, 시도, 캐치 및 결선을 처리하는 것보다 execute(SQL, up to three inputs) 메서드가 있지만 결과 집합에 액세스하려고하면 실행 결과가 나옵니다. 오류 :Java SQL 실행 메소드를 사용하지만 결과에 액세스 할 수 있음

당신이 된 PreparedStatement를 닫을 때는 ResultsSetToo을 닫습니다 (그리고 주위에 방법이없는 것 같다) 때문이다
"Operation not allowed after ResultSet closed" 

.

해결 방법이 있습니까? 내가 생각할 수있는 유일한 방법은

답변

9

나는 이전에 같은 문제가 발생했습니다.

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

가 대신 ResultSet을 반환하는이지도의 목록을 (1 개 행을 나타내는 각각의) 반환

: 지금은이 방법을 사용합니다. 첫 번째 String은 Label 열이고 두 번째 String은 열 값입니다. 나는 그것이 도움이되기를 바랍니다. :-)

+0

반환 된 실제 데이터 유형에 대한 정보가 손실되지 않도록하려면'Map '를 다시 전달해야합니다. 그리고'rs.getObject (1) .toString()'은 테이블에 NULL 값이있는 경우 NullPointerException으로 폭탄을 제거합니다. –

+0

매핑 된 모든 JDBC 유형에는 toString() 메소드가 있습니다. 그리고 null에 대해서는 아무런 문제가 없었습니다. SELECT * Null 값을 가진 DATE 필드가있는 내 테이블 중 하나에서 콘솔에 "null"을 출력합니다. – athspk

+0

물론 toString() 메서드가 있습니다. 그러나 문자열을 "진짜"로 다시 변환하는 것은 문제가 될 수 있습니다.어떤 물체를 다시 변환해야하는지 어떻게 알 수 있습니까? 로케일 (소수 구분 기호, 날짜 형식 등)에 따라 달라지는 기본 서식은 어떻습니까? 이것은 데이터베이스의 varchar 열에 모든 것을 저장하는 것과 같습니다. –

4

when you close the PreparedStatement it closes the ResultsSetToo

수정, 당신의 시간을

많은 감사를 저장하는 배열로 변환되었다. 결과를 처리 할 때까지 PreparedStatement를 닫지 않을 수 있습니다.

인터페이스를 정의합니다. ResultConsumer 또는 execute()의 호출자가 구현할 수있는 것과 비슷한 것입니다. 그런 다음 execute() 메서드 내에서 결과 집합을 소비자에게 전달하면됩니다.

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

그런 다음 실행()이

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

(나는 명확성을 위해 처리하는 모든 오류 검사 및 예외를 제거, 물론 당신이 처리해야합니다)

+0

이와 같은 마감 처리를하면이 문제를 해결할 수 있습니다. 그래도 데이터를 보관하려면 일반 클로저를 작성하여 결과를 목록 에 던지거나 나중에 읽을 수 있도록 할 수 있습니다. – jricher

4

처럼 보일 수 있습니다 잠시 뒤로 나는 똑같은 문제를 다루어야했다. 이 디자인에 대해 숙고 한 후에 우리는 아래처럼 그것을하기로 결정했습니다. 코드 아래 ExecuteRequest 클래스가 사용됩니다에서

private static ExecuteRequest er = new ExecuteRequest(); 

아래에 주어진 몇 가지 구체적인 이유

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

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

    return resulProperties; 

} 

, 나는 내 수업에서 필드를 만들었습니다.

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; 

} 

이 방법을 해결책으로 사용할 수 있습니다.

관련 문제