Dans ce TP, nous allons implémenter des requêtes SQL vers une base de données en utilisant le framework JDBC et en suivant le patron DAO (Data Access Object) et d'autres patrons de conception (fabrique, fabrique abstraite et singleton).
Les DAO sont des objets qui permettent de faire des accès de type CRUD sur une base de données, soit les opérations de base sur les données : Create, Read, Update, Delete. L'idée est d'avoir pour chaque table/élément, un point d'entrée de ce type qui va intégrer toute la mécanique SQL et rendre plus facile les accès en base (même s'il faudra étendre généralement les opérations du DAO avec des opérations plus complexes spécifiques aux données). L'architecture que nous allons utiliser est définie pour pouvoir facilement changer le support de persistance ou la méthode d'accès à ce support. Dans le prochain TP, nous remplacerons JDBC par JPA par exemple.
Coté Java, les données manipulées seront des classes Java classiques (des POJO) et le but des DAO est de faire le lien entre le contenu des objets de ces classes et leur stockage sur un support de persistance.
Dans ce qui suit, les explications techniques
correspondent à l'environnement de développement des salles de TP, à
savoir Eclipse comme IDE et MariaDB comme serveur SQL.
Vous pouvez utiliser un autre IDE (comme IntelliJ) ou un autre type de
serveur SQL. A vous dans ce cas d'adapter les explications qui
suivent.
Les données considérées concernent des disciplines sportives et des sportifs :
Connectez-vous au serveur MariaDB et exécutez les commandes suivantes pour créer les tables :
create table sport(code_sport int unsigned not null auto_increment, intitule varchar(20), primary key(code_sport));
create table discipline(code_discipline int unsigned not null auto_increment, intitule varchar(20), code_sport int unsigned, primary key(code_discipline), foreign key(code_sport) references sport(code_sport));
create table sportif(code_sportif int unsigned not null auto_increment, nom varchar(20), rue varchar(20), ville varchar(20), code_postal varchar(20), primary key(code_sportif));
create table pratique(code_sportif int unsigned, code_discipline int unsigned, primary key(code_sportif, code_discipline), foreign key(code_sportif) references sportif(code_sportif), foreign key(code_discipline) references discipline(code_discipline));
Rajoutez dans les tables sport et discipline les données présentées dans le transparent 5 du cours sur JDBC.
Maven est un outil de gestion et de production de projets que nous allons utiliser pour gérer les dépendances de nos projets Java. Maven permet de télécharger automatiquement des librairies Java (des fichiers de type .jar) qui sont utiles lors du développement d'un projet Java. Ici, nous aurons besoins de plusieurs librairies pour accéder à la base de données SQL en JDBC ou JPA ainsi que de lire des données dans des fichiers XML ou JSON. Les dépendances d'un projet sont précisées dans un fichier de configuration et les fichiers .jar associés sont téléchargés automatiquement par Maven (concrètement, ils sont placés dans le répertoire ".m2" se trouvant à la racine d'un compte utilisateur Linux ou dans "C:\Users\[MonCompte]" sous Windows).
Lancez Eclipse en version JEE. Utilisez de préférence un nouveau workspace.
Créez un projet Maven en cochant la case Create a simple project (skip archetype selection). Dans Group Id mettez ce que vous voulez (votre nom par exemple), dans Artifact Id et Name, mettez un nom simple comme "DAO" et rentrez quelques mots de description. Ne remplissez rien dans la section Parent Project et cliquez sur Finish.
A ce stade vous avez un projet Maven vide qui ne définit aucune dépendance. Nous avons besoin d'importer plusieurs librairies (concrètement, des fichiers .jar) :
A la racine du projet, vous avez un fichier "pom.xml" : c'est lui qui définit les dépendances du projet, que l'on rajoute soit en éditant le fichier à la main, soit en passant par des assistants de votre IDE. Ces dépendances sont ensuite automatiquement téléchargées et les .jar associés sont ajoutés à votre projet.
Le problème du Eclipse installé sur les ordinateurs des salles de TP est que parfois il n'arrive pas à se connecter à Internet ou à télécharger toutes les dépendances Maven. Donc selon que votre Eclipse arrive ou non à accéder correctement à Internet, vous utiliserez une des deux solutions suivantes pour configurer votre projet.
Si en créant votre projet Maven ou en modifiant les dépendances par la
suite, vous avez des erreurs et notamment une croix rouge sur le
fichier "pom.xml", sélectionnez le fichier dans l'explorateur et
forcez la mise à jour du projet par : clic droit -> Maven -> Update
Projet.
Si vous avez une erreur sur la première ligne du fichier "pom.xml", il
est possible que cela vienne de la fin de la ligne
: ... https://maven.apache.org/xsd/maven-4.0.0.xsd">
Enlevez simplement le "S" de https
pour
avoir http
S'il y a encore des erreurs, recommencez la manipulation de mise à
jour Maven en cochant la case Force Update of
Snapshots/Release.
Si le projet a toujours des erreurs, effacez le et créez un projet
Java classique. Passez alors à la solution 2 et quand vous importerez
les sources, modifiez la variable "configFile" de la classe
SQLConnection du package sportsDAO :
private static String configFile = "src/sportsDAO/configJDBC.xml";
Il est également possible qu'à la création d'un projet ou lors d'une
mise à jour des dépendances Maven, la version de Java utilisée par le
projet ne soit pas/plus la bonne. Par exemple, vous avez "JRE System
Library [J2SE-1.5]" dans l'explorateur Eclipse de votre projet, soit
un projet configuré pour fonctionner en Java 1.5.
Pour changer la version de Java, sélectionnez le JRE actuel dans
l'explorateur Eclipse, faites un clic droit -> Build Path ->
Configure Build Path... Sélectionnez le JRE actuel et cliquez
sur Edit.... Dans la liste Execution environment,
choisissez le JRE le plus récent en bas de la liste puis cliquez sur
Finish et Apply and Close. Vous devez maintenant voir
"JRE System Library [J2SE-17]" dans l'explorateur (ou une autre
version en fonction de votre système).
Ouvrez le fichier "pom.xml" et après la balise </description> et avant la balise </project>, rajoutez les dépendances suivantes en faisant un copier/coller :
<dependencies>
<dependency>
<groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.6</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>2.0.6</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>2.3.1</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>javax.persistence-api</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.4.21.Final</version>
</dependency>
</dependencies>
Faites un clic droit -> Source -> Format ou un Ctrl + Shift + F pour présenter correctement le XML. Si vous avez une ligne soulignée en rouge ou si le nom du fichier "pom.xml" dans l'arborescence du projet est affichée avec une croix rouge, c'est qu'il y a eu un problème.
Normalement, une fois le fichier sauvé (Ctrl S) et le temps pour Eclipse de télécharger les fichiers, vous devez voir apparaitre dans l'arborescence du projet un onglet "Maven Dependencies" dans lequel il y a un ensemble de fichiers .jar. Si ça n'est pas le cas, sélectionnez le fichier "pom.xml", faites un clic droit -> Maven -> Update Project.
Comme le nombre de fichiers est relativement important, le plus simple est de créer une librairie pour pouvoir la réutiliser facilement d'un projet à un autre. Voici les étapes à suivre :
Avant d'aller plus loin dans le TP, on peut déjà à ce stade s'assurer que la connexion au serveur MariaDB fonctionne et que l'on peut exécuter des requêtes SQL sur les tables.
Pour cela, créez une classe "TestJDBC" à la racine du projet (dans "src/main/java") qui contiendra le code suivant :
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class TestJDBC {
public static void main(String argv[]) {
try {
Connection conn = DriverManager.getConnection("URL", "LOGIN", "MDP");
System.out.println("Connexion JDBC OK");
Statement req = conn.createStatement();
ResultSet res = req.executeQuery("select * from sport");
System.out.println("La liste des sports : ");
while (res.next())
System.out.println(" - " + res.getString(2));
}
catch (Exception e) {
System.err.println("Erreur : " + e);
e.printStackTrace();
}
}
}
En remplaçant les chaines URL, LOGIN, MDP par respectivement l'URL de connexion JDBC, votre login et votre mot de passe pour le serveur MariaDB.
L'exécution de ce programme doit afficher la liste des sports enregistrés dans la table "sport" de votre base.
L'archive sources-SportsDAO.zip contient le code des DAO et des POJO. Placez les fichiers dans le répertoire "src/main/java" de votre projet Maven. Normalement le code ne doit pas présenter d'erreurs de compilation. Si c'est le cas, vérifiez les dépendances installées comme précisé ci-dessus.
En quelques mots, le contenu de ces sources est le suivant :
Sport
et Discipline
. Le but est coté Java de manipuler des
instances de ces classes et via les DAO d'en charger ou sauvegarder
le contenu dans la base SQL. Regardez bien les attributs des classes
et notamment les références croisées entre les 2 classes : ici on ne
s'intéresse pas aux clés étrangères comme dans les tables SQL mais à
des relations objets classiques. Néamoins, on a gardé un entier
relatif à la clé primaire qui a un rôle principalement technique et
non pas métier.DAO
: DAO générique qui est spécialisé par les
deux classes DAO_JDBC_Sport
et DAO_JDBC_Discipline
.DAOException
: exception levée en cas de
problème lors de l'utilisation des DAO.AbstractDAOFactory
et SportsDAOFactory
: la première est une fabrique
abstraite qui retourne une fabrique concrète typée par la
seconde et qui en pratique est une instance de
Sports_JDBC_DAOFactory
.SQLConnection
: permet de se connecter à la BDD
via une instance de ConfigJDBC
dont le contenu est
initialisé par la désérialisation du fichier
"configJDBC.xml".PersistenceKind
: énumération qui définit les
différents types de support de persistance. Pour l'instant, seul
le support JDBC est en partie implémenté.Lien vers la documentation Javadoc des classes.
TestDAO
se trouvant à la
racine des sources. Vous devez voir dans la console le nom du sport
d'identifiant 1 avec sa liste de disciplines. Dans la base de
données, vérifiez que le sport "Pétanque" et ses deux disciplines
"Doublette" et "Triplette" ont bien été rajoutés.TestDAO
: vous
pouvez constater que tout est typé de manière abstraite via
notamment DAO<Sport>
et DAO<Discipline>
en appelant uniquement les
méthodes génériques du DAO abstrait et en manipulant les instances
des POJO Sport
et Discipline
comme des
objets Java classiques sans y voir une seule ligne de SQL. La seule
ligne où on fait apparaitre le lien vers le support de persistance
concret est la première ligne pour instancier la factory avec l'item
"PersitenceKind.JDBC". L'idée est que dans le prochain TP, vous
implémenterez la version JPA des DAO et qu'il y aura juste cette
valeur à changer, le reste du code de TestDAO
ne
changera pas et réalisera les mêmes actions.DAO_JDBC_Discipline
pour implémenter les méthodes manquantes.Sportif
dans le package
"donnees". Définissez ses attributs en prenant soin de réfléchir à
ses relations avec le POJO Discipline
(qu'il sera nécessaire
également de modifier).Sportif
et rajoutez dans les classes existantes
des fabriques le code nécessaire pour ce DAO. Modifiez au besoin le
DAO concret pour Discipline
.Eric Cariou, dernière modification : 23/01/24