Comment établir un pool de connexion dans JDBC?

est-ce que quelqu'un peut fournir des exemples ou des liens sur la façon d'établir un pool de connexion JDBC?

de la recherche google je vois beaucoup de façons différentes de faire ceci et il est assez confus.

finalement j'ai besoin du code pour retourner un objet java.sql.Connection , mais j'ai du mal à démarrer..toutes les suggestions de bienvenue.

mise à Jour: N'est pas javax.sql ou java.sql ont mis en commun de connexion implémentations? Pourquoi ne serait-il pas préférable d'utiliser ces?

101
demandé sur Luiggi Mendoza 2010-05-14 18:55:05

13 réponses

si vous avez besoin d'un pool de connexion autonome, ma préférence va à C3P0 au lieu de DBCP (que j'ai mentionné dans ce réponse précédente ), j'ai juste eu trop de problèmes avec le DBCP sous lourde charge. Utiliser C3P0 est très simple. De la documentation :

ComboPooledDataSource cpds = new ComboPooledDataSource();
cpds.setDriverClass( "org.postgresql.Driver" ); //loads the jdbc driver
cpds.setJdbcUrl( "jdbc:postgresql://localhost/testdb" );
cpds.setUser("swaldman");
cpds.setPassword("test-password");

// the settings below are optional -- c3p0 can work with defaults
cpds.setMinPoolSize(5);
cpds.setAcquireIncrement(5);
cpds.setMaxPoolSize(20);

// The DataSource cpds is now a fully configured and usable pooled DataSource 

mais si vous exécutez à l'intérieur d'un serveur d'application, je recommande d'utiliser la connexion intégrée piscine qu'il fournit. Dans ce cas, vous aurez besoin de le configurer (se référer à la documentation de votre serveur d'application) et de récupérer une source de données via JNDI:

DataSource ds = (DataSource) new InitialContext().lookup("jdbc/myDS");
97
répondu Pascal Thivent 2017-05-23 12:18:27

habituellement, si vous avez besoin d'un pool de connexion, vous écrivez une application qui tourne dans un environnement géré, c'est-à-dire que vous exécutez à l'intérieur d'un serveur d'application. Si c'est le cas, assurez-vous de vérifiez quelles fonctionnalités de mise en commun des connexions votre serveur d'application fournit avant d'essayer toute autre option.

la solution out-of-the-box sera la mieux intégrée avec le reste des serveurs d'application installation. Si toutefois vous n'utilisez pas un serveur d'application, je vous recommande le Apache Commons DBCP Component . Il est largement utilisé et offre toutes les fonctionnalités de base de mutualisation dont la plupart des applications ont besoin.

18
répondu Tendayi Mawushe 2010-05-14 18:09:55

ne réinvente pas la roue.

essayer l'un des composants tiers facilement disponibles:

Apache DBCP est livré avec un exemple différent sur la façon de configurer un pooling javax.SQL.Source de données . Voici un échantillon qui peut vous aider à obtenir commencé.

15
répondu Alexander Pogrebnyak 2011-11-18 14:12:03

je recommande d'utiliser la bibliothèque commons-dbcp . Il ya de nombreux exemples énumérés sur la façon de l'utiliser, voici le lien vers le mouvement simple un . L'usage est très simple:

 BasicDataSource ds = new BasicDataSource();
 ds.setDriverClassName("oracle.jdbc.driver.OracleDriver")
 ds.setUsername("scott");
 ds.setPassword("tiger");
 ds.setUrl(connectURI);
 ...
 Connection conn = ds.getConnection();

vous n'avez besoin de créer la source de données qu'une seule fois, alors assurez-vous de lire la documentation Si vous ne savez pas comment faire. Si vous n'êtes pas au courant de la façon d'écrire correctement les déclarations JDBC si vous ne divulguez pas de ressources, vous pourriez aussi vouloir lire cette page Wikipedia .

14
répondu Eric Hauser 2010-05-14 15:10:26

HikariCP

C'est moderne, c'est rapide, c'est simple. Je l'utilise pour chaque nouveau projet. Je préfère ça au C3P0, Je ne connais pas trop bien les autres piscines.

14
répondu tobijdc 2015-06-03 15:34:50

dans le serveur d'application que nous utilisons là où je travaille (Oracle Application Server 10g, si je me souviens bien), la mise en commun est gérée par le serveur d'application. Nous récupérons un javax.sql.DataSource en utilisant une recherche JNDI avec un javax.sql.InitialContext .

il fait quelque chose comme ça

try {     
   context = new InitialContext();
   jdbcURL = (DataSource) context.lookup("jdbc/CachedDS");
   System.out.println("Obtained Cached Data Source ");
}
catch(NamingException e)   
{  
    System.err.println("Error looking up Data Source from Factory: "+e.getMessage());
}

(nous n'avons pas écrit ce code, il est copié de cette documentation .)

7
répondu Powerlord 2010-05-14 15:49:47

comme répondu par d'autres, vous serez probablement heureux avec Apache Dbcp ou c3p0 . Les deux sont populaires et fonctionnent bien.

concernant votre doute

n'est pas javax.sql ou java.sql ont implémentations de connexion groupée? Pourquoi ne vaudrait-il pas mieux les utiliser?

ils ne fournissent pas des implémentations, mais plutôt des interfaces et un certain soutien classes, ne concernant que les programmeurs qui implémentent des bibliothèques tierces (pools ou drivers). Normalement, tu ne regardes même pas ça. Votre code devrait traiter les connexions de votre pool de la même manière qu'il s'agissait de connexions "simples", d'une manière transparente.

4
répondu leonbloy 2013-08-09 12:21:55

Vibur DBCP est une autre bibliothèque à cet effet. Plusieurs exemples montrant comment le configurer pour L'utiliser avec hibernation, printemps + hibernation, ou programmatiquement, peuvent être trouvés sur son site web: http://www.vibur.org /

Voir Aussi Le disclaimer ici .

4
répondu Simeon Malchev 2017-05-23 12:02:59

Piscine

  • mécanisme de mise en commun est la façon de créer les objets à l'avance. Quand une classe est chargée.
  • il améliore l'application performance [en réutilisant les mêmes objets pour effectuer n'importe quelle action sur Object-Data] & memory [l'allocation et la dé-allocation de nombreux objets crée une importante fonction de gestion de la mémoire].
  • nettoyage de L'objet n'est pas nécessaire car nous utilisons le même objet, ce qui réduit la charge de collecte des ordures.

" la Mutualisation [ Object piscine, String Constante de la Piscine, Thread Piscine, pool de Connexion]

Constante de Chaîne piscine

  • Chaîne de caractères littérale de la piscine ne conserve qu'un seul copie de chaque chaîne de valeur. qui doivent être immuables.
  • lorsque la méthode intern est invoquée, elle vérifie la disponibilité de l'objet avec le même contenu dans pool en utilisant la méthode equals. "Si la Chaîne de copie est disponible dans la Piscine puis retourne la référence. "Sinon, L'objet String est ajouté à la liste et renvoie la référence.

exemple: chaîne pour vérifier objet Unique de pool.

public class StringPoolTest {
    public static void main(String[] args) { // Integer.valueOf(), String.equals()
        String eol = System.getProperty("line.separator"); //java7 System.lineSeparator();

        String s1 = "Yash".intern();
        System.out.format("Val:%s Hash:%s SYS:%s "+eol, s1, s1.hashCode(), System.identityHashCode(s1));
        String s2 = "Yas"+"h".intern();
        System.out.format("Val:%s Hash:%s SYS:%s "+eol, s2, s2.hashCode(), System.identityHashCode(s2));
        String s3 = "Yas".intern()+"h".intern();
        System.out.format("Val:%s Hash:%s SYS:%s "+eol, s3, s3.hashCode(), System.identityHashCode(s3));
        String s4 = "Yas"+"h";
        System.out.format("Val:%s Hash:%s SYS:%s "+eol, s4, s4.hashCode(), System.identityHashCode(s4));
    }
}

pool de connexion utilisant le type-4 Driver utilisation de bibliothèques tierces[ DBCP2 , c3p0 , Tomcat JDBC ]

Type 4 - The Thin driver converts JDBC calls directly into the vendor-specific database protocol Ex[Oracle - Thick, MySQL - Quora]. wiki

dans le mécanisme de pool de connexion, quand la classe est chargée, il obtenir le physical JDBC connection " objets et fournit un objet de connexion physique enveloppé à l'utilisateur. PoolableConnection est une enveloppe autour de la connexion réelle.

  • getConnection() choisissez l'une des connexions emballées libres de la connexion objectpool et retournez-la.
  • close() au lieu de fermer, il renvoie la connexion enveloppée à la piscine.

exemple: Utilisation d'un Pool de connexion ~ DBCP2 avec Java 7[ try-with-resources ]

public class ConnectionPool {
    static final BasicDataSource ds_dbcp2 = new BasicDataSource();
    static final ComboPooledDataSource ds_c3p0 = new ComboPooledDataSource();
    static final DataSource ds_JDBC = new DataSource();

    static Properties prop = new Properties();
    static {
        try {
            prop.load(ConnectionPool.class.getClassLoader().getResourceAsStream("connectionpool.properties"));

            ds_dbcp2.setDriverClassName( prop.getProperty("DriverClass") );
            ds_dbcp2.setUrl( prop.getProperty("URL") );
            ds_dbcp2.setUsername( prop.getProperty("UserName") );
            ds_dbcp2.setPassword( prop.getProperty("Password") );
            ds_dbcp2.setInitialSize( 5 );

            ds_c3p0.setDriverClass( prop.getProperty("DriverClass") );
            ds_c3p0.setJdbcUrl( prop.getProperty("URL") );
            ds_c3p0.setUser( prop.getProperty("UserName") );
            ds_c3p0.setPassword( prop.getProperty("Password") );
            ds_c3p0.setMinPoolSize(5);
            ds_c3p0.setAcquireIncrement(5);
            ds_c3p0.setMaxPoolSize(20);

            PoolProperties pool = new PoolProperties();
            pool.setUrl( prop.getProperty("URL") );
            pool.setDriverClassName( prop.getProperty("DriverClass") );
            pool.setUsername( prop.getProperty("UserName") );
            pool.setPassword( prop.getProperty("Password") );
            pool.setValidationQuery("SELECT 1");// SELECT 1(mysql) select 1 from dual(oracle)

            pool.setInitialSize(5);
            pool.setMaxActive(3);
            ds_JDBC.setPoolProperties( pool );
        } catch (IOException e) {   e.printStackTrace();
        } catch (PropertyVetoException e) { e.printStackTrace(); }
    }

    public static Connection getDBCP2Connection() throws SQLException {
        return ds_dbcp2.getConnection();
    }

    public static Connection getc3p0Connection() throws SQLException {
        return ds_c3p0.getConnection();
    }

    public static Connection getJDBCConnection() throws SQLException {
        return ds_JDBC.getConnection();
    }
}
public static boolean exists(String UserName, String Password ) throws SQLException {
    boolean exist = false;
    String SQL_EXIST = "SELECT * FROM users WHERE username=? AND password=?";
    try ( Connection connection = ConnectionPool.getDBCP2Connection();
          PreparedStatement pstmt = connection.prepareStatement(SQL_EXIST); ) {
        pstmt.setString(1, UserName );
        pstmt.setString(2, Password );

        try (ResultSet resultSet = pstmt.executeQuery()) {
            exist = resultSet.next(); // Note that you should not return a ResultSet here.
        }
    }
    System.out.println("User : "+exist);
    return exist;
}

jdbc:<DB>:<drivertype>:<HOST>:<TCP/IP PORT>:<dataBaseName> jdbc: oracle :thin:@localhost:1521:myDBName jdbc: mysql ://localhost:3306/myDBName

connectionpool.propriétés

URL         : jdbc:mysql://localhost:3306/myDBName
DriverClass : com.mysql.jdbc.Driver
UserName    : root
Password    :

Web Application: pour éviter les problèmes de connexion lorsque toutes les connexions sont fermées[MySQL" wait_timeout " par défaut 8 heures] afin de rouvrir la connexion avec DB sous-jacente.

vous pouvez le faire pour tester chaque connexion en paramétrant testOnBorrow = true et validationQuery= "SELECT 1" et donot utiliser autoReconnect pour MySQL server car il est déprécié. problème

===== ===== context.xml ===== =====
<?xml version="1.0" encoding="UTF-8"?>
<!-- The contents of this file will be loaded for a web application -->
<Context>
    <Resource name="jdbc/MyAppDB" auth="Container" 
        factory="org.apache.tomcat.jdbc.pool.DataSourceFactory" 
        type="javax.sql.DataSource" 

        initialSize="5" minIdle="5" maxActive="15" maxIdle="10"

        testWhileIdle="true"
            timeBetweenEvictionRunsMillis="30000"

        testOnBorrow="true"
            validationQuery="SELECT 1"
            validationInterval="30000"


        driverClassName="com.mysql.jdbc.Driver" 
        url="jdbc:mysql://localhost:3306/myDBName" 
        username="yash" password="777"
    />
</Context>

===== ===== web.xml ===== =====
<resource-ref>
    <description>DB Connection</description>
    <res-ref-name>jdbc/MyAppDB</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
</resource-ref>
===== ===== DBOperations ===== =====
servlet «   init() {}
Normal call used by sevlet  « static {}

static DataSource ds;
static {
    try {
        Context ctx=new InitialContext();
        Context envContext = (Context)ctx.lookup("java:comp/env");
        ds  =   (DataSource) envContext.lookup("jdbc/MyAppDB");
    } catch (NamingException e) {   e.printStackTrace();    }
}

voir ceux-ci également:

4
répondu Yash 2017-05-23 11:55:03

Apache Commons possède une bibliothèque à cet effet: DBCP . À moins que vous n'ayez d'autres exigences autour de vos piscines, j'utiliserais une bibliothèque car elle est forcément plus délicate et plus subtile que vous ne l'espérez.

3
répondu sblundy 2010-05-14 15:10:04

à la fin de 2017 Proxool, BoneCP, C3P0, DBCP sont principalement défunts à ce moment. HikariCP (créé en 2012) semble prometteur, souffle les portes de tout ce que je sais d'autre. http://www.baeldung.com/hikaricp

Proxool a un certain nombre de questions:

- Sous forte charge peut dépasser le nombre maximum de connexions et ne pas revenir en dessous de max

- Peut réussir à ne pas revenir à des connexions min même après des connexions expiration

- Peut verrouiller l'ensemble du pool (et tous les threads serveur/client) s'il a des problèmes de connexion à la base de données pendant le thread HouseKeeper (ne pas utiliser .setQueryTimeout)

- Le thread HouseKeeper, tout en ayant le verrouillage du pool de connexion pour son processus, demande au thread Prototyper de recréer les connexions (sweep) qui peuvent entraîner des conditions de course/verrouillage. Dans ces appels de méthode, le dernier paramètre doit toujours être sweep: false pendant la boucle, seulement de balayage:true ci-dessous.

- HouseKeeper n'a besoin que de l'unique prototypecontroller balayage à la fin et a plus [mentionné ci-dessus]

- La femme de ménage vérifie le thread pour tester les connexions avant de voir quelles connexions peuvent être expirées [un certain risque de tester une connexion expirée qui peut être brisée/interrompue par d'autres temps d'arrêt vers le DB dans le pare-feu, etc.]

- Le projet a un code inachevé (propriétés qui sont définies mais pas suivi)

- La durée de vie par défaut de la connexion max si elle n'est pas définie est de 4 heures (excessive)

- Le fil de la femme de ménage court toutes les cinq secondes par Piscine (excessif)



Vous pouvez modifier le code et apporter ces améliorations. Mais comme il a été créé en 2003, et mis à jour en 2008, son manque de près de 10 ans d'améliorations java que les solutions comme hikaricp utilisent.

3
répondu bluejaguar 2017-12-13 23:33:06

MiniConnectionPoolManager est une implémentation de fichier java, si vous êtes à la recherche d'une solution intégrable et que vous n'êtes pas trop préoccupé par les performances (bien que je ne l'ai pas testé à cet égard).

Il est multi-licence EPL , LGPL et MPL .

sa documentation donne aussi des alternatives à vérifier (en plus de DBCP et C3P0):

0
répondu Matthieu 2016-10-13 13:25:07