Contexte
Vous avez des données sérialisées dans une base de données et vous souhaitez y accéder et les manipuler avec des objets Java. Cependant, votre entreprise est en pleine restructuration et vous ne savez pas si vos données vont :
- rester où elles sont ;
- migrer sur une autre base de données ;
- être stockées dans des fichiers XML ;
- ...
Comment faire en sorte de ne pas avoir à modifier toutes les utilisations de nos objets ?
Comment faire un système adaptatif aux futures modifications de supports de données ?
Comment faire en sorte que les objets que nous allons utiliser restent tels qu'ils sont ?
Il pourrait y avoir beaucoup de problématiques de ce genre, mais le pattern DAO est là pour vous !
La définition d'un design pattern est toujours un peu pompeuse et mystifiée ; par contre, et ceux qui ont lu les chapitres concernant les design patterns du tuto Java le confirmeront, ils apportent plus de souplesse et de robustesse à vos programmes !
Le pattern DAO
Ce pattern permet de faire le lien entre la couche d'accès aux données et la couche métier d'une application. Il permet de mieux maîtriser les changements susceptibles d'être opérés sur le système de stockage des données, donc, par extension, de préparer une migration d'un système à un autre (BDD vers fichiers XML par exemple...).
Ceci se fait en séparant accès aux données (BDD) et objets métiers (POJO).
Je me doute que tout ceci doit vous sembler très flou !
Euh... un peu...

C'est normal, mais ne vous en faites pas, je vais tout vous expliquer...
Déjà, il y a une histoire de séparation des "
couches métiers et couches d'accès aux données". Il s'agit ni plus ni moins de faire en sorte qu'un type d'objet se charge de récupérer les données dans la base et qu'un autre type d'objet (souvent des POJO) soit utilisé pour manipuler ces données. Schématiquement, ça nous donne :
Si on comprend bien, nous allons avoir deux types d'objets !
Tout à fait.
Les objets que nous avons créés plus haut sont nos POJO, les objets utilisés par le programme pour manipuler les données de la base.
Il ne nous reste plus qu'à créer les objets qui vont rechercher les données dans la base !
Oui, mais nous n'allons pas faire n'importe comment...
Les dits objets devront être capables de faire des recherches, des insertions, des mises à jour et des suppressions ! Par conséquent, nous pouvons définir un super type d'objet afin d'utiliser au mieux le polymorphisme...
Nous allons devoir créer une classe abstraite (ou une interface) mettant en oeuvre toutes les méthodes sus-mentionnées !
Comment va-t-on faire pour demander à nos objets DAO de récupérer tel type d'objet ou d'en sérialiser tel autre ? Avec des cast ?
Soit en castant, soit en faisant une classe générique ! Comme ceci :
Ah... mais oui !
Vous aviez oublié que nous pouvions créer des classes génériques ?
Bon, je vous pardonne. Maintenant, voyons un peu les codes sources de ces objets :
Secret (cliquez pour afficher)
Classe DAO.java
Code : Java 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 | package com.sdz.dao;
import java.sql.Connection;
import com.sdz.connection.SdzConnection;
public abstract class DAO<T> {
protected Connection connect = null;
/**
* Constructeur
* @param conn
*/
public DAO(Connection conn){
this.connect = conn;
}
/**
* Méthode de création
* @param obj
* @return
*/
public abstract boolean create(T obj);
/**
* Méthode pour effacer
* @param obj
* @return
*/
public abstract boolean delete(T obj);
/**
* Méthode de mise à jour
* @param obj
* @return
*/
public abstract boolean update(T obj);
/**
* Méthode de recherche des informations
* @param id
* @return
*/
public abstract T find(int id);
}
|
Classe EleveDAO.java
Code : Java 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48 | package com.sdz.dao.implement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.sdz.bean.Eleve;
import com.sdz.dao.DAO;
public class EleveDAO extends DAO<Eleve> {
public EleveDAO(Connection conn) {
super(conn);
}
public boolean create(Eleve obj) {
return false;
}
public boolean delete(Eleve obj) {
return false;
}
public Eleve find(int id) {
Eleve eleve = new Eleve();
try {
ResultSet result = this.connect .createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY
).executeQuery(
"SELECT * FROM eleve WHERE elv_id = " + id
);
if(result.first())
eleve = new Eleve(id, result.getString("elv_nom"), result.getString("elv_prenom"));
} catch (SQLException e) {
e.printStackTrace();
}
return eleve;
}
public boolean update(Eleve obj) {
return false;
}
}
|
Classe MatiereDAO.java
Code : Java 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56 | package com.sdz.dao.implement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.sdz.bean.Eleve;
import com.sdz.bean.Matiere;
import com.sdz.dao.DAO;
public class MatiereDAO extends DAO<Matiere> {
public MatiereDAO(Connection conn) {
super(conn);
}
public boolean create(Matiere obj) {
return false;
}
public boolean delete(Matiere obj) {
return false;
}
public Matiere find(int id) {
Matiere matiere = new Matiere();
try {
ResultSet result = this.connect .createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY
).executeQuery(
"SELECT * FROM matiere WHERE mat_id = " + id
);
if(result.first())
matiere = new Matiere(id, result.getString("mat_nom"));
} catch (SQLException e) {
e.printStackTrace();
}
return matiere;
}
public boolean update(Matiere obj) {
return false;
}
}
|
Classe ProfesseurDAO.java
Code : Java 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61 | package com.sdz.dao.implement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.sdz.bean.Eleve;
import com.sdz.bean.Professeur;
import com.sdz.dao.DAO;
public class ProfesseurDAO extends DAO<Professeur> {
public ProfesseurDAO(Connection conn) {
super(conn);
}
public boolean create(Professeur obj) {
return false;
}
public boolean delete(Professeur obj) {
return false;
}
public Professeur find(int id) {
Professeur professeur = new Professeur();
try {
ResultSet result = this.connect .createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY
).executeQuery(
"select * from professeur "+
"left join j_mat_prof on jmp_prof_k = prof_id AND prof_id = "+ id +
" inner join matiere on jmp_mat_k = mat_id"
);
if(result.first()){
professeur = new Professeur(id, result.getString("prof_nom"), result.getString("prof_prenom"));
result.beforeFirst();
MatiereDAO matDao = new MatiereDAO(this.connect);
while(result.next())
professeur.addMatiere(matDao.find(result.getInt("mat_id")));
}
} catch (SQLException e) {
e.printStackTrace();
}
return professeur;
}
public boolean update(Professeur obj) {
return false;
}
}
|
Classe ClasseDAO.java
Code : Java 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81 | package com.sdz.dao.implement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.sdz.bean.Classe;
import com.sdz.bean.Eleve;
import com.sdz.dao.DAO;
public class ClasseDAO extends DAO<Classe> {
public ClasseDAO(Connection conn) {
super(conn);
}
public boolean create(Classe obj) {
return false;
}
public boolean delete(Classe obj) {
return false;
}
public Classe find(int id) {
Classe classe = new Classe();
try {
ResultSet result = this.connect .createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY
).executeQuery(
"select * from classe WHERE cls_id = " + id
);
if(result.first()){
classe = new Classe(id, result.getString("cls_nom"));
result = this.connect .createStatement()
.executeQuery(
"select prof_id, prof_nom, prof_prenom from professeur " +
"INNER JOIN j_mat_prof on prof_id = jmp_prof_k " +
"INNER JOIN j_cls_jmp on jmp_id = jcm_jmp_k AND jcm_cls_k = " + id
);
ProfesseurDAO profDao = new ProfesseurDAO(this.connect);
while(result.next())
classe.addProfesseur(profDao.find(result.getInt("prof_id")));
EleveDAO eleveDao = new EleveDAO(this.connect);
result = this.connect .createStatement()
.executeQuery(
"select elv_id, elv_nom, elv_prenom from eleve " +
"INNER JOIN classe on elv_cls_k = cls_id AND cls_id = " + id
);
while(result.next())
classe.addEleve(eleveDao.find(result.getInt("elv_id")));
}
} catch (SQLException e) {
e.printStackTrace();
}
return classe;
}
public boolean update(Classe obj) {
return false;
}
}
|
Pour ne pas compliquer la tâche, je n'ai détaillé que la méthode de recherche des données, les autres sont des coquilles vides...
Mais vous devriez être capables de faire ça tout seuls, normalement...