Pour parler avec un SGBD, il faut passer par un pilote, un morceau de programme qui sait utiliser le protocole de communication idoine. Il existe un pilote générique qui s'appuie sur le protocole le plus universel (ODBC), mais si vous souhaitez profiter des particularités et des optimisations d'un système spécifique, mieux vaut employer un pilote dédié, typiquement fourni par son éditeur.
Il est possible de trouver sur le site de MariaDB (avec un peu de persévérance) une
archive java (d'extension .jar
) qui contient le pilote en question et ses
dépendances. À l'IUT et sous Linux, vous trouverez cette archive avec le chemin
suivant : /export/documents/mariadb-client.jar
.
Pour que votre programme ait accès aux classes correspondantes, il faut s'y prendre en
deux temps. D'abord il faut dire aux outils java qu'il y a un nouvel emplacement pour les
classes, par le biais de l'option -cp
(pour class path) :
bob@box:~$ java -cp ".:/export/documents/mariadb-client.jar" MonProgramme
Notez bien que l'option -cp
prend en argument une liste de chemins séparés
par un caractère dépendant du système d'exploitation (:
sous Linux,
;
sous Windows). On y inclut toujours .
pour qu'il continue à
chercher les classes dans le répertoire courant. En général (mais pas pour ce sujet), il
est nécessaire de passer la même option lors de la compilation.
La deuxième précaution à prendre vous est déjà familière : dans votre code source, si vous souhaitez mentionner une classe de la bibliothèque externe, vous devez préciser son package, typiquement avec une instruction d'import.
import org.mariadb.jdbc.*;
On reconnait les packages des bibliothèques externes au fait qu'il ne commencent pas par java ou javax. Spécifiquement dans le cas du pilote MariaDB, un tel import est inutile car nous ne mentionnerons jamais les classes correspondantes.
Nous utiliserons ici le package java.sql de l'API officielle. Dans ce package, la classe DriverManager est responsable du choix du pilote lors d'une tentative de connexion.
Connection cnx = DriverManager.getConnection( "jdbc:mariadb://dwarves.iut-fbleau.fr/bob", "bob", "m0tdepasse");
Il est tout à fait possible que la connexion échoue, auquel cas vous devrez capturer une SQLException.
Il est également possible que le pilote approprié ne soit pas disponible, mais dans ce cas un autre pilote sera choisi et aucune erreur ne vous préviendra du problème. Il est recommandé de vérifier cette disponibilité avant la connexion.
Class.forName("org.mariadb.jdbc.Driver");
Cette instruction lèvera une ClassNotFoundException en cas de souci.
Pour donner des ordres au SGBD, il faut formuler une requête SQL. Pour éviter les ambigüités, nous allons préparer cette requête en deux fois : d'abord le SQL brut, puis les paramètres, c'est à dire les constantes numériques et textuelles qui sont susceptibles de changer d'une exécution à l'autre.
PreparedStatement pst = cnx.prepareStatement("INSERT INTO Mesure (valeur) VALUES (?)"); pst.setInt(1, 27); pst.executeUpdate(); pst.setInt(1, 84); pst.executeUpdate();
Notez bien que chacune de ces lignes est individuellement capable de générer une SQLException. Il est possible de répéter la même requête en changeant à chaque fois les paramètres afin d'optimiser les opérations sur la base.
Dans le cas où une requête génère une réponse de la part de la base, on emploie une méthode différente.
PreparedStatement pst = cnx.prepareStatement( "SELECT valeur FROM Mesure WHERE valeur BETWEEN ? AND ?"); pst.setInt(1, 50); pst.setInt(2, 100); ResultSet rs = pst.executeQuery();
L'objet de la classe ResultSet) ne contient pas nécessairement toutes les données de la réponse, car il peut y avoir beaucoup. À tout moment, il rend disponible une seule ligne. On peut changer la ligne visible par la méthode next, et dans certains cas first, last, ou previous. La plupart du temps, la ligne disponible peut avancer mais pas reculer.
Chaque ligne est typiquement composée de plusieurs colonnes, donc pour extraire une donnée de la ligne courante, on doit préciser la colonne (par son nom ou son numéro) et le type espéré.
while(rs.next()) { System.out.println(rs.getInt(1)); }
Remarque Toutes les méthodes présentées ici sont également susceptibles de lever des SQLException.
Les objets des classes ResultSet, PreparedStatement et Connection doivent être fermés lorsqu'ils ne sont plus utiles. En particulier, un PreparedStatement ne peut pas être employé pour envoyer une requête tant que le ResultSet précédemment obtenu n'est pas fermé. De plus, chacun de ces objets encore ouverts réserve des ressources du SGBD.
rs.close(); pst.close(); cnx.close();
En pratique, on peut économiser certaines lignes. Fermer une requête ferme également le jeu de données associé. Fermer une connexion ferme toutes les requêtes qu'elle a servi à créer. Dans l'exemple précédent, la troisième instruction suffirait à nettoyer correctement toutes les ressources exploitées.
Remarque Attention à la gestion des exceptions ! Vous devez nettoyer même en cas de problème. Il ne faut jamais sortir d'un programme avec une connexion ouverte car le SGBD mettra beaucoup de temps à réaliser qu'il n'y a plus personne au bout du fil.
Vote. Représentez les données de ce tableau dans votre base de données personnelle.
Compétiteur | Votants | Points |
---|---|---|
Pays-Bas | Italie | 5 |
Pays-Bas | Russie | 5 |
Italie | Pays-Bas | 16 |
Italie | Russie | 1 |
Russie | Pays-Bas | 5 |
Russie | Italie | 8 |
Écrivez en Java un programme qui prend en argument le pays d’un compétiteur et qui affiche la liste des points obtenus dans chaque autre pays, ainsi que le total. Ce programme doit marcher même si on ajoute des données dans vos tables.
bob@box:~$ java -cp "/export/documents/mariadb-client.jar:." Vote Italie Pays-Bas 16 Russie 1 --- Total 17
Remarque Prenez soin des ressources communes : dans tous les cas où vous avez ouvert une connexion avec le serveur MariaDB, vous devez impérativement la fermer proprement.
Victoire. Écrivez une application qui affiche le pays ayant le plus de points cumulés, ainsi que son score. Le bouton permet de rafraîchir l’affichage pour refléter les changements de la base de données.