Подтвердить что ты не робот

Java 7 Автоматическое управление ресурсами JDBC (приложение try-with-resources)

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

Перед 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? Какова наилучшая практика здесь, особенно если используется объединение пулов?

4b9b3361

Ответ 1

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. IMO, приведенный выше пример фиксирует правильную логику, которая:

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

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

Ответ 2

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

Ответ 3

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

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

Этот пример кода обрабатывает значения автосохранения.