web-dev-qa-db-fra.com

Besoin de code pour créer un pool de connexions dans java

Besoin de code pour créer le pool de connexions en Java? Comment pouvons-nous nous assurer que le pool de connexions ne renvoie pas le même objet qui est déjà utilisé? Comment se passe-t-il si le client ferme la connexion après l'avoir retirée du pool de connexions?

Mise à jour 1:

Je veux créer ceci en termes simples Java termes et je veux voir comment cela fonctionne dans Multithreading Env. Je veux dire quelles méthodes seraient synchronisées et lesquelles ne le seront pas. Cette classe serait également une classe publique ? Si oui, n'importe qui peut accéder à cette classe et réinitialiser le pool de connexions.

Mise à jour 2:

J'ai du code comme ci-dessous. Mais je ne sais pas comment "La fermeture d'une connexion provenant d'un pool la renvoie au pool, elle ne ferme pas physiquement la connexion." De plus, je n'ai pas compris cela "Parce que si une connexion a été empruntée à la piscine et n'est pas encore retournée, elle n'est pas" disponible "et ne peut pas être redistribuée à un autre client de la piscine."

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();
 }

}
30
mohan

Besoin de code pour créer le pool de connexions en Java?

Vous ne savez pas quelle est la question, mais ne créez pas encore un autre pool de connexions, utilisez une solution existante comme C3P , Apache DBCP , Proxool ou - BoneCP (un nouveau joueur dans ce domaine). J'utiliserais C3P0.

Comment pouvons-nous nous assurer que le pool de connexions ne renvoie pas le même objet qui est déjà utilisé?

Parce que si une connexion a été empruntée au pool et n'est pas encore retournée, elle n'est tout simplement pas dans le pool et ne peut pas être affectée à un autre client du pool (les ressources sont supprimées du pool jusqu'à ce qu'elles soient retournées).

Comment se passe-t-il si le client ferme la connexion après l'avoir retirée du pool de connexions?

La connexion qu'un client obtient d'un pool n'est pas vraiment un Java.sql.Connection , c'est un wrapper (un proxy) pour un Java.sql.Connection qui personnalise le comportement de certaines méthodes. La méthode close() en fait partie et ne pas ferme l'instance Connection mais la renvoie au pool.

46
Pascal Thivent

N'écrivez pas le vôtre. Il existe de nombreux bibliothécaires qui le feront pour vous, qui sont open source et faciles à utiliser et auront résolu tous les problèmes que vous rencontrerez en essayant de le faire vous-même.

Voici un exemple simple qui utilise le DBCP et le pool de communes d'Apache:

Configurez d'abord un DataSource.

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");

Une fois que vous disposez d'un DataSource, il est facile d'obtenir une connexion à partir du pool.

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

la fermeture de la connexion la ramènera dans la piscine pour vous.

connection.close();
13
Ryan Elkins

J'espère que ce code source aide 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);
 }
}
12
Jagadeesh

Utilisez simplement des sémaphores. Idéalement, vous devez utiliser CP3O ou DBCP comme pool de connexions. Vous pouvez maintenant limiter votre connexion basée sur Semaphore.

Chaque fois que vous faites Get, vous obtenez et sur chaque Release vous le libérez de Semaphore. Plus de sémaphores sont thread-safe.

6
Princesh

Utilisez l'un des existants, par exemple Apache DBCP

Les connexions renvoyées par le pool sont souvent des proxys qui "ignorent" l'appel à close() depuis l'application. Lorsque les connexions sont retournées au pool, elles peuvent être réutilisées. Les piscines se ferment et se rouvrent également automatiquement si nécessaire.

4
mhaller

Si votre application s'exécute sur un serveur, configurez-la en tant que source de données, où le serveur se chargera du regroupement ou bien si un simple Java Client utilise alors Apache DBCP (si dans la base de données) ou bien utilise Apache Commons Pooling API Voir ici: Apache Commons

2
Phani

Un argument pour rouler votre propre connpool est la configuration et les pots supplémentaires qui sont évités. Je suis d'accord que vous devez activer les interfaces tierces pour pouvoir échanger dans un connpool mature, mais avoir votre propre petite solution peut avoir sa place. Le vecteur autonettoyant avec bloc synchronisé et un wrapper conn avec close () marquant le conn comme étant disponible fonctionne très bien pour les applications de servlet.

2
Jonathan Cole

J'ai une solution pour la même chose pour créer un utilitaire de pool de connexions qui peut vous aider à créer un pool de taille par défaut 10.

@Component public class ConnectionPool {private static final Logger logger = LoggerFactory.getLogger (ConnectionPool.class); int statique final privé MAX_POOL_SIZE_LIMIT = 10; private BlockingQueue activeConnectinoQueue = new LinkedBlockingQueue <> (); BlockingQueue privé usedConnectinoList = new LinkedBlockingQueue <> (); private int initialPoolSize = 5;

@Autowired
@Qualifier("dataSource")
private DataSource dataSource;

public void initConnectionPool() {
    logger.info("ConnectionPool initialization started.");
    if(activeConnectinoQueue.isEmpty() && usedConnectinoList.isEmpty()) {
        for (int i=0; i<initialPoolSize; i++) {
            createConnections();
        }
    }
    logger.info("ConnectionPool initialization completed. ConnectionPool size : {}", activeConnectinoQueue.size());
}

private void createConnections() {
    try {
        Connection connection = dataSource.getConnection();
        activeConnectinoQueue.add(connection);
    }catch (SQLException e) {
        logger.error("Error in getting connection from pool : ", e);
    }
}

public Connection getConnection() {
    if(activeConnectinoQueue.isEmpty()) {
        initConnectionPool();
    }
    Connection connection =  activeConnectinoQueue.remove();

    try {
        if(connection.isClosed()) {
            connection = dataSource.getConnection();
        }
    }catch (SQLException e) {
        logger.error("Error while getting connection from pool : ", e);
    }

    usedConnectinoList.add(connection);
    return connection;
}


public void releaseConnection(Connection connection) {
    if(connection != null) {
        usedConnectinoList.remove(connection);
        activeConnectinoQueue.add(connection);
    }
}

public void setInitialPoolSize(int initialPoolSize) {
    if(!(initialPoolSize < 0 || initialPoolSize > MAX_POOL_SIZE_LIMIT)) {
        this.initialPoolSize = initialPoolSize;
    }
}

public int getInitialPoolSize() {
    return initialPoolSize;
}

public int getConnectionPoolSize() {
    return activeConnectinoQueue.size() + usedConnectinoList.size();
}

public void setDataSource(AbstractDataSource dataSource) {
    this.dataSource = dataSource;
}

public void closeConnectionPool() {

    logger.info("Closing connectionPool started.");
    close(usedConnectinoList);
    close(activeConnectinoQueue);
    logger.info("ConnectionPool Closed.");
}

private void close(BlockingQueue<Connection> connectinosQueue) {
    for (int i=0; i<connectinosQueue.size(); i++) {
        Connection connection = connectinosQueue.remove();
        if(connection != null) {
            try {
                connection.close();
            } catch (SQLException e) {
                logger.error("Error in initializing connection pool : ", e);
            }
        }
    }
}

}

maintenant Pour le rendre sûr, nous devons attacher un objet d'usine ..

public enum ConnectionFactory {
CONNECTION;

private ConnectionPool connectionPool;
public void setConnectionPool(ConnectionPool connectionPool) {
    this.connectionPool = connectionPool;
}

public Connection getConnection() {
    return connectionPool.getConnection();
}

public void closeConnection() {
    connectionPool.closeConnectionPool();
}

public void releaseConnection(Connection connection) {
    connectionPool.releaseConnection(connection);
}

public int getConnectionPoolSize() {
    return connectionPool.getConnectionPoolSize();
}

@Component
public static class ConnectionBuilder {
    @Autowired
    private ConnectionPool connectionPool;

    public void setConnectionPool(ConnectionPool connectionPool) {
        this.connectionPool = connectionPool;
    }
    @PostConstruct
    public void postConstruct() {
        for (ConnectionFactory cfactory : EnumSet.allOf(ConnectionFactory.class)) {
            cfactory.setConnectionPool(connectionPool);
        }
    }
}

}

0