Gestione dei Pool di Connessioni (Parte II)
Pagina 2 di 2
Sviluppo passo passo di una classe ConnectionPool in Java
Procediamo con lo sviluppo di codice Java in grado di gestire correttamente un pool di connessioni.
Costruiamo innanzitutto una classe ConnectionPoolException, le cui istanze sono le eccezioni che verranno sollevate quando si dovesse presentare un errore a runtime nella classe ConnectionPool.
// Classe che gestisce le eccezioni sollevate a runtime dalla
// classe ConnectionPool
public class ConnectionPoolException extends Exception {
public ConnectionPoolException() {
}
}
Ricordiamo che al pool di connessioni dovranno accedere processi distinti. E' necessatio quindi trovare un artificio per far si che tutti i processi accedano ad unica istanza della classe ConnectionPool.
L'idea è quella di avere una variabile statica connectionPool all'interno della classe ConnectionPool. Un metodo statico, getConnectionPool, permetterà di accedere a questa variabile da parte dei processi che ne fanno richiesta. Se la variabile non è stata ancora istanziata il metodo getConnectionPool provvederà alla sua istanziazione.
Dal momento che più processi accedono a getConnectionPool in concorrenza, definiamo il metodo come synchronized.
...
// La classe che gestisce un pool di connessioni
public class ConnectionPool {
...
// La variabile che gestisce l'unica istanza di ConnectionPool
private static ConnectionPool connectionPool = null;
...
public static synchronized ConnectionPool getConnectionPool()
throws ConnectionPoolException {
if(connectionPool == null) {
connectionPool = new ConnectionPool();
}
return connectionPool;
}
...
}
Il codice di getConnectionPool accede al costruttore della classe per creare l'unica istanza di ConnectionPool. Questo si preoccupa di creare la coda per le connessioni libere, caricare i parametri per l'accesso al database accedendo al metodo loadParameters e caricare il driver della base di dati con il metodo loadDriver.
Osserviamo che il costruttore è privato. In questo modo garantiamo che l'accesso ad esso avvenga solo tramite la funzione pubblica getConnectionPool.
import java.util.*;
...
// La classe che gestisce un pool di connessioni
public class ConnectionPool {
...
private Vector freeConnections; // La coda di connessioni libere
private String dbUrl; // Il nome del database
private String dbDriver; // Il driver del database
private String dbLogin; // Il login per il database
private String dbPassword; // La password di accesso al database
...
// Costruttore della classe ConnectionPool
private ConnectionPool() throws ConnectionPoolException {
// Costruisce la coda delle connessioni libere
freeConnections = new Vector();
// Carica I parametric per l'accesso alla base di dati
loadParameters();
// Carica il driver del database
loadDriver();
}
// Funzione privata che carica i parametri per l'accesso al database
private loadParameters() {
// Url per un database locale
dbUrl = "jdbc:mysql://localhost/prova";
// Driver per database mysql
dbDriver = "org.gjt.mm.mysql.Driver";
// Login della base di dati
dbLogin = "Login";
// Password per l'accesso al database
dbPassword = "Password";
}
// Funzione privata che carica il driver per l'accesso al database.
// In caso di errore durante il caricamento del driver solleva un'eccezione.
private loadDriver() throws ConnectionPoolException {
try {
java.lang.Class.forName(
dbDriver + "?user=" +
dbUser + "&password=" + dbPassword);
} catch (Exception e) {
throw new ConnectionPoolException();
}
}
...
}
Analizziamo la funzione getConnection che restituisce una connessione libera. getConnection verifica innanzitutto che ci siano elementi nella coda delle connessioni libere. Se la coda non è vuota, preleva la prima connessione e verifica che sia valida. Se la connessione non è più valida effettua una chiamata ricorsiva per prelevare l'elemento successivo.
Se la coda e' vuota, getConnection chiama newConnection per stabilire una nuova connessione. Il metodo getConnection è di tipo synchronized perché può essere richiamato da più processi concorrenti.
Il metodo newConnection non deve necessariamente essere synchronized perché viene richiamato da getConnection che già opera in mutua esclusione.
import java.sql.*;
...
// Il metodo getConnection restituisce una connessione libera prelevandola
// dalla coda freeConnections oppure se non ci sono connessioni disponibili
// creandone una nuova con una chiamata a newConnection
public synchronized Connection getConnection()
throws ConnectionPoolException {
Connection con;
if(freeConnections.size() > 0) {
// Se la coda delle connessioni libere non è vuota
// preleva il primo elemento e lo rimuove dalla coda
con = (Connection) freeConnections.firstElement();
freeConnections.removeElementAt(0);
try {
// Verifica se la connessione non è più valida
if(con.isClosed()) {
// Richiama getConnection ricorsivamente
con = getConnection();
}
} catch(SQLException e) {
// Se c'è un errore richiama GetConnection
// ricorsivamente
con = getConnection();
}
} else {
// se la coda delle connessioni libere è vuota
// crea una nuova connessione
con = newConnection();
}
// restituisce la connessione
return con;
}
// Il metodo newConnection restituisce una nuova connessione
private Connection newConnection() throws ConnectionPoolException {
Connection con = null;
try {
// crea la connessione
con = DriverManager.getConnection(dbUrl);
} catch(SQLException e) {
// in caso di errore solleva un'eccezione
throw new ConnectionPoolException();
}
// restituisce la nuova connessione
return con;
}
...
Una volta terminato l'uso della connessione si chiama il metodo releaseConnection per ritornare la connessione non più utilizzata nella coda.
Questo metodo come getConnection opera in regime di
concorrenza e deve quindi essere synchronized.
...
// Il metodo releaseConnection rilascia una connessione inserendola
// nella coda delle connessioni libere
public synchronized void releaseConnection(Connection con) {
// Inserisce la connessione nella coda
freeConnections.add(con);
}
..
Il codice completo
Potete scaricare il codice completo da qui.
Riferimenti
Accesso ai database da java:
Java database e programmazione client/server - Giuseppe
Naccarato - Apogeo
Java 2 Tecniche avanzate - Cay S. Horstmann e Gary Cornwell
- McGraw Hill
Tecniche per gestire eccezioni e per la programmazione
concorrente:
Java la guida completa - Patrick Naughton e Herbert Schildt
- Mc Graw Hill
Core Java - Gary Cornell e Cay S. Horstmann - Sunsoft
Press
Java Fondamenti di programmazione - Deitel & Deitel -
Apogeo
Sviluppo di siti web dinamici tramite servlet:
Java Servlet Programmino - Jason Hunter e Williiam Crawford
- O'Reilly
Accesso a database MySql da codice Java:
JSP Servlet e MySql - David Harms - McGraw Hill