2011-01-12 15 views
5

Karmaşık SQL sorguları yapmak yerine, kodda her yerde çalışır, yakalar ve sonlandırır. execute(SQL, up to three inputs) yöntemine sahibim, ancak ResultsSet'e erişmeye çalışırsanız, bunu yürütme dışında gerçekleştirirsiniz hata:Java SQL Execute yöntemini kullanarak ancak sonuçlara erişebilmek için

Eğer PreparedStatement kapattığınızda ResultsSetToo kapanır (ve çevresinde hiçbir şekilde var gibi görünüyor) çünkü
"Operation not allowed after ResultSet closed" 

.

Bunu düzeltmenin bir yolu var mı? Aklıma gelen tek şey

cevap

9

Geçmişte aynı sorunla karşılaştım.

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

yerine ResultSet dönen, bu Maps listesini (1 satır temsil eden her bir) döndürür

: Şimdi bu yöntemi kullanır. İlk Dize sütun Etiketi ve ikincisi sütunun değeridir. Umut ediyorum bu yardım eder. :-)

+0

Döndürülmüş gerçek veri türleri hakkında bilgi kaybetmemek için bir 'Harita ' iletilmelidir. Ve tablo nULL değerleri içeriyorsa 'rs.getObject (1) .toString()' NullPointerException ile bombalar. –

+0

Tüm eşlenen JDBC Türleri bir toString() yöntemine sahiptir. Ve null hakkında, hiç sorunum olmadı. SELECT * NULL değerleriyle DATE alanı bulunan Tablolarımdan, konsolda "null" yazdı. – athspk

+0

Elbette bir toString() yöntemine sahipler. Ama String'i "gerçek" bir şeye geri çevirmek bir problem olabilir.Hangi nesneyi geri dönüştürmeleri gerektiğini nereden biliyorsunuz? Yerel ayarlara bağlı olan varsayılan biçimlendirme (ondalık ayırıcı, tarih biçimleri vb.). Bu, veritabanındaki bir varchar sütunundaki her şeyi depolamak gibidir ... –

4

when you close the PreparedStatement it closes the ResultsSetToo

Doğru, zaman ayırdığınız için

çok teşekkür ederiz depolandığı bir diziye dönüştürerek edildi. Dolayısıyla, sonucu işleyene kadar PreparedStatement'ı kapatamayabilir.

Bir arabirim tanımlayabilirim örn. ResultConsumer veya execute() uygulamasının gerçekleştirebileceği benzer bir şey. Sonra execute() yönteminizin içinde Resultset'i sadece tüketiciye iletirsiniz.

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

Sonra senin yürütmek() bu

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

(Ben netlik için işleme hata denetimlerini ve istisna kaldırılmış, elbette bununla başa çıkmak ihtiyacımız vardır)

+0

Böyle bir kapatma işleminde bunun üstesinden gelmek harika bir yoldur. Eğer hala verileri saklamak istiyorsanız, sonuçları bir Liste listesine veya daha sonra okumak istediğiniz bir şeye atmak için genel bir kapanış yazabilirsiniz. – jricher

4

gibi görünebilir Bir süre önce, başa çıkmak için aynı problemdeydim. Bazıları bu tasarım üzerinde durduktan sonra aşağıda olduğu gibi yapmaya karar verdik. kodunun altına ExecuteRequest sınıf kullanılır ise

private static ExecuteRequest er = new ExecuteRequest(); 

aşağıda verildiği gibi bazı özel nedenle

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

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

    return resulProperties; 

} 

, benim sınıfta bir alan yarattı.

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; 

} 

Bu yaklaşımı bir çözüm olarak kullanabilirsiniz.