Комментарии 38
Понятно что решение обобщённое и подходит для любых ресурсов, а не только соединений с БД, но неужели нельзя в строке подключения указать что-то вроде «Pooling=yes»?
У драйвера нельзя, он низкоуровневый и с такими категориями не работает.
Обожаю статьи типа «Две недели назад я начал заниматься… и вот я решил написать статью...»
Мне тоже понравились «письменные мысли путем написания...». :-)
Мне всегда нравилась JAVA. Пачка фаилов, для того чтобы только подключится к БД
Наверное правильнее сказать что всего 2 файла и получаем пул соединений. :)
Вы не правы. Захардкодить подключение можно одной строчкой, а пачкой файлов можно добиться гибкости.
Connection conn = DriverManager.getConnection(«jdbc:oracle:thin:127.0.0.1:1521», «system», «sys»);

Реквестирую пачку файлов. Кроме JDBC-драйвера естественно.
ну, вообще-то именно это и называется «захардкодить одной строчкой» :)
Хотя нет, не так. Не от maxWait это зависит. У нас была проблема с тем, что соединения отвалившиеся по таймауту оставались в пуле
У нас на проекте тоже были проблемы… Мы их «решали» давольно легким способом — перед выполнением запроса делали фейковый запрос к БД. Если он срабатывал, то все хорошо, иначе пересоздавали, хотя система считала, что все нормально… ведь у нее же было открытое потключение :)
Настройка validationQuery почти этим и занимается. Думаю удобней один раз в конфиге прописать и забыть о проблеме вобще)
Две недели назад я начал писать на Java и теперь, дорогие хабралюди, я расскажу вам о чудном способе вывода «Hello, world»… [*сарказм*]
НЛО прилетело и опубликовало эту надпись здесь
Сдаётся мне, что главная причина, по которой используется пул соединений — это возможность одновременной работы нескольких потоков (threads) приложения. В противном случае потоку, который открывает транзакцию, пришлось бы ещё и тормозить остальные потоки. Кстати, странно, что используется работа с БД напрямую. Есть же JPA, есть же Hibernate. Насколько я знаю, для них пул можно настроить специфическим механизмом.
В посте правильно написано, главная причина — исключить затраты на открытие/закрытие соединения.
Ну не совсем правильно выразился. В посте написано, что можно было бы использовать singleton, но лучше его не использовать, т.к. это пагубно скажется на производительности. А как раз поднимать только одно соединение на всё приложение чревато не столько снижением производительности, сколько невозможности одновременной обработки нескольких запросов.
Не поверите, «для них пул можно настроить специфическим механизмом» внутри hibernate пула лежит примерный такой же механизм описанный автором.
Да, работают они все так же. Но внутри Hibernate использует пул по умолчанию. Кроме того, можно (и нужно в продуктиве) настраивать пул специально для Hibernate. В этом случае настройка пула выглядит несколько иначе, чем описано в статье.
Я бы добавил к статье следующее замечание.
Перед возвратом соединения в пул все Statement'ы и ResultSet'ы, полученные с помощью этого соединения, автоматически закрываются в соответствии с API.
Ну да, так оно и есть. Главное не забывать, что соединение необходимо вовремя закрывать, иначе можем запросто переполнить пул соединений и очередь. Statement и ResultSet тоже лучше закрывать, если они больше не нужны. У меня эта привычка осталась с «древних» времен Turbo C/Pascal когда самому приходилось следить за ресурсами. С моей точки зрения привычка «убирать за собой» при работе приложения на сервере приложений, это хорошая привычка. Каждый объект, будь то EJB, Servlet и пр. имеет свой жизненный цикл и тут уже нельзя полагаться на то, что конкретный экземпляр умрет сразу после обращения и GC унесет весь мусор связанный с ним.
Лучше сделать аннотацию и высвобождать ресурсы в interceptor-е. А само соединение получать через dependency injection. И не нужно будет помнить о дуратских close в finally
А еще удобнее этим через Spring пользоваться — он сам «вставит» Connection Pool в ваши классы
еще опции:
autoCommit=«false»
— тут я думаю понятно

removeAbandoned=«true» removeAbandonedTimeout=«30» logAbandoned=«true»
— автоматически возвращает в пул соединения, которые не были закрыты а ссылка на коннекшн потеряна
(например прогер «забыл» сделать try-catch-finaly и в финализации закрыть стейтмент и соединение, а произошло исключение…

это, собственно, одна из главных опций, а автор про неё почему-то и не упомянул…
В конце, как обычно, следует закрыть соединение (conn.close()), однако в отличии от обычного соединения через драйвер JDBC, это соединение на самом деле не закроется: оно будет помечено в пуле как свободное, и его можно будет переиспользовать позже.

Каким образом об этом узнает пул? Как осуществляется обратная связь?
По ссылке на мануал написано, что идет не закрытие соединения, а его возврат в пул:

pool.returnConnection(this);
Этот же пул соединений используется в tomcat, в таком случае записывается в контекст приложения.
Основываясь на практическом опыте, могу сказать, что стоит весьма трепетно отнестись к производительности самого пула.

dbcp отличается низкой производительностью. В случае большого количества параллельных обращений к пулу он становится существенным затыком во всей системе. Проблема заключается в неэффективной реализации контейнера объектов (собственно говоря commons-pool), которая использует java synchronized.

Есть несколько альтернатив dbcp: c3p0, proxol, nanopool, miniconanectionpool, Oracle jdbc connection pool и др. После сравнительных тестов производительности мы выбрали Tomcat JDBC Connection Pool. Он использует java concurrent collections, прост в использовании и расширении, а конфигурация совместима c dbcp. Пропускная способность нашего приложения после этой замены варосла приблизительно на 30%.
Странно. Всегда думал, что затыком является не пул, а сам движок базы данных.
Поправил ошибки.
<resource-ref>
<description>DB Connection</description>
<res-ref-name>jdbc/appname</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>


InitialContext initContext= new InitialContext();
DataSource ds = (DataSource) initContext.lookup("java:comp/env/jdbc/appname");
Connection conn = ds.getConnection();


У меня была ошибка: сannot create JDBC driver of class '' for connect URL 'null'
Исправил context.xml так:
<?xml version="1.0" encoding="UTF-8"?>
<Context>   
   <Resource name="jdbc/appname" auth="Container"
				type="javax.sql.DataSource" maxActive="100" 
				maxIdle="30" maxWait="10000"
				username="username" 
				password="password"
				driverClassName="jdbc.driver.name"
				url="jdbc:protocol://hostname:port/dbname"/>
</Context>
Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.