5.2 - Establiment de la connexió
Un objecte de la classe Connection (de l'API JDBC) representarà una connexió a la Base de Dades d'un determinat SGBD. Haurem de tenir el controlador del SGBD inclós en el projecte (en el classpath), i millor si el tenim carregat en memòria amb la sentència Class.forName('nom de la classe del driver').
L'objecte Connection l'obtindrem a partir del DriverManager, que havíem comentat que és capaç de gestionar tots els drivers carregats en memòria (i amb Class.forName ens asseguràvem que estaven en memòria). El mètode que utilitzarem del DriverManager és el getConnection(url,usuari,password), on li passarem les dades de connexió a la Base de Dades d'aquesta manera:
- URL: cadena de connexió seguint el protocol JDBC. Comença sempre per jdbc, el nom del SGBD (separat per dos punts), i la manera d'arribar a la BD, també separat per 2 punts. Aquesta manera d'arribar a la BD dependrà del controlador del SGBD, però d'alguna manera harem d'especificar el servidor, el port de connexió i el nom de la BD o esquema a connectar.
- Usuari i contrasenya: encara que en alguns SGBD (com per exemple SQLite) no seran necessaris.
Aquestes són les url que utilitzarem:
- PostgreSQL: per connectar-nos al servidor situal a l'adreça 89.36.214.106, que escolta el port per defecte (5432), i a la Base de Dades anomenada geo_ad, la cadena serà:
jdbc:postgresql://89.36.214.106:5432/geo_ad
- Oracle: el tenim en un altre servidor, en l'adreça 94.177.240.173; el port per defecte d'Oracle és el 1521, i hem d'especificar la instància (la macro Base de Dades d'Oracle) que es diu orcl ; observeu que en la cadena no especifiquem l'esquema, que seria l'equivalent a la mini Base de Dades on volem connectar (en Oracle un usuari es connecta sempre al seu esquema). La cadena de connexió serà:
jdbc:oracle:thin:@94.177.240.173:1521:orcl
- MySQL: el servidor és el mateix de PostgreSQL, el port per defecte és 3306, i si volem connectar a la Base de Dades geo:
jdbc:mysql://89.36.214.106:3306/factura
- SQLite: no haurem d'especificar ni servidor ni port (ni posteriorment usuarini contrasenya); únicament el nom del fitxer amb la ruta. Si volem connectar a la Base de Dades situada en el directori /home/usuari/BD_SQLite, i anomenada proveta.sqlite:
jdbc:sqlite:/home/usuari/BD_SQLite/proveta.sqlite
Mirem quatre exemple de connexió, un per a cada Base de Dades de prova que tenim en els diferents SGBD que ens hem plantejat connectar. Observeu com només hem canviat la classe que carreguem amb Class.forName i la url, a banda de l'usuari i contrasenya, clar (en SQLite no hi haurà). I el millor de tot és que una vegada feta la connexió, farem el mateix tractament siga quin siga el SGBD al qual ens hem connectat, com veurem amb posterioritat.
- PostgreSQL
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class provaConnexioPostgreSQL {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
String url = "jdbc:postgresql://89.36.214.106:5432/geo_ad";
String usuari = "geo_ad";
String password = "geo_ad";
Class.forName("org.postgresql.Driver");
Connection con = DriverManager.getConnection(url, usuari, password);
System.out.println("Connexió completada");
con.close();
}
}
- Oracle
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class provaConnexioOracle {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
String url = "jdbc:oracle:thin:@94.177.240.173:1521:orcl";
String usuari = "scott";
String password = "tiger";
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection con = DriverManager.getConnection(url, usuari, password);
System.out.println("Connexió completada");
con.close();
}
}
- MySQL
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class provaConnexioMySQL {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
String url = "jdbc:mysql://89.36.214.106:3306/factura";
String usuari = "factura";
String password = "factura";
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection(url, usuari, password);
System.out.println("Connexió completada");
con.close();
}
}
- SQLite
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class provaConnexioSQLite {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
String url = "jdbc:sqlite:proveta.sqlite";
Class.forName("org.sqlite.JDBC");
Connection con = DriverManager.getConnection(url);
System.out.println("Connexió completada");
con.close();
}
}
Com que no hem posat ruta, crearà el fitxer proveta.sqlite en el directori actiu, és a dir, en l'arrel del projecte. També podríem posar la ruta d'aquesta manera:
String url = "jdbc:sqlite:/home/usuari/BD_SQLite/proveta.sqlite";
en aquest cas haureu de cuidar que existesca la ruta del fitxer, sinó es produirà una SQLException
Observem les següents qüestions en els quatre programes equivalents anteriors:
- Com ja hem comentat alguna vegada, la sentència Class.forName() no seria necessària en moltes aplicacions. Però ens assegura que hem carregat el driver, i per tant el DriverManager el sabrà gestionar.
- El DriverManager és capaç de trobar el driver adequat a través de la url proporcionada (sobretot si el driver està carregat en memòria), i és qui ens proporciona l'objecte Connection per mig del mètode getConnection(). Hi ha una altra manera d'obtenir el Connection per mig de l'objecte Driver, com veurem al final d'aquest pregunta, però també serà passant indirectament pel DriverManager.
- Si no es troba la classe del driver (per no tenir-lo en les llibreries del projecte, o haver escrit malament el seu nom) es produirà l'excepció ClassNotFoundException. És convenient tractar-la amb try ... catch, encara que en els exemples anteriors s'ha optat per fer throws per a simplificar-los.
- Si no es pot establir la connexió per alguna raó es produirà l'excepció SQLException. Igual que en al cas anterior, és convenient tractar-la amb try ... catch.
- L'objecte Connection mantindrà una connexió amb la Base de Dades des del moment de la creació fins el moment de tancar-la amb close(). És molt important tancar la connexió, no solament per alliberar la memòria del nostre ordinador (que en tancar l'aplicació s'alliberaria), sinó sobretot per tancar la sessió oberta en el Servidor de Bases de Dades.
- En el cas de SQLite només s'ha d'especificar la url. No hem dit ni usuari ni contrasenya, que no tenen sentit en aquest SGBD monousuari.
Una manera de connectar alternativa a les anteriors és utilitzant l'objecte Driver. La classe java.sql.Driver pertany a l'API JDBC, però no és instanciable, i tan sols és una interfície, per a que les classes Driver dels contenidors hereten d'ella i implementen la manera exacta d'accedir al SGBD corresponent. Com no és instanciable (no podem fer new Driver()) la manera de crear-lo és a través del métode getDriver() del DriverManager, que seleccionarà el driver adequat a partir de la url. Ja només restaran definir algunes propietats, com l'usuari i la contrasenya, i obtenir el Connection per mig del mètode connect()
La manera de connectar a través d'un objecte Driver és més llarga, però més completa ja que es podrien especificar més coses. I potser ajude a entendre el muntatge dels controladors dels diferents SGBD en Java.
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
public class provaConnexioPostgreSQLAmbDriver {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
String url="jdbc:postgresql://89.36.214.106:5432/geo_ad";
String usuari="geo_ad";
String password="geo_ad";
Driver driver = DriverManager.getDriver(url);
Properties properties = new Properties();
properties.setProperty("user", usuari);
properties.setProperty("password", password);
Connection con = driver.connect(url, properties);
System.out.println("Connexió completada a través de Driver");
con.close();
}
}
En aquest exemple s'ha optat per no carregar el driver amb Class.forName(). Segurament la major part de vegades funcionarà, però podria ser que no funcionara en un moment determinat. Com ja hem comentat, el Class.forName() ens assegura que estarà carregat en memòria.
Llicenciat sota la Llicència Creative Commons Reconeixement CompartirIgual 2.5