Закрытие соединений JDBC в пуле
Наш стандартный раздел кода для использования JDBC...
Connection conn = getConnection(...);
Statement stmt = conn.conn.createStatement (ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
ResultSet rset = stmt.executeQuery (sqlQuery);
// do stuff with rset
rset.close(); stmt.close(); conn.close();
Вопрос 1: при использовании пула соединений нужно ли закрывать соединение в конце? Если так, разве цель объединения не потеряна? И если нет, то как DataSource узнает, когда конкретный экземпляр Connection освобожден и может быть повторно использован? Я немного запутался в этом, любые указатели оценены.
Вопрос 2: Является ли следующий метод чем-то близким к стандартному? Похоже на попытку получить соединение из пула, и если DataSource не может быть установлен, используйте старомодный DriverManager. Мы даже не уверены, какая часть исполняется во время выполнения. Повторяя вопрос выше, следует ли закрыть соединение, выходящее из такого метода?
Спасибо, - ср.
synchronized public Connection getConnection (boolean pooledConnection)
throws SQLException {
if (pooledConnection) {
if (ds == null) {
try {
Context envCtx = (Context)
new InitialContext().lookup("java:comp/env");
ds = (DataSource) envCtx.lookup("jdbc/NamedInTomcat");
return ds.getConnection();
} catch (NamingException e) {
e.printStackTrace();
}}
return (ds == null) ? getConnection (false) : ds.getConnection();
}
return DriverManager.getConnection(
"jdbc:mysql://"+ipaddy+":"+dbPort +"/" + dbName, uName, pWord);
}
Изменить: я думаю, что мы получаем пул соединения, так как мы не видим трассировки стека.
3 ответа
При использовании пула соединений нужно ли закрывать соединение в конце? Если так, разве цель объединения не потеряна? И если нет, то как DataSource узнает, когда конкретный экземпляр Connection освобожден и может быть повторно использован? Я немного запутался в этом, любые указатели оценены.
Да, конечно, вам также необходимо закрыть пул соединения. Это на самом деле обертка вокруг фактического соединения. Под крышками освободится фактическое соединение с бассейном. Далее пул должен решить, будет ли фактическое соединение фактически закрыто или будет повторно использовано для нового getConnection()
вызов. Таким образом, независимо от того, используете ли вы пул соединений или нет, вы всегда должны закрывать все ресурсы JDBC в обратном порядке в finally
блок из try
блок, где вы их приобрели. В Java 7 это может быть еще более упрощено с помощью try-with-resources
заявление.
Является ли следующий метод близким к стандартному? Похоже на попытку получить соединение из пула, и если DataSource не может быть установлен, используйте старомодный DriverManager. Мы даже не уверены, какая часть исполняется во время выполнения. Повторяя вопрос выше, следует ли закрыть соединение, выходящее из такого метода?
Пример довольно страшный. Вам просто нужно искать / инициализировать DataSource
только один раз при запуске приложения в каком-либо конструкторе / инициализации класса конфигурации БД для всего приложения. Тогда просто позвоните getConnection()
на одном и том же источнике данных в течение оставшейся части времени жизни приложения. Нет необходимости ни в синхронизации, ни в нулевых проверках.
Смотрите также:
Пулы обычно возвращают вам обернутый объект Connection, где метод close() переопределяется, обычно возвращая Connection к пулу. Вызов close() в порядке и, вероятно, все еще требуется.
Метод close(), вероятно, будет выглядеть так:
public void close() throws SQLException {
pool.returnConnection(this);
}
Для второго вопроса вы можете добавить регистратор, чтобы показать, работает ли нижний блок. Я бы предположил, что вы хотите использовать тот или иной способ настройки соединений с вашей базой данных. Мы исключительно используем пул для доступа к нашей базе данных. В любом случае, закрытие соединения было бы очень важно для предотвращения утечек.
На самом деле, лучший подход к управлению соединениями - не размещать их в любом месте кода.
Создайте класс SQLExecutor, который является единственным местоположением, которое открывает и закрывает соединения.
Вся остальная часть приложения затем закачивает операторы в исполнителя, а не получает соединения из пула и управляет (или неправильно управляет ими) повсеместно.
Вы можете иметь столько экземпляров executor, сколько захотите, но никто не должен писать код, который открывает и закрывает соединения от своего имени.
Удобно, что это также позволяет вам регистрировать весь ваш SQL из единого набора кода.