Java с использованием метода SQL Execute, но с возможностью доступа к результатам - PullRequest
5 голосов
/ 13 января 2011

Вместо того, чтобы иметь сложные SQL-запросы, попытки, ловить и финалы повсюду в коде, у меня есть метод execute(SQL, up to three inputs), однако, если попытаться получить доступ к ResultsSet, который производит за пределами выполнения, вы получите ошибку:

"Operation not allowed after ResultSet closed"

Это потому, что когда вы закрываете PreparedStatement, он закрывает ResultsSetToo (и кажется, что нет никакого способа обойти это).

Есть ли способ это исправить? Единственное, о чем я мог подумать, это преобразовать его в массив, который хранится

Большое спасибо за ваше время,

Ответы [ 3 ]

9 голосов
/ 13 января 2011

Я сталкивался с той же проблемой в прошлом.Теперь я использую этот метод:

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 строку).Первая строка является меткой столбца, а вторая - значением столбца.Я надеюсь, что это помогает.: -)

4 голосов
/ 13 января 2011

Некоторое время назад я столкнулся с той же проблемой.После некоторых размышлений над этим дизайном мы решили сделать это, как показано ниже.

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

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

    return resulProperties;

}

По какой-то конкретной причине я создал поле в своем классе, как показано ниже

private static ExecuteRequest er = new ExecuteRequest();

В ExecuteRequest используется код ниже класса.

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;

}

Вы можете использовать этот подход в качестве решения.

4 голосов
/ 13 января 2011

при закрытии PreparedStatement он закрывает ResultsSetToo

Правильно.Поэтому нельзя закрывать PreparedStatement, пока вы не обработаете результат.

Я бы определил интерфейс, например ResultConsumer или что-то подобное, что может реализовать вызывающая функция execute ().Затем внутри вашего метода execute () вы просто передаете Resultset потребителю.

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

Тогда ваш execute () может выглядеть следующим образом

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

(я удалил все проверки ошибок иобработка исключений для ясности, конечно, вам придется иметь дело с этим)

...