Java 7 Автоматическое управление ресурсами JDBC (оператор try-with-resources) - PullRequest
37 голосов
/ 13 февраля 2012

Как интегрировать обычную идиому JDBC создания / получения соединения, запроса к базе данных и, возможно, обработки результатов с помощью автоматического управления ресурсами Java 7, оператора try-with-resources? ( Учебник )

До Java 7 обычный шаблон был примерно таким:

Connection con = null;
PreparedStatement prep = null;

try{
    con = getConnection();
    prep = prep.prepareStatement("Update ...");
    ...
    con.commit();
}
catch (SQLException e){
    con.rollback(); 
    throw e;
}
finally{
    if (prep != null)
        prep.close();
    if (con != null)
        con.close();
}

С Java 7 вы можете перейти на:

try(Connection con = getConnection(); PreparedStatement prep = con.prepareConnection("Update ..."){

   ...
   con.commit();
}

Это закроет Connection и PreparedStatement, но как насчет отката? Я не могу добавить предложение catch, содержащее откат, потому что соединение доступно только в блоке try.

Вы все еще определяете соединение вне блока try? Какова наилучшая практика, особенно если используется пул соединений?

Ответы [ 3 ]

39 голосов
/ 13 февраля 2012
try(Connection con = getConnection()) {
   try (PreparedStatement prep = con.prepareConnection("Update ...")) {
       //prep.doSomething();
       //...
       //etc
       con.commit();
   } catch (SQLException e) {
       //any other actions necessary on failure
       con.rollback();
       //consider a re-throw, throwing a wrapping exception, etc
   }
}

Согласно документации oracle , вы можете объединить блок try-with-resources с обычным блоком try. ИМО, приведенный выше пример фиксирует правильную логику:

  • Попытка закрыть PreparedStatement, если все в порядке
  • Если во внутреннем блоке что-то идет не так, (независимо от того, что это) откат текущей транзакции
  • Попытка закрыть соединение независимо от того, что
  • Если что-то пойдет не так при закрытии соединения, вы не сможете откатить транзакцию (так как это метод для соединения, который сейчас находится в неопределенном состоянии), поэтому не пытайтесь

В java 6 и более ранних версиях я делал бы это с помощью тройного вложенного набора блоков try (внешний try-finally, средний try-catch, внутренний try-finally). Синтаксис ARM делает это более кратким.

4 голосов
/ 13 февраля 2012

IMO, объявляя Connection и PreparedStatement вне try-catch, является лучшим способом, доступным в этом случае.

2 голосов
/ 25 февраля 2015

Если вы хотите использовать пул соединения в транзакции, вы должны использовать его следующим образом:

try (Connection conn = source.getConnection()) {
        conn.setAutoCommit(false);
        SQLException savedException = null;
        try {
            // Do things with connection in transaction here...
            conn.commit();
        } catch (SQLException ex) {
            savedException = ex;
            conn.rollback();
        } finally {
            conn.setAutoCommit(true);
            if(savedException != null) {
                throw savedException;
            }
        }
    } catch (SQLException ex1) {
        throw new DataManagerException(ex1);
    }

Этот пример кода обрабатывает установку значений автоматической фиксации.

...