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?
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");
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.
Ne réinventez pas la roue.
Essayez l’un des composants tiers facilement disponibles:
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.
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 .
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.
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 .)
À 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.
Pool
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]."Pooling [ Object
pool, String
pool constant, Thread
Pool, pool de connexions]
Constante de chaîne
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:
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.
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 .
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.
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.
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):