Реализуем все в виде класса, конструктор которого принимает на вход начальное количество соединений в пуле и параметры подключения к бд (название загружаемого класса из драйвера и строка подключения вместе с именем пользователя и паролем). Назовем класс ConnectionPool, его конструктор будет иметь вид:
public ConnectionPool(String url, String driver, int initConnCnt) { try { Class.forName(driver); } catch (Exception e) { e.printStackTrace(); } this.url = url; for (int i = 0; i < initConnCnt; i++) { availableConns.addElement(getConnection()); } }
url — это строка подключения, для MS SQL Server она будет иметь вид наподобие: jdbc:sqlserver://192.168.0.1;databaseName=dbname;username=username;password=pwd. Можно разделить имя пользователя и пароль, передавать их отдельно в DriverManager. Здесь все в одном месте, по крайней мере мне так показалось удобней. Один из допустимых драйверов для работы с MS SQL Server имеет следующий вид: com.microsoft.sqlserver.jdbc.SQLServerDriver.
В данном классе должны объявляться два вектора:
private Vector<Connection> availableConns = new Vector<Connection>(); private Vector<Connection> usedConns = new Vector<Connection>();
Первый будет содержать список доступных для использования соединений, второй список используемых в любой момент времени.
Кроме этого определяется переменная url, которая будет хранить строку подключения к бд:
private String url;
В конструкторе используется функция getConnection, которая просто создает новое подключение. Его реализация следующая:
private Connection getConnection() { Connection conn = null; try { conn = DriverManager.getConnection(url); } catch (Exception e) { e.printStackTrace(); } return conn; }
Итак, мы имеем вектор availableConns, заполненный Connection’ами в количестве initConnCnt штук, ни один из которых пока не используется непосредственно по назначению, т.е. для доступа к бд. Теперь напишем функцию retrieve, эта функция забирает из availableConns очередной Connection и добавляет его в usedConns, затем возвращает это соединение, тем самым он становится используемым:
public synchronized Connection retrieve() throws SQLException { Connection newConn = null; if (availableConns.size() == 0) { newConn = getConnection(); } else { newConn = (Connection) availableConns.lastElement(); availableConns.removeElement(newConn); } usedConns.addElement(newConn); return newConn; }
Логика понятна: сначала мы проверяем, есть ли свободные соединения, если нет, то мы создаем новое подключение, если есть, то мы извлекаем последний элемент из availableConns и удаляем его из вектора свободных соединений. Затем мы только что созданное соединение или извлеченное из списка свободных добавляем в список используемых строкой
usedConns.addElement(newConn);
и возвращаем это соединение. Конечно же без synchronized не обойтись. Как же иначе? Доступ то многопоточный, вдруг двум потокам выделится одно и то же соединение! Когда соединение становится не нужным, то мы выполняем обратную операцию, иначе говоря putback:
public synchronized void putback(Connection c) { if (c != null) { usedConns.removeElement(c); availableConns.addElement(c); } }
Логика тоже понятна и не требует объянений.
Дальше можно по необходимости написать кучу всяких дополнительных функций, которые предоставляют доступ к дополнительной информации, например, функция для получения количества свободных соединений будет выглядеть следующим образом:
public int getAvailableConnsCnt() { return availableConns.size(); }
Полностью весь класс:
import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Vector; class ConnectionPool { private Vector<Connection> availableConns = new Vector<Connection>(); private Vector<Connection> usedConns = new Vector<Connection>(); private String url; public ConnectionPool(String url, String driver, int initConnCnt) { try { Class.forName(driver); } catch (Exception e) { e.printStackTrace(); } this.url = url; for (int i = 0; i < initConnCnt; i++) { availableConns.addElement(getConnection()); } } private Connection getConnection() { Connection conn = null; try { conn = DriverManager.getConnection(url); } catch (Exception e) { e.printStackTrace(); } return conn; } public synchronized Connection getConn() throws SQLException { Connection newConn = null; if (availableConns.size() == 0) { newConn = getConnection(); } else { newConn = (Connection) availableConns.lastElement(); availableConns.removeElement(newConn); } usedConns.addElement(newConn); return newConn; } public synchronized void putConn(Connection c) { if (c != null) { usedConns.removeElement(c); availableConns.addElement(c); } } public int getAvailableConnsCnt() { return availableConns.size(); } }
ссылка на оригинал статьи http://habrahabr.ru/post/229199/
Добавить комментарий