Блог → JDBC Connection pool - своими руками. Часть 2

Итак, на чём мы остановились вчера? Мы успели познакомиться с классом DBConnectionPool и инициализировать хранилище, но разумеется, этого мало для полноценной работы. Чего же не хватает? Ну, как минимум - функций для работы с пулом. Итак, продолжаем!

Получение соединения из пула

Метод getConnection() предоставляет возможность получить соединение с базой данных в виде объекта Connection. Внутри метода проверяется содержимое контейнера, представляющего собой объект класса ArrayList. В том случае, когда контейнер содержит элементы, из него извлекается одно из доступных соединений и возвращается объекту-клиенту. Если же свободных соединений в контейнере нет, тогда создается новое соединение, которое также возвращается объекту-клиенту.

public synchronized Connection
getConnection() {

Connection con = null;
if (!freeConnections.isEmpty()) {
con = (Connection)
freeConnections.get
(freeConnections.size()-1);
freeConnections.remove(con);

try {
if (con.isClosed()) {
log("Removed bad connection ");
// Try again recursively
con = getConnection();
}
}

catch (SQLException e) {
log ("Removed bad connection ");
// Try again recursively
con = getConnection();
}

catch (Exception e) {
log ("Removed bad connection ");
// Try again recursively
con = getConnection();
}

} else {
con = newConnection();
}

return con; }


Внутри метода getConnection() существует проверка на доступность соединения. Если возникает исключение, то процесс получения соединения будет рекурсивно повторяться до тех пор, пока ресурсы контейнера не истощатся, после чего будет создан новый экземпляр объекта Connection.

В том случае, если контейнер не содержит элементов, программа автоматически создает новое соединение при помощи метода newConnection(). Для этого используются URL-идентификатор, имя пользователя и пароль. Внутри метода вызываются статические методы getConnection() класса DriverManager. Метод возвращает ссылку на объект Connection.

private Connection
newConnection() {

Connection con = null;
try {
if (user == null) {
con = DriverManager.
getConnection(URL);
}

else {
con = DriverManager.
getConnection(URL, user, password);
}

log("Created a new connection in pool");
}

catch (SQLException e) {
log("Can't create a new connection for " + URL);
return null;
}

return con; }


Возвращение соединения в пул

Класс DBConnectionPool предоставляет также и возможность возвратить использованное соединение обратно в пул в виде метода freeConnection(). Параметром метода является ссылка на используемый объект типа Connection.

public synchronized void
freeConnection(Connection con) {

// Put the connection
// at the end of the List
if ( (con != null) &&
(freeConnections.size!) <= maxConn) ) {
freeConnections.add(con);
}
}


Уничтожение пула

После того, как все необходимые действия с базой данных выполнены, и больше запросов от пользователя не поступает, можно удалить все элементы из пула, вызвав метод release(), в котором, как можно легко догадаться, закрываются и удаляются все открытые соединения.

public synchronized void released {
Iterator allConnections = freeConnections.iterator();

while (allConnections. hasNext()) {
Connection con = (Connection) allConnections.next();

try {
con. closed;
log("Closed connection for pool");
}

catch (SQLException e) {
log("Can't close connection for pool");
}

}

freeConnections.clear(); }


Использование пула соединений в контексте сервлета

Так как сервлет представляет собой обыкновенный java-класс, его время жизни определено следующими методами:
• init() - создание и инициализация сервлета;
• service() - контроль над поступающими запросами от клиентов;
• destroy() - уничтожение сервлета.

Для эффективного использования пула соединений рекомендуется произвести следующие действия:
• создать объект типа DBConnectionPool в методе init();
• каждый раз при обращении клиента к сервлету выделять доступное соединение при помощи метода getConnection() в методе service();
• уничтожить ненужное хранилище соединений в методе destroy().

Для наглядности, вот как всё это выглядит на примере простого java-сервлета:

import java.io.*;
import java.sql.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class TestServlet extends
HttpServlet {
private static DBConnectionPool pool;

public void init(ServletConfig conf)
throws ServletException {
super.init(conf);
pool = DBConnectionPool.
getInstance("jdbc:odbc:test", "Administrator", "Admin", 30);
}

public void
service(HttpServletReguest reg,
HttpServletResponse res)
throws IOException {

res. setContentType (text/html);
PrintWriter out = res.getWriterd;
Connection con = pool.getConnection();
if (con == null) {
out.printIn("Can't recieve connection!");
return;
}

ResultSet rs = null;
Statement stmt = null;
ResultSetMetaData md = null;

try {
stmt = con.createConnectiond;
rs = stmt.executeQuery("SELECT * FROM COMPANY");
md = rs.getMetaDatad;
out.println(*Important info:");
while(rs.next()) {
out. println ("
");
for (int i = 1; i < md.getColumnCountd; i++) {
out.print(re.getstring(i) +
", ";
}

}
stmt.close();
rs.close();
}

catch (SQLException ex) {
ex.printStackTrace(out);
}

pool.freeConnection(con);
}

public void destroy() {
pool.release();
}

}


Рассмотренный пример использования технологии пула соединений наглядно демонстрирует простоту и доступность средств программирования, связанных с производительностью баз данных и методов доступа к ним. Данная технология может с успехом применяться в проектировании интернет-магазинов и других интерактивных интернет-сайтов, позволяя программистам эффективно использовать имеющиеся ресурсы. Надеюсь, что обе части статьи были полезны, и как обычно - до новых встреч в блоге ITpool!