web-dev-qa-db-ja.com

javaで接続プールを作成するコードが必要

Javaで接続プールを作成するコードが必要ですか?接続プールがすでに使用されている同じオブジェクトを返さないことをどのように確認しますか?クライアントが接続プールから取り出した後に接続を閉じた場合、どうなりますか?

更新1:

これをSimple Javaの用語で作成し、マルチスレッド環境でどのように機能するかを確認したいと思います。どのメソッドが同期され、どのメソッドが同期されません。はいの場合、誰でもこのクラスにアクセスして接続プールを再初期化できますか?

アップデート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();
 }

}
30
mohan

Javaで接続プールを作成するコードが必要ですか?

質問はわかりませんが、別の接続プールを作成しないでください。 C3PApache DBCPProxool または-のような既存のソリューションを使用してください BoneCP (そのフィールドの新しいプレイヤー)。 C3P0を使用します。

接続プールがすでに使用されている同じオブジェクトを返さないことをどのように確認しますか?

接続がプールから借用されてまだ返されていない場合、接続はプール内になく、プールの別のクライアントに割り当てることができないためです(リソースは返されるまでプールから削除されます)。

クライアントが接続プールから取り出した後に接続を閉じた場合、どうなりますか?

クライアントがプールから取得する接続は、実際には _Java.sql.Connection_ ではなく、動作をカスタマイズする _Java.sql.Connection_ のラッパー(プロキシ)ですいくつかのメソッドの。 close()メソッドはそれらの1つであり、Connectionインスタンスをnot閉じますが、プールに返します。

46
Pascal Thivent

自分で書いてはいけません。あなたのためにこれを行うオープンソースで使いやすいライブラリーがたくさんあり、自分で作ろうとして遭遇するすべての問題を解決します。

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();
13
Ryan Elkins

このソースコードが役立つことを願っています 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

セマフォを使用するだけです。理想的には、接続プールとしてCP3OまたはDBCPを使用する必要があります。これで、セマフォに基づいて接続を調整できます。

Getを実行するたびに、SemaphoreからReleaseを取得してリリースします。セマフォ以上はスレッドセーフです。

6
Princesh

既存のいずれかを使用します。 Apache DBCP

プールによって返される接続は、多くの場合、アプリケーションからのclose()への呼び出しを「無視」するプロキシです。接続がプールに戻されると、再利用できます。また、プールは必要に応じて自動的に閉じて開き直します。

4
mhaller

アプリケーションがサーバーで実行される場合、サーバーがプーリングを処理するデータソースとして設定するか、単純なJavaクライアントがApache DBCP(データベースへの場合)を使用するか、またはApache Commons Pooling APIここを参照してください: Apache Commons

2
Phani

独自のconnpoolをロールするための1つの引数は、回避される設定と追加のjarです。サードパーティのインターフェイスを有効にして、成熟したconnpoolに交換できるようにする必要があることに同意しますが、独自の小さなソリューションを用意することはできます。同期ブロックと、connを使用可能としてマークするclose()を使用したconnラッパーを使用したSelf Cleaning Vectorは、サーブレットアプリで非常にうまく機能します。

2
Jonathan Cole

デフォルトサイズ10のプールの作成に役立つ接続プールユーティリティを作成するための同じ解決策が1つあります。

@Component public class ConnectionPool {private static final Logger logger = LoggerFactory.getLogger(ConnectionPool.class); private static final int MAX_POOL_SIZE_LIMIT = 10; private BlockingQueue activeConnectinoQueue = new LinkedBlockingQueue <>(); private BlockingQueue 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);
            }
        }
    }
}

}

今それを安全にするために、ファクトリオブジェクトをアタッチする必要があります。

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

}