web-dev-qa-db-fra.com

Comment établir un pool de connexion dans JDBC?

Quelqu'un peut-il fournir des exemples ou des liens sur la manière d'établir un pool de connexions JDBC?

En effectuant une recherche sur Google, je vois différentes façons de procéder, ce qui est plutôt déroutant.

En fin de compte, j'ai besoin du code pour renvoyer un Java.sql.Connection objet, mais j'ai du mal à démarrer .. toutes les suggestions sont les bienvenues.

Mise à jour: Ne fait pas javax.sql ou Java.sql ont des implémentations de connexion groupées? Pourquoi ne serait-il pas préférable de les utiliser?

104
llm

Si vous avez besoin d'un pool de connexions autonome, ma préférence va à C3P sur DBCP (que j'ai mentionné dans ce réponse précédente ), je viens d'avoir trop de problèmes avec DBCP sous une charge lourde. L'utilisation de C3P0 est extrêmement 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 

Toutefois, si vous utilisez un serveur d'applications, je vous recommande d'utiliser le pool de connexions intégré qu'il fournit. Dans ce cas, vous devrez le configurer (voir la documentation de votre serveur d'applications) et récupérer un DataSource via JNDI:

DataSource ds = (DataSource) new InitialContext().lookup("jdbc/myDS");
99
Pascal Thivent

Généralement, si vous avez besoin d’un pool de connexions, vous écrivez une application qui s’exécute dans un environnement géré, c’est-à-dire que vous utilisez un serveur d’applications. Si tel est le cas, assurez-vous de () vérifiez les fonctions de mise en pool de connexions fournies par votre serveur d'applications avant d'essayer toute autre option.

La solution prête à l'emploi sera la mieux intégrée au reste des installations de serveurs d'applications. Si toutefois vous ne travaillez pas à l'intérieur d'un serveur d'applications, je vous recommande le composant DBCP d'Apache Commons. Il est largement utilisé et fournit toutes les fonctionnalités de pooling de base requises par la plupart des applications.

18
Tendayi Mawushe

Ne réinventez pas la roue.

Essayez l’un des composants tiers facilement disponibles:

  • Apache DBCP - Celui-ci est utilisé en interne par Tomcat, et par le vôtre sincèrement.
  • c3p0

Apache DBCP est livré avec un exemple différent sur la façon de configurer un pool javax.sql.DataSource . Voici un exemple qui peut vous aider à démarrer.

16

Je recommanderais d'utiliser la bibliothèque commons-dbcp . Il y a de nombreux exemples listés sur la façon de l'utiliser, voici le lien vers le déménagement simple . L'utilisation 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();

Il vous suffit de créer la source de données une seule fois. Assurez-vous donc de lire la documentation si vous ne savez pas comment procéder. Si vous ne savez pas comment écrire correctement les instructions JDBC afin de ne pas perdre de ressources, vous pouvez également lire cette page Wikipedia .

16
Eric Hauser

HikariCP

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

16
tobijdc

Dans le serveur d'applications que nous utilisons où je travaille (Oracle Application Server 10g, si je me souviens bien), le pooling est géré par le serveur d'applications. Nous récupérons un javax.sql.DataSource en utilisant une recherche JNDI avec un javax.sql.InitialContext .

c'est 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 a été copié à partir de cette documentation .)

7
Powerlord

À la fin de 2017, Proxool, BoneCP, C3P0, DBCP sont pour la plupart disparus à cette époque. HikariCP (créé en 2012) semble prometteur, fait disparaître tout ce que je connais. http://www.baeldung.com/hikaricp

Proxool a un certain nombre de problèmes:
- Sous forte charge, peut dépasser le nombre maximal de connexions et ne pas revenir en dessous
- Peut ne pas revenir aux connexions min, même après leur expiration
- Peut verrouiller le pool entier (et tous les threads serveur/client) s'il rencontre des difficultés pour se connecter à la base de données pendant le thread HouseKeeper (n'utilise pas .setQueryTimeout)
- Le thread HouseKeeper, alors qu'il dispose d'un verrou de pool de connexions pour son processus, demande au thread Prototyper de recréer les connexions (balayage), ce qui peut entraîner une condition de concurrence critique/un blocage. Dans ces appels de méthode, le dernier paramètre doit toujours être sweep: false pendant la boucle, seulement sweep: true en dessous.
- HouseKeeper n'a besoin que du balayage simple PrototypeController à la fin et a plus [mentionné ci-dessus]
]
- Le projet contient du code inachevé (propriétés définies mais non traitées)
- La durée de vie maximale par défaut de la connexion, si elle n'est pas définie, est de 4 heures (excessive)
- Le thread HouseKeeper s'exécute toutes les cinq secondes par pool (excessif)

Vous pouvez modifier le code et apporter ces améliorations. Mais comme il a été créé en 2003 et mis à jour en 2008, il lui manque près de 10 années d'améliorations Java utilisées par des solutions telles que hikaricp.

5
bluejaguar

Pool

  • Le mécanisme de mise en commun est le moyen de créer les objets à l’avance. Quand une classe est chargée.
  • Il améliore l'application performance [En utilisant le même objet pour effectuer toute action sur Object-Data] & memory [allouer et dé-allouer de nombreux objets crée une surcharge de gestion de la mémoire].
  • Le nettoyage des objets n'est pas nécessaire, car nous utilisons le même objet, ce qui réduit la charge de la récupération de place.

"Pooling [ Object pool, String pool constant, Thread Pool, pool de connexions]

Constante de chaîne

  • Le pool littéral de chaîne ne conserve qu'une copie de chaque valeur de chaîne distincte. qui doit être immuable.
  • Lorsque la méthode intern est appelée, elle vérifie la disponibilité des objets avec le même contenu dans le pool à l'aide de la méthode equals. "Si String-copy est disponible dans le pool, la référence est renvoyée. "Sinon, l'objet String est ajouté au pool et renvoie la référence.

Exemple: Chaîne à vérifier Objet unique depuis le 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 connexions utilisant le type 4 Pilote utilisant des 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 du pool de connexions, lorsque la classe est chargée, il récupère les objets _physical JDBC connection_ et fournit un objet de connexion physique encapsulé à l'utilisateur. PoolableConnection est un wrapper autour de la connexion réelle.

  • getConnection() choisissez l'une des connexions encapsulées libres de la connexion objectpool et le renvoie.
  • close() au lieu de la fermer, la connexion renvoyée est renvoyée au pool.

Exemple: utilisation du pool de connexions ~ 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.properties

_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" 8 heures par défaut] afin de rouvrir la connexion avec le DB sous-jacent.

Vous pouvez le faire pour tester chaque connexion en définissant testOnBorrow = true et validationQuery = "SELECT 1" et en n'utilisant pas le serveur autoReconnect for MySQL car il est obsolète. issue

_===== ===== 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 aussi ceux-ci:

5
Yash

Comme d'autres l'ont répondu, vous serez probablement satisfait de Apache Dbcp ou c3p . Les deux sont populaires et fonctionnent bien.

Concernant ton doute

Javax.sql ou Java.sql ne disposent-ils pas d'implémentations de connexion en pool? Pourquoi ne serait-il pas préférable de les utiliser?

Ils ne fournissent pas d'implémentations, mais plutôt des interfaces et des classes de support, qui ne concernent que les programmeurs qui implémentent des bibliothèques tierces (pools ou pilotes). Normalement, vous ne regardez même pas cela. Votre code doit traiter les connexions de votre pool comme s'il s'agissait de connexions "simples", de manière transparente.

4
leonbloy

Vibur DBCP est une autre bibliothèque à cette fin. Vous trouverez plusieurs exemples montrant comment le configurer pour une utilisation avec Hibernate, Spring + Hibernate ou par programmation, sur son site Web: http://www.vibur.org/

Voir également la clause de non-responsabilité ici .

4
Simeon Malchev

Apache Commons a une bibliothèque à cet effet: DBCP . À moins que vous n'ayez des exigences étranges autour de vos piscines, j'utiliserais une bibliothèque, car elle est plus délicate et plus subtile que vous ne le souhaiteriez.

3
sblundy

Vous devriez envisager d'utiliser UCP. niversal Connection Pool (UCP) est un pool de connexions Java. Il s'agit d'un pool de connexions riche en fonctionnalités et étroitement intégré aux bases de données Real Application Clusters (RAC), ADG et DG d'Oracle d'Oracle.

Reportez-vous à ceci page pour plus de détails sur UCP.

1
Nirmala

MiniConnectionPoolManager est une implémentation à un seul fichier Java, si vous recherchez une solution intégrable et que les performances ne vous préoccupent pas trop (même si je ne l'ai pas testée à cet égard) .

Il est multi-licence EPL , LGPL et MPL .

Sa documentation donne également des alternatives intéressantes à vérifier (en plus des formats DBCP et C3P0):

0
Matthieu