Java / JDBC: лучший шаблон проектирования для закрытия соединения с базой данных при возникновении исключения

Я новичок в Java (я использую Java 6). Я использовал приведенный ниже шаблон проектирования для всех моих Java POJO и сервлетов для доступа к базе данных Oracle 11G через веб-сервер GlassFish 3.1.2.

Я получаю неустойчивую ошибку базы данных (ORA-12519), когда все доступные процессы (или сеансы, не уверен, в чем разница) используются, что заставляет меня думать, что процессы не освобождаются приложением.

Глядя на шаблон проектирования ниже, есть ли лучший способ убедиться, что соединение JDBC с базой данных освобождается в случае исключения? Например, я должен также разместитьif ( conn != null) conn.close(); код ВНУТРИ блока catch? Или есть лучший дизайн шаблона? Заранее спасибо за любые комментарии / подсказки.

public String MyFunction() throws Exception {     

    Connection conn;
    CallableStatement cs;

  try {

      Context context = new InitialContext();
      DataSource ds = (DataSource)context.lookup("jdbc/MyPool");
      conn = ds.getConnection();        

      cs = conn.prepareCall( "{call my_sproc (?)}" );

      cs.registerOutParameter(1, Types.VARCHAR);

      cs.execute();

      String outParam = cs.getString(1); 

      if ( conn != null )  // close connection
         conn.close();

  } catch (Exception e) {
      outParam = "an error occurred";
  }
    return outparam;
}
 ggkmath22 июн. 2012 г., 19:33
Обратите внимание, что также может быть полезно закрыть наборы результатов и операторы. Вот полезная ссылка (см. Ответ Стефана Швайцера в ссылке для хорошего шаблона дизайна):stackoverflow.com/questions/103938/…

Ответы на вопрос(4)

Java 7 поддерживает функцию пробного использования ресурсов. это создает окончательно для вас.http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html

Блок finally закроет ресурсы, выделенные в попытке. как вы использовали ключевое слово, используя в C #

Однако пользователь использует Java SE6 ... Смотрите параметры других пользователей :)

ВАЖНО: Используемые заявления также должны быть закрыты.

 23 июн. 2012 г., 12:12
 ggkmath22 июн. 2012 г., 19:08
Отличный справочник для пользователей java se 7, спасибо!
 22 июн. 2012 г., 19:12
Я не читал, но пользователь Miserable Variable тоже говорил о попытке с ресурсами.
 22 июн. 2012 г., 19:48
Я был неправ. Апидоки дляConnection не говорите, что закрытиеConnection закрывает егоStatements; но обратите внимание, что закрытиеStatement is требуется закрытьResultSets
Решение Вопроса
if ( conn != null )  // close connection
         conn.close();

На этой линииconn cannot быть нулевым Самый популярный шаблон вплоть до Java 6:

Connection conn = null;
try {
   // initialize connection
   // use connection 
} catch {
  // handle exception
} finally {
  if (conn != null) {
     try { conn.close(); } catch (Exception e) { /* handle close exception, quite usually ignore */ } 
     }
}

СJava 7 это станет менее громоздким с егопопробуйте-с ресурсом построить. Приведенный выше код может измениться на гораздо более короткий

try (Connection conn  = createConnection()) {
    // use connection 
} catch {
    // handle exception
}
// close is not required to be called explicitly
 22 июн. 2012 г., 19:29
Да, как я показал в своем шаблоне, соединения, как правило, закрываются только в окончании.
 22 июн. 2012 г., 18:59
Да, исключения изconnection.close() часто игнорируются или по большей части регистрируются, но не обрабатываются каким-либо другим способом :) Я не знаю, почему; На самом деле я никогда не видел, чтобы близкие бросали исключение.
 ggkmath22 июн. 2012 г., 19:00
Хорошо, я, наверное, войду, спасибо!
 ggkmath22 июн. 2012 г., 18:57
Спасибо, несчастная переменная, когда говоришь "до Java 6" Вы имеете в виду "вплоть до Java 6"? (это то, что я использую)? Я так полагаю. Кроме того, когда вы говорите «обычно игнорируется», вы ссылаетесь только наtry...catch в блоке finally (то естьif (conn != null) conn.close(); всегда там, верно?) Почему люди обычно игнорируют обработку исключения в блоке finally для закрытия соединения?
 ggkmath22 июн. 2012 г., 19:03
Просто чтобы быть понятным, поскольку, наконец, выполняется независимо от того, что, мне не нужно закрывать соединение внутри блока try, верно? Я могу просто закрыть соединение один раз в коде, который находится в блоке finally. Это правильно?

Использоватьfinally блокировать всегда, чтобы высвободить ресурсы.

The finally block always executes when the try block exits. This ensures that the finally block is executed even if an unexpected exception occurs.

  try {

      Context context = new InitialContext();
      DataSource ds = (DataSource)context.lookup("jdbc/MyPool");
      conn = ds.getConnection();        

      cs = conn.prepareCall( "{call my_sproc (?)}" );

      cs.registerOutParameter(1, Types.VARCHAR);

      cs.execute();

      String outParam = cs.getString(1); 


  } catch (Exception e) {
      outParam = "an error occurred";
  }
 finally {
       conn.close();
    } 
 22 июн. 2012 г., 18:52
Если вы подозреваете, чтоconn.close() снова выдаст ошибку, окружите ееtry catch finally также.
 22 июн. 2012 г., 18:58
@ggkmath да, вам нужно проверитьconn != null; может быть нулевым, еслиds.getConnection() выбрасывает исключение. И будь вы подозреваете или нет, вам нужно поставитьclose() вtry/catch/finally; иначе метод должен включить его в свойthrows пункт, который не хорошо.
 ggkmath22 июн. 2012 г., 18:50
Спасибо Казекаге, Уиллconn.close() строка кода в блоке finally выдает ошибку, если соединение еще не открыто или по какой-либо другой причине? Если да, то я не должен использовать этоif (conn!=null) утверждение выше в блоке finally?

Я предпочитаю другой более элегантный способ, чем:

} finally {
  if (conn != null) {
     try {
         conn.close();
     } catch (Exception e) {
         /* handle close exception, quite usually ignore */
     } 
  }
}

Вы можете использовать DbUtils.closeQuietly:http://commons.apache.org/dbutils/apidocs/org/apache/commons/dbutils/DbUtils.html

Ваш ответ на вопрос