Нужен код для создания пула подключений в Java - PullRequest
30 голосов
/ 13 мая 2010

Нужен код для создания пула соединений в Java? Как мы можем убедиться, что пул соединений не возвращает тот же объект, который уже используется? Как происходит, если клиент закрыл соединение после удаления его из пула соединений?

Обновление 1:

Я хочу создать это в терминах Simple Java и посмотреть, как это работает в Multithreading Env. Я имею в виду, какие методы будут синхронизированы, а какие нет. Также будет ли этот класс публичным? Если да, то любой может получить доступ к этому классу и повторно инициализировать пул соединений?

Обновление 2:

У меня есть код, как показано ниже. Но я не знаю, как «Закрытие соединения из пула возвращает его в пул, физически оно не закрывается». Также я не понял этого: «Если соединение было заимствовано из пула и еще не возвращено, оно не« доступно »и не может быть перераспределено другому клиенту пула».

import java.util.*;
import java.sql.*;

class ConnectionPoolManager
{

 String databaseUrl = "jdbc:mysql://localhost:3306/myDatabase";
 String userName = "userName";
 String password = "userPass";

 Vector connectionPool = new Vector();

 public ConnectionPoolManager()
 {
  initialize();
 }

 public ConnectionPoolManager(
  //String databaseName,
  String databaseUrl,
  String userName,
  String password
  )
 {
  this.databaseUrl = databaseUrl;
  this.userName = userName;
  this.password = password;
  initialize();
 }

 private void initialize()
 {
  //Here we can initialize all the information that we need
  initializeConnectionPool();
 }

 private void initializeConnectionPool()
 {
  while(!checkIfConnectionPoolIsFull())
  {
   System.out.println("Connection Pool is NOT full. Proceeding with adding new connections");
   //Adding new connection instance until the pool is full
   connectionPool.addElement(createNewConnectionForPool());
  }
  System.out.println("Connection Pool is full.");
 }

 private synchronized boolean checkIfConnectionPoolIsFull()
 {
  final int MAX_POOL_SIZE = 5;

  //Check if the pool size
  if(connectionPool.size() < 5)
  {
   return false;
  }

  return true;
 }

 //Creating a connection
 private Connection createNewConnectionForPool()
 {
  Connection connection = null;

  try
  {
   Class.forName("com.mysql.jdbc.Driver");
   connection = DriverManager.getConnection(databaseUrl, userName, password);
   System.out.println("Connection: "+connection);
  }
  catch(SQLException sqle)
  {
   System.err.println("SQLException: "+sqle);
   return null;
  }
  catch(ClassNotFoundException cnfe)
  {
   System.err.println("ClassNotFoundException: "+cnfe);
   return null;
  }

  return connection;
 }

 public synchronized Connection getConnectionFromPool()
 {
  Connection connection = null;

  //Check if there is a connection available. There are times when all the connections in the pool may be used up
  if(connectionPool.size() > 0)
  {
   connection = (Connection) connectionPool.firstElement();
   connectionPool.removeElementAt(0);
  }
  //Giving away the connection from the connection pool
  return connection;
 }

 public synchronized void returnConnectionToPool(Connection connection)
 {
  //Adding the connection from the client back to the connection pool
  connectionPool.addElement(connection);
 }

 public static void main(String args[])
 {
  ConnectionPoolManager ConnectionPoolManager = new ConnectionPoolManager();
 }

}

Ответы [ 7 ]

46 голосов
/ 13 мая 2010

Нужен код для создания пула соединений в Java?

Не уверен, что вопрос, но не создавайте еще один пул соединений, используйте существующее решение, такое как C3P0 , Apache DBCP , Proxool или BoneCP (новый игрок на этом поле). Я бы использовал C3P0.

Как мы можем убедиться, что пул соединений не возвращает тот же объект, который уже используется?

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

Как происходит, если клиент закрыл соединение после удаления его из пула соединений?

Соединение, которое клиент получает из пула, на самом деле не java.sql.Connection, это обертка (прокси) для java.sql.Connection, которая настраивает поведение некоторых методов , Метод close() является одним из них и не закрывает экземпляр Connection, но возвращает его в пул.

13 голосов
/ 13 мая 2010

Не пиши свое. Существует множество библиотек, которые сделают это для вас, с открытым исходным кодом, просты в использовании и решат все проблемы, с которыми вы столкнетесь, пытаясь сделать это самостоятельно.

Вот простой пример, который использует Apache Commons DBCP и Commons Pool:

Сначала настройте источник данных.

javax.sql.DataSource source = new org.apache.commons.dbcp.BasicDataSource();
source.setDriverClassName("com.mysql.jdbc.Driver");
source.setUsername("username");
source.setPassword("password");
source.setUrl("jdbc:mysql://localhost:3306/myDatabase");

Получив источник данных, легко получить соединение из пула.

java.sql.Connection connection = source.getConnection();

закрытие соединения вернет его в пул для вас.

connection.close();
12 голосов
/ 13 марта 2014

Надеюсь, этот исходный код поможет http://jagadeeshmanne.blogspot.in/2014/03/connection-pool-in-java-jdbc.html

Configuration.java

package com.jmanne.utils;

public class Configuration {

 public String DB_USER_NAME ;

 public String DB_PASSWORD ;

 public String DB_URL;

 public String DB_DRIVER;

 public Integer DB_MAX_CONNECTIONS;

 public Configuration(){
  init();
 }

 private static Configuration configuration = new Configuration();

 public static Configuration getInstance(){ 
  return configuration;
 }

 private void init(){
  DB_USER_NAME = "root"
  DB_PASSWORD = "root"
  DB_URL = "jdbc:mysql://localhost:3306/jmanne"
  DB_DRIVER = "com.mysql.jdbc.Driver"
  DB_MAX_CONNECTIONS = 5
 }     
}

JdbcConnectionPool.java

package com.jmanne.db;

import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.jmanne.utils.Configuration;
import com.mysql.jdbc.Connection;

public class JdbcConnectionPool {

 List<connection> availableConnections = new ArrayList<connection>();

 public JdbcConnectionPool()
 {
  initializeConnectionPool();
 }

 private void initializeConnectionPool()
 {
  while(!checkIfConnectionPoolIsFull())
  {
   availableConnections.add(createNewConnectionForPool());
  }
 }

 private synchronized boolean checkIfConnectionPoolIsFull()
 {
  final int MAX_POOL_SIZE = Configuration.getInstance().DB_MAX_CONNECTIONS;

  if(availableConnections.size() < MAX_POOL_SIZE)
  {
   return false;
  }

  return true;
 }

 //Creating a connection
 private Connection createNewConnectionForPool()
 {
  Configuration config = Configuration.getInstance();
  try {
   Class.forName(config.DB_DRIVER);
   Connection connection = (Connection) DriverManager.getConnection(
     config.DB_URL, config.DB_USER_NAME, config.DB_PASSWORD);
   return connection;
  } catch (ClassNotFoundException e) {
   e.printStackTrace();
  } catch (SQLException e) {
   e.printStackTrace();
  }
  return null;

 }

 public synchronized Connection getConnectionFromPool()
 {
  Connection connection = null;
  if(availableConnections.size() > 0)
  {
   connection = (Connection) availableConnections.get(0);
   availableConnections.remove(0);
  }
  return connection;
 }

 public synchronized void returnConnectionToPool(Connection connection)
 {
  availableConnections.add(connection);
 }
}

DataSource.java

package com.jmanne.db;

import java.sql.SQLException;

import com.mysql.jdbc.Connection;

public class DataSource {

 static JdbcConnectionPool pool = new JdbcConnectionPool();

 public static Connection getConnection() throws ClassNotFoundException, SQLException{
  Connection connection = pool.getConnectionFromPool();
  return connection;
 }

 public static void returnConnection(Connection connection) {
  pool.returnConnectionToPool(connection);
 }
}
6 голосов
/ 02 ноября 2012

Просто используйте семафоры. В идеале вам следует использовать CP3O или DBCP в качестве пула соединений. Теперь вы можете регулировать ваше соединение на основе семафора.

Каждый раз, когда вы делаете Get, вы приобретаете, и на каждом Release вы освобождаете его от Семафора. Более того, семафоры являются потокобезопасными.

4 голосов
/ 13 мая 2010

Используйте один из существующих, например, Apache DBCP

Соединения, возвращаемые пулом, часто являются прокси, которые «игнорируют» вызов close() из приложения. Когда соединения возвращаются в пул, их можно использовать повторно. Бассейны также закрываются и автоматически открываются при необходимости.

2 голосов
/ 09 августа 2012

Одним из аргументов в пользу создания собственного соединения является конфигурация и дополнительные файлы jar, которых следует избегать. Я согласен, что вам нужно включить сторонние интерфейсы, чтобы вы могли поменяться в зрелом соединении, но иметь свое собственное крошечное решение может иметь место. Самоочищающийся Vector с синхронизированным блоком и оболочкой conn с close (), помечающей conn как доступный, очень хорошо работает для приложений сервлета.

2 голосов
/ 13 мая 2010

Если ваше приложение работает на сервере, то настройте его в качестве источника данных, где сервер позаботится о пуле, либо, если простой Java-клиент затем использует Apache DBCP (если это база данных), или же используйте Apache Commons Pooling API Смотрите здесь: Apache Commons

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...