Безопасно ли собирать ссылки на объекты JDBC и закрывать их в цикле? - PullRequest
0 голосов
/ 15 декабря 2011

Итак, я пытаюсь реорганизовать некоторый код, который создает объекты JDBC в цикле и не закрывает их чисто. Моя первая мысль - создать LinkedList для хранения подготовленных операторов, наборов результатов и т. Д., А затем закрыть их в цикле внутри блока finally. Итак, подход такой:

Connection conn = null;
LinkedList<PreparedStatement> statements = new LinkedList<PreparedStatement>();
LinkedList<ResultSet> results = new LinkedList<ResultSet>();

    try {
        conn = database.getConnection(); 

        for (String i : arr1) {
            for (String j : arr2) {

                Statement stmt = conn.createStatement();
                statements.add(stmt);

                ResultSet rs = stmt.executeQuery(...);
                results.add(rs);

                // ...work...

            }
        }

    }
    catch(SQLException ex) {ex.printStackTrace();}
    finally {
        // close all result sets..
        for (ResultSet rs : (ResultSet[])results.toArray()) {
            if (rs != null)   try { rs.close();   } catch (SQLException ex) {ex.printStackTrace();}
        }

        for (Statement stmt : (Statement[])statements.toArray()) {
            if (stmt != null) try { stmt.close(); } catch (SQLException ex) {ex.printStackTrace();}
        }

        if (conn != null) try { conn.close(); } catch (SQLException ex) {ex.printStackTrace();}
   }

Это разумный подход? Будет ли это в конечном итоге вызвать утечку или проблемы? Заранее спасибо, и, пожалуйста, дайте мне знать, если это относится к codereview.se или где-то еще.

Ответы [ 4 ]

2 голосов
/ 15 декабря 2011

Это ИМХО плохая идея по крайней мере по трем причинам:

  1. Ресурсы не очищаются сразу, когда они больше не используются.ResultSet является дорогим ресурсом, и я даже не уверен, можно ли использовать несколько открытых результирующих наборов для одного соединения ( обновление : можно, см. Комментарии).

  2. При таком подходе вы открываете несколько ресурсов одновременно, что может привести к чрезмерному и ненужному использованию ресурсов базы данных и пикам.Особенно опасно, если число итераций велико.

  3. Особый случай предыдущего пункта - память - если либо Statement, либо ResultSet содержит много памяти, содержит ненужную ссылкук нескольким таким объектам приведет к чрезмерному использованию памяти.

При этом следует рассмотреть возможность использования уже созданных и безопасных служебных классов, таких как JdbcTemplate.Я знаю, что это происходит из среды Spring, но вы можете использовать его вне контейнера (просто пропустите экземпляр DataSource) и больше не беспокоиться о закрытии ресурсов JDBC.

1 голос
/ 15 декабря 2011

Это действительно плохо, потому что это может заставить базу данных удерживать ресурсы, которые вы больше не используете.Я видел случаи, когда сбой при закрытии объектов Statement или ResultSet (не помню, какие, возможно, оба) вызывал ошибки утечки курсора в Oracle.

1 голос
/ 15 декабря 2011

Не обязательно утечка, но я мог видеть проблемы.

Мой опыт работы с Oracle JDBC (в частности) научил меня, что самое лучшее, что нужно сделать при обработке ресурсов JDBC, это закрыть их в точности наоборотчтобы ты их открыл.Каждый раз.Как можно скорее.

Сбор их для последующей очистки и освобождение их в другом порядке может вызвать проблему.Я не могу увидеть конкретный пример, но Oracle, кажется, был самым сложным в прошлом.Хорошо, что вы освобождаете ResultSet перед Statement, перед Connection, но этого может быть недостаточно.

0 голосов
/ 15 декабря 2011

Вы должны выполнить всю свою работу в try и только закрыть соединение в finally.Это стандартный шаблон.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...