Vous êtes sur la page 1sur 20

1

Partie 3 : Modles de persistance


DAO - Data Access Object
Problmatique et dfinitions
Diagramme de classes du modle DAO
Diagramme de squences du modle DAO
Oprations CRUD
DAO et Exceptions
Utilisation des DAO
DAO t C i DAO et Connexion
DAO et Transaction
DAO et Hritage
Fabrique de DAO
Prsentation du TP JDBC/DAO
MaudeManouvrier - Univ. Paris Dauphine 42
Modles de persistance :
DAO - Data Access Object (1/2)
Problmesrsoudre:
Variationducodedepersistanceenfonction:
Du type de support de persistance (BD relationnelle BD objet Du type de support de persistance (BD relationnelle, BD objet,
fichiers, etc.)
DesdiffrentesimplmentationsdesfournisseursdeSGBD
Difficult changer de support de persistance en cas
dimbricationducodedepersistanceet ducodemtier
Solution:
Sparationdesentres sortiesdesclassesmtier
MaudeManouvrier - Univ. Paris Dauphine repris et adapt de [Grin05] et du Core J2EE Patterns - Data Access Object 2001-2002
de Sun Microsystems http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html
43
Sparationdesentres-sortiesdesclassesmtier
Utilisation dun objet particulier - objet daccs aux
donnes - pour abstraireet encapsuler lesaccsauxdonnes
DAO: Motif deconception galement connusous le
nomdeData Mapper (M. Fowler)
2
Modles de persistance :
DAO - Data Access Object (2/2)
DiffrenceentreunDAOet unactive record :
Les objets manipulant les donnes nont pas accs au
code permettant de sauvegarder ces donnes dans la code permettant de sauvegarder ces donnes dans la
base
UtilitdesDAO:
Faciliter lamodificationdumodledebasededonnes
Factoriser lecodedaccsauxdonnes
MaudeManouvrier - Univ. Paris Dauphine repris et adapt de [Grin05] et du Core J2EE Patterns - Data Access Object 2001-2002
de Sun Microsystems http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html
44
Faciliter loptimisationdes accs labaseenles regroupant
auseindobjetsparticuliers
Placement des DAO dans la couche daccs aux
donnes
Diagramme de classes du modle de
conception DAO (1/2)
MaudeManouvrier - Univ. Paris Dauphine
45
Figure reprise de Core J2EE Patterns - Data Access Object 2001-2002 de Sun Microsystems
http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html
3
Diagramme de classes du modle de
conception DAO (2/2)
Objet mtier (Business Object) :
Donnesvuespar leclient
Objet ncessitant laccs et lestockagededonnes depuis lesupport de Objet ncessitant l accs et lestockagededonnes depuis lesupport de
persistance
Objet pouvant treimplmentpar uneEJB session, EJ B entit, or tout
autre objet J ava en association avec un servlet ou une helper bean qui
accdentlasourcededonnes.
Objet daccs aux donnes (Data Access Object) :
Abstraction delimplmentation delaccs aux donnes pour rendrecet
accstransparentvisvisdelobjetmtier
MaudeManouvrier - Univ. Paris Dauphine repris et adapt de [Grin05] et du Core J2EE Patterns - Data Access Object 2001-2002
de Sun Microsystems http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html
46
Dlgation des oprations de sauvegarde et de rcupration de lobjet
mtier verslobjetdaccsauxdonnes
Source de donnes (Data source) : BDrelationnelle, BDobjet, fichiers, etc.
Objet de transfert (Data Transfert Object - DTO) : Objet detransport des
donnesentrelacouchedaccsauxdonneset lacouchemtier
Diagramme de squences du modle DAO
MaudeManouvrier - Univ. Paris Dauphine
47
Figure reprise de Core J2EE Patterns - Data Access Object 2001-2002 de Sun Microsystems
http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html
4
Oprations CRUD (1/5)
Implmentation par les DAO des 4 oprations
debasedepersistanceCRUD:
Create : crationdunenouvelleentit
Retrieve : recherche dune ou plusieurs
entits
Update : modificationduneentit
MaudeManouvrier - Univ. Paris Dauphine repris et adapt de [Grin05]
48
Delete : suppressionduneentit
Plusieurs variantes de signatures pour ces
mthodesdanslesDAO
Oprations CRUD (2/5)
Create
Paramtres: ltat delanouvelleentittransmispar
U i d d d ib l i l Unesriedeparamtres detypedes attributs solution la
pluscourante
Unobjet DTO
Unobjet mtier rendrepersistant
Typeretour :
voi d
MaudeManouvrier - Univ. Paris Dauphine repris et adapt de [Grin05]
49
bool ean - pour indiquer si lacrationapuavoir lieu
Un identificateur dentit utile en cas de gnration
automatiquedidentificateur
Unobjet mtier ouunDTOcorrespondant lentitcre
5
Oprations CRUD (3/5)
Retrieve
Retour dunobjet
P t id tifi t d l tit h h Paramtre: identificateur delentitrecherche
Retour : un objet mtier ou un DTO contenant les donnes de
lentitrecherche
Retour dunecollection dobjets
Paramtre: objet ouvaleurscritresderechercheouunobjet
exemple
R ll i
MaudeManouvrier - Univ. Paris Dauphine repris et adapt de [Grin05]
50
Retour : Resul t Set ou RowSet ou collection
(Col l ect i on, Set , Li st ) dobjetsmtier ouDTO
Retour dunevaleur calcule
Possibilitdecalculer unevaleur partir desobjetsenmmoire
Meilleur choix: interroger directement labase
Oprations CRUD (4/5)
Update
Diversesvariantesdeparamtres:
Identificateur +valeurs (plusieurs paramtres pour
lesvaleursouunDTO)
Objet mtier correspondant lentit modifier
danslabase
Typeretour :
MaudeManouvrier - Univ. Paris Dauphine repris et adapt de [Grin05]
51
Typeretour :
voi d
bool ean - pour indiquer si la mise jour a pu
avoir lieu
6
Oprations CRUD (5/5)
Delete
Diversesvariantesdeparamtres:
Identificateur delentitsupprimer danslabase
Objet mtier correspondant lentit supprimer
danslabase
Typeretour :
MaudeManouvrier - Univ. Paris Dauphine repris et adapt de [Grin05]
52
voi d
bool ean - pour indiquer si la suppression a pu
avoir lieu
DAO et Exceptions
Possibilitdelancer ouattraper des exceptions Possibilitdelancer ouattraper des exceptions
dans les mthodes des DAO car oprations
dentres/sorties
Ne pas lier les exceptions un type de DAO
particulier pour pouvoir facilement enchanger
MaudeManouvrier - Univ. Paris Dauphine repris et adapt de [Grin05]
53
particulier pour pouvoir facilement enchanger
7
Utilisation des DAO (1/3)
2stratgies:
DAO rfrenc par chaque objet mtier pour sa propre
persistance persistance
Aucune connaissance des DAO par les programmes
qui manipulent lesobjetsmtiers
Ncessit dune rfrence vers le DAO utilis (ex.
obtenuepar unemthodest at i c delaclasseDAO)
DAO directement manipuls par les programmes qui
i l l bj i
MaudeManouvrier - Univ. Paris Dauphine repris et adapt de [Grin05]
54
manipulent lesobjetsmtier
PasderfrenceauxDAOpar lesobjetsmtier
Stratgielaplussouvent utilise
- PertedelapuretdelaprogrammationOO
Utilisation des DAO (2/3)
class Departement {
private DepartementDAO dao;
Rfrence
au DAO
Exemple pour la stratgie 1 :
public void devientPersistant() {
dao = getDAO();
dao.insertOrUpdate(this);
}
private DepartementDAO getDAO() {
if (dao == null)
Possibilit
de passer
un DTO
MaudeManouvrier - Univ. Paris Dauphine repris et adapt de [Grin05]
55
if (dao null)
DepartementDAO.getDAO();
return dao;
}
...
}
Grer les exceptions
8
Utilisation des DAO (3/3)
DepartementDAO deptDAO = DepartementDAO.getDAO();
int idDepartement = deptDAO.create("1","MIDO",...);
Exemple pour la stratgie 2 :
p p ( , , );
Departement dept = deptDAO.findById(idDepartement);
deptDAO.update(idDepartement, ...);
DTO
ou objet mtier
Nouvelles valeurs
pour lentit
D
dept.setNom("Mathmatiques,
MaudeManouvrier - Univ. Paris Dauphine repris et adapt de [Grin05]
56
Departement
List<Departement> liste = deptDAO.findAll();
dept.setNom( Mathmatiques,
Informatique, Dcision et
Organisation");
deptDAO.update(dept);
ou bien
DAO et Connexion
Connexion et dconnexion au sein des
mthodesdesDAO
- Cot lev sans utilisation de pool de
connexions
Mthodes spcifiques de connexion et de
dconnexionspar DAO
MaudeManouvrier - Univ. Paris Dauphine repris et adapt de [Grin05]
57
+ Utilisation dune mme connexion par
plusieursmthodesduDAO
9
DAO et Transaction
Le+souvent : dbut et findelatransaction
i d h th d d DAO greauseindechaquemthodedeDAO
Dans les cas complexes : intervention au
sein dune mme transaction de plusieurs
mthodes de DAO associs diffrents
typesdobjetsmtier
MaudeManouvrier - Univ. Paris Dauphine repris et adapt de [Grin05]
58
typesd objetsmtier
Gestiondestransactionspar leclient
DAO et Hritage (1/2)
Problme : rendre persistantes via une classe
fille des proprits pr i vat e de sa classe fille des proprits pr i vat e de sa classe
mre
Solution: Utilisationdunehirarchieparallle
declassesmappers
TransmissionauDAOdesdonnesncessaires
MaudeManouvrier - Univ. Paris Dauphine repris et adapt de [Grin05]
59
TransmissionauDAOdesdonnesncessaires
pour les changes avec la BD par chaque
classemapper
10
DAO et Hritage (2/2)
MaudeManouvrier - Univ. Paris Dauphine repris de http://www.martinfowler.com/eaaCatalog/inheritanceMappers.html
60
Exemple de hirarchie
de classes
Exemple de hirarchie
de classes mappers
Fabrique de DAO (1/10)
DAO Factory :
U ili i d f b i / Utilisationdunefabriquepour crer/rcuprer
un DAO et donc cacher le type concret de la
classeduneinstanceencration
Fabrique abstraite : pour cacher le type rel
dunensembledefabriquesconcrtes
MaudeManouvrier - Univ. Paris Dauphine repris et adapt de [Grin05]
61
d unensembledefabriquesconcrtes
Fabriques concrtes : pour fournir tous les
DAO (de chaque objet mtier) associs une
certainesourcededonnes
11
Fabrique de DAO (2/10)
Fabrique
abstraite
Fabriques
concrtes
MaudeManouvrier - Univ. Paris Dauphine repris de http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html
62
DAO crs
Fabrique de DAO (3/10)
Cration de tous les DAO
associs une source de
donnes par la fabrique
concrte
MaudeManouvrier - Univ. Paris Dauphine repris de http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html
63
12
Fabrique de DAO (4/10)
Exemple :
MaudeManouvrier - Univ. Paris Dauphine repris de http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html
64
Fabrique de DAO (5/10)
// Abstract class DAO Factory
public abstract class DAOFactory
{ // List of DAO types supported by the factory
public static final int CLOUDSCAPE = 1;
public static final int ORACLE = 2;
public static final int SYBASE = 3; ...
// There will be a method for each DAO that can be created.
// The concrete factories will have to implement these methods.
public abstract CustomerDAO getCustomerDAO();
public abstract AccountDAO getAccountDAO();
public abstract OrderDAO getOrderDAO(); ...
bli t ti DAOF t tDAOF t (i t hi hF t ) {
MaudeManouvrier - Univ. Paris Dauphine repris de http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html
65
public static DAOFactory getDAOFactory(int whichFactory) {
switch (whichFactory) {
case CLOUDSCAPE: return new CloudscapeDAOFactory();
case ORACLE : return new OracleDAOFactory();
case SYBASE : return new SybaseDAOFactory(); ...
default : return null; }
}
}
13
Fabrique de DAO (6/10)
// Cloudscape concrete DAO Factory implementation
public class CloudscapeDAOFactory extends DAOFactory {
// method to create Cloudscape connections
public static Connection createConnection() {
// Use DRIVER and DBURL to create a connection // Use DRIVER and DBURL to create a connection
// Recommend connection pool implementation/usage
}
public CustomerDAO getCustomerDAO() {
// CloudscapeCustomerDAO implements CustomerDAO
return new CloudscapeCustomerDAO();
}
public AccountDAO getAccountDAO() {
// CloudscapeAccountDAO implements AccountDAO
return new CloudscapeAccountDAO();
MaudeManouvrier - Univ. Paris Dauphine repris de http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html
66
p ();
}
public OrderDAO getOrderDAO() {
// CloudscapeOrderDAO implements OrderDAO
return new CloudscapeOrderDAO();
}
...
}
Fabrique de DAO (7/10)
// Interface that all CustomerDAOs must support
public interface CustomerDAO {
public int insertCustomer(...);
public boolean deleteCustomer(...);
public Customer findCustomer(...);
public boolean updateCustomer(...);
public RowSet selectCustomersRS(...);
public Collection selectCustomersTO( );
MaudeManouvrier - Univ. Paris Dauphine repris de http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html
67
public Collection selectCustomersTO(...); ...
}
14
Fabrique de DAO (8/10)
// CloudscapeCustomerDAO implementation of the CustomerDAO interface.
// This class can contain all Cloudscape specific code and SQL statements.
// The client is thus shielded from knowing these implementation details.
public class CloudscapeCustomerDAO implements CustomerDAO {
public CloudscapeCustomerDAO() { // initialization } p p () { // }
// The following methods can use CloudscapeDAOFactory.createConnection()
// to get a connection as required
public int insertCustomer(...) {
// Implement insert customer here.
// Return newly created customer number or a -1 on error
}
public boolean deleteCustomer(...) {
// Implement delete customer here
// Return true on success, false on failure
MaudeManouvrier - Univ. Paris Dauphine repris de http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html
68
}
public Customer findCustomer(...) {
// Implement find a customer here using supplied argument values
// as search criteria
// Return a Transfer Object if found,
// Return null on error or if not found
}
...
}
Fabrique de DAO (9/10)
//Customer Transfer Object
public class Customer implements java io Serializable { public class Customer implements java.io.Serializable {
// member variables
int CustomerNumber;
String name;
String streetAddress;
String city;
...
MaudeManouvrier - Univ. Paris Dauphine repris de http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html
69
// getter and setter methods
...
...
}
15
Fabrique de DAO (10/10)
// Client code
// create the required DAO Factory
DAOFactory cloudscapeFactory =
DAOFactory.getDAOFactory(DAOFactory.DAOCLOUDSCAPE);
// Create a DAO
C t DAO tDAO l d F t tC t DAO() CustomerDAO custDAO = cloudscapeFactory.getCustomerDAO();
// create a new customer
int newCustNo = custDAO.insertCustomer(...);
// Find a customer object. Get the Transfer Object.
Customer cust = custDAO.findCustomer(...);
// modify the values in the Transfer Object.
cust.setAddress(...);
cust.setEmail(...);
// update the customer object using the DAO
custDAO.updateCustomer(cust);
// d l t t bj t
MaudeManouvrier - Univ. Paris Dauphine repris de http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html
70
// delete a customer object
custDAO.deleteCustomer(...);
// select all customers in the same city
Customer criteria=new Customer();
Criteria.setCity("New York");
Collection customersList = custDAO.selectCustomersTO(criteria);
// returns customersList - collection of Customer Transfer Objects.
// iterate through this collection to get values. ...
TP JBDC/DAO (1/10)
ht t p: / / www. l amsade. dauphi ne. f r / ~manouvr i / HI BERNATE/ TP_J DBC/ TP_J DBC. ht ml
Donnes:
Unebasededonnesexemple(sousformedescripts SQL) gresous Unebasededonnesexemple(sousformedescripts SQL), gresous
PostgreSQL
Un programme J ava exemple (Test J DBCPost gr esql . j ava)
contenantlesprincipalescommandesJ DBC
Une classe Java (Conf i gConnect i on. j ava) pour grer les
connexionslabasededonnes
Uneclasseexemple(typeActive record - Depar t ement . j ava)
MaudeManouvrier - Univ. Paris Dauphine
71
Unprogramme(Cr eer Depar t ement . j ava) permettant detester la
classe
Travail raliser : Dvelopper 3DAO
16
TP JBDC/DAO (2/10)
Connexion la BD
import java.sql.*;
public class TestJDBCPostgresql
{ Connection db=null; // Connexion la BD
Statement sql=null; // Curseur pour la requte tate e t sq u ; // u seu pou a equte
DatabaseMetaData dbmd; // Mta-donnes issues du driver
public TestJDBCPostgresql(String argv[])
throws ClassNotFoundException, SQLException, java.io.IOException
{
String database = argv[0];
String username = argv[1];
String password = argv[2];
MaudeManouvrier - Univ. Paris Dauphine
72
String password = argv[2];
Class.forName("org.postgresql.Driver"); // Rcupration du driver
db = DriverManager.getConnection("jdbc:postgresql:"+database,
username,
password); // Connexion
TP JBDC/DAO (3/10)
Excution dune requte de MJ
sql = db.createStatement(); // Cration du curseur pour la requte
String sqlText = "CREATE TABLE Note ( Note_ID SERIAL, " +
"Etudiant_ID integer, " +
"Inscription ID integer " + "Inscription_ID integer," +
"Note real," +
"CONSTRAINT PK_Notes PRIMARY KEY (Note_ID)," +
"CONSTRAINT FK_Notes_Etudiant FOREIGN KEY (Etudiant_ID) " +
" REFERENCES Etudiant (Etudiant_ID)," +
" CONSTRAINT FK_Notes_Inscription " +
" FOREIGN KEY (Inscription_ID) " +
" REFERENCES Inscription (Inscription_ID) " +
)
MaudeManouvrier - Univ. Paris Dauphine
73
" );";
System.out.println("Executing this command: "+sqlText+"\n");
sql.executeUpdate(sqlText); // Excution de la requte
db.commit(); // Validation de la requte
17
TP JBDC/DAO (4/10)
Excution dune requte dinterrogation
sqlText="SELECT capacite FROM Salle " +
"WHERE Batiment ='B' " +
"AND Numero_Salle='020' FOR UPDATE";
S t t i tl ("E ti thi d "+ lT t+"\ ") System.out.println("Executing this command : "+sqlText+"\n");
ResultSet rset = sql.executeQuery(sqlText);
// Pour afficher le rsultat de la requte
while (rset.next()) {
System.out.println("Capacit de la salle B020 : "
+ rset.getInt(1) + "\n");
MaudeManouvrier - Univ. Paris Dauphine
74
}
TP JBDC/DAO (5/10)
Excution dune requte de MJ paramtrable
System.out.println("\n\nNow demostrating a prepared statement...");
sqlText = "INSERT INTO Salle VALUES (?,?,?)";
System.out.println("The Statement looks like this: "+sqlText+"\n");
System.out.println("Looping several times filling in the fields...\n");
PreparedStatement ps = db prepareStatement(sqlText); PreparedStatement ps = db.prepareStatement(sqlText);
// Excution dune requte paramtre
String [] NumBatiment = {"A", "B", "C", "P", "D"};
String [] NumSalle = {"208", "026", "405", "340", "120"};
int lenNB = NumBatiment.length;
for (int i=0, c=30 ; (i<lenNB) && (c<35) ;c++,i++)
{ System.out.println(i+" " + NumBatiment[i]+ " " + NumSalle[i]+ "...\n");
ps.setString(1,NumBatiment[i]); //Affectation de la colonne 1(Batiment)
MaudeManouvrier - Univ. Paris Dauphine
75
p g( , [ ]) ( )
ps.setString(2,NumSalle[i]);; // Affectation de la colonne 2(Numero_Salle)
ps.setInt(3,c); //Affectation de la colonne 3(Capacite)
ps.executeUpdate();
}
db.commit();
ps.close();
18
TP JBDC/DAO (6/10)
Classe de connexion
public class ConfigConnection {
public static Connection getConnection(String nomFichierProp)
throws IOException, ClassNotFoundException, SQLException {
Properties props = new Properties();
URL urlFichierProp = ConfigConnection.class.getResource(nomFichierProp);
B ff dI tSt bi ll BufferedInputStream bis = null;
try {
bis = new BufferedInputStream(urlFichierProp.openStream());
props.load(bis);
String driver = props.getProperty("driver");
String url = props.getProperty("url");
String utilisateur = props.getProperty("utilisateur");
String mdp = props.getProperty("mdp");
Class.forName(driver);
MaudeManouvrier - Univ. Paris Dauphine
76
return DriverManager.getConnection(url, utilisateur, mdp);
}
finally {
if (bis != null) {
bis.close();
}
}
}
TP JBDC/DAO (7/10)
Utilisation de la classe de Connexion
String username = argv[0];
String password = argv[1];
String fichierProp = argv[2]; String fichierProp = argv[2];
System.out.println("Username=" +username + " Passwd="+password+"
fichierProp="+fichierProp+"\n");
db = ConfigConnection.getConnection(fichierProp,username,password);
MaudeManouvrier - Univ. Paris Dauphine
77
19
TP JBDC/DAO (8/10)
Exemple de classe type Active Record
public class Departement {
private int id;
private String nom; private String nom;
private boolean _builtFromDB;
private static String _query = "SELECT * FROM Departement";
public Departement() {
_builtFromDB=false;
}
public Departement(ResultSet rs) throws SQLException {
MaudeManouvrier - Univ. Paris Dauphine
78
public Departement(ResultSet rs) throws SQLException {
id = rs.getInt("Departement_ID");
nom = rs.getString("Nom_Departement");
_builtFromDB = true;
}
TP JBDC/DAO (9/10)
Exemple de classe type Active Record (suite)
public void save(Connection cx) throws SQLException {
Statement s = cx.createStatement();
if(_builtFromDB) {
System.out.println("Executing this command: "+_update()+"\n");
s.executeUpdate(_update());
}
else {
System.out.println("Executing this command: "+_insert()+"\n");
s.executeUpdate(_insert());
_builtFromDB=true;
// Pour rcuperer la cl gnre sous PostgreSQL
MaudeManouvrier - Univ. Paris Dauphine
79
ResultSet rset =s.executeQuery("SELECT last_value FROM
departement_departement_id_seq");
if (rset.next()) {
id = rset.getInt(1);
}
}
}
20
TP JBDC/DAO (10/10)
Exemple de classe type Active Record (suite)
public void delete(Connection cx) throws SQLException {
Statement s = cx.createStatement();
if(_builtFromDB) {
System out println("Executing this command: "+ delete()+"\n"); System.out.println( Executing this command: +_delete()+ \n );
s.executeUpdate(_delete());
}
else System.out.println("Objet non persistant!");
}
Exemple dutilisation de la classe :
MaudeManouvrier - Univ. Paris Dauphine
80
// Insertion d'un nouveau dpartement
Departement d = new Departement("DEP");
d.save(_cx);
_cx.commit();
System.out.println("Dpartement cr et persistant : " + d.toString());

Vous aimerez peut-être aussi