Вы находитесь на странице: 1из 142

Les 2 parties du cours Introduction au cours sur la persistance des objets

Universit de Nice Sophia-Antipolis


Version 0.9 16/9/06

Ce cours se divise en 2 parties : n persistance des objets n bases de donnes avances Ce support est une introduction la premire partie

Richard Grin

Richard Grin

Objet-relationnel

page 2

On part des objets


Le cours de L3 a montr comment concevoir la structure dune base de donnes en partant dune analyse/conception de type entitassociation (E-A) Le point de vue de ce cours est diffrent : on part dune application objet et on veut rendre certaines donnes de lapplication persistantes La structure de la base de donnes devra donc correspondre au modle objet de lapplication
Richard Grin Objet-relationnel page 3

Le dcor
Une application complexe multi-tiers Le cours sintresse linterface entre le tiers mtier et le tiers base de donnes Lnorme majorit des base de donnes sont relationnelles et de nombreuses applications modernes sont crites avec des langages objet Comment une application crite dans un langage objet peut effectuer la persistance de ses objets dans une base de donnes relationnelle
Richard Grin Objet-relationnel page 4

Persistance des objets


A la fin dune session dutilisation dune application toutes les donnes des objets existant dans la mmoire vive de lordinateur sont perdues Rendre persistant un objet cest sauvegarder ses donnes sur un support non volatile de telle sorte quun objet identique cet objet pourra tre recr lors dune session ultrieure
Richard Grin Objet-relationnel page 5

Pourquoi les BD relationnelles ?


Position dominante Grande facilit et efficacit pour effectuer des recherches complexes dans des grandes bases de donnes Facilit dadaptation des besoins diffrents (applications avec des vues diffrentes des donnes) Facilit pour spcifier des contraintes dintgrit sans programmation Une thorie solide et des normes reconnues
Richard Grin Objet-relationnel page 6

Pourquoi pas un SGBD Objet ?


Principale raison : de trs nombreuses bases relationnelles en fonctionnement Les SGBD objet noffre pas la capacit dadaptation la charge des SGBD relationnels Moins de souplesse pour sadapter aux besoins dapplications diffrentes Manque de normalisation pour les SGBDO ; trop de solutions propritaires Peu d'informaticiens forms aux SGBDO (consquence des autres raisons)
Richard Grin Objet-relationnel page 7

Objet -> relationnel pas toujours possible


Une partie des donnes peut tre contenue dans une base de donnes prexistante Ces donnes sont dj utilises par dautres applications et leur structure ne peut donc tre modifie Il nest donc pas toujours possible de suivre une dmarche objet vers relationnel

Richard Grin

Objet-relationnel

page 8

Lobjet et le relationnel sont 2 paradigmes bien diffrents


Faire la correspondance entre les donnes modlises par un modle objet et par un modle relationnel nest pas simple Le modle relationnel est moins riche que le modle objet Par exemple, pas dhritage, ni de rfrences, ni de collections (pas dattributs multi-valus) dans le modle relationnel
Richard Grin Objet-relationnel page 9

Plan de cette partie du cours


LAPI de base pour la persistance en Java (JDBC) - 1 TP Correspondance objet-relationnel - 1 TP Organisation dune application objet pour lutilisation dune BD relationnelle Patterns pour la persistance (DAO,) 1 TP Bases de donnes Relationnelles-Objet (RO) - 1 TP JDBC avanc - 1 TP Outils et frameworks de mapping - 1 TP
Richard Grin Objet-relationnel page 10

Client - Serveur Organisation gnrale dune application dentreprise


Cette architecture a montr ses limites dans le cadre des applications dentreprise complexes : n client riche difficile installer / dployer n dpendance forte vis--vis des outils de persistance et de la couche de prsentation n enchevtrement des services techniques (concurrence, persistance, transactionnel, scurit,) avec les processus mtier

Richard Grin

Objet-relationnel

page 11

Richard Grin

Objet-relationnel

page 12

Architecture 3-tiers (ou n-tiers)


Les nouvelles architectures prconises ajoutent au moins une couche (tiers, niveau) entre le client et le serveur Dans cette couche tournent n les traitements mtiers des applications n les processus techniques qui grent la scurit, le transactionnel,

Les diffrentes couches

Extrait dun article de Sbastien Ros sur le mapping Objet-relationnel


Richard Grin Objet-relationnel page 13 Richard Grin Objet-relationnel page 14

Les couches
Prsentation, interface homme-machine (IHM) Traitements relatifs au domaine de lapplication (traitements mtiers ) avec les rgles de gestion en vigueur Enregistrement, rcupration et gestion des donnes persistantes dans une base de donnes

Les traitements mtier


Ce sont les vrais traitements : ils font le travail essentiel lis au domaine de lapplication (comptabilit, facturation, calculs scientifiques,) Ils ncessitent des traitements techniques, non fonctionnels, pour grer la scurit, le transactionnel, la concurrence, Ces traitements techniques sont souvent runis sous le nom de couche services et pris en charge par le framework de dveloppement (container EJB par exemple)
Richard Grin Objet-relationnel page 16

Richard Grin

Objet-relationnel

page 15

La couche de persistance
Elle est compose de la base de donnes Le plus souvent on y ajoute une couche qui effectue la correspondance (mapping) entre les objets et la base de donnes (DAO, ORM) En effet, le passage du monde objet au monde relationnel (ou plus gnralement des objets mtier aux donnes enregistres) peut ncessiter des traitements complexes Souvent cette couche sert aussi de cache pour les objets rcuprs dans la BD et amliore donc les performances
Richard Grin Objet-relationnel page 17

Relations entre les couches


Il est admis par tous quaucune des 2 autres couches ne doit dpendre de la couche prsentation En effet, la couche prsentation est souvent modifie et cela ne doit pas induire des modifications dans les autres couches

Richard Grin

Objet-relationnel

page 18

Indpendance de la couche mtier


La couche mtier ne doit pas dpendre non plus de limplmentation de la couche de persistance Le plus souvent un processus mtier reste stable durant toute la vie de lapplication On ne doit les modifier que pour lamliorer ou le corriger mais pas pour tenir compte dune modification (le plus souvent technique) dans lune des autres couches
Richard Grin Objet-relationnel page 19

Fuites de la logique mtier vers la couche de prsentation


La logique mtier ne devrait pas se trouver dans la couche prsentation pour viter de la duplication de code et amliorer lindpendance entre les couches a signifie, par exemple, que la couche de prsentation doit appeler des mthodes des objets mtiers mais que le contenu de ces mthodes ne doit pas apparatre dans la couche de prsentation
Richard Grin Objet-relationnel page 20

Fuites de la logique mtier vers la couche de persistance


La couche de persistance doit dpendre le moins possible de la couche mtier Une indpendance totale est videmment impossible Cependant une bonne indpendance (par lutilisation de vues par exemple) permettra dans certain cas dviter quune modification du modle objet nimplique automatiquement une modification de la couche de persistance
Richard Grin Objet-relationnel page 21

Prsentation JDBC de base


Universit de Nice - Sophia Antipolis Richard Grin
Version 2.9.6 16/9/06

JDBC (Java Data Base Connectivity) permet l'accs des bases de donnes avec le langage SQL, depuis un programme en Java Il est fourni par le paquetage java.sql LAPI JDBC est presque totalement indpendante des SGBDs (quelques mthodes ne peuvent tre utilises quavec certains SGBDs mais ne doivent tre utilises quen cas de ncessit imprieuse pour amliorer les performances)
R. Grin JDBC page 2

Versions de SQL supportes


Les premires versions de JDBC supportent le standard SQL-2 Entry Level JDBC 2 et 3 offrent en plus des fonctionnalits de SQL3 Pour des raisons d'efficacit un driver peut utiliser les possibilits particulires d'un SGBD (c'est permis par JDBC), mais au dtriment de la portabilit JDBC 4 qui sortira avec Java 6 au 4me trimestre 2006 utilisera les annotations et apportera plus de facilits pour lcriture du code
R. Grin JDBC page 3

Contenu de java.sql
Ce paquetage contient un grand nombre d'interfaces et quelques classes Les interfaces constituent linterface de programmation JDBC ne fournit pas les classes qui implantent les interfaces

R. Grin

JDBC

page 4

Drivers
Pour travailler avec un SGBD il faut disposer de classes qui implantent les interfaces de JDBC Un ensemble de telles classes est dsign sous le nom de driver JDBC Les drivers dpendent du SGBD auquel ils permettent d'accder Tous les SGBD importants du march ont un (et mme plusieurs) driver JDBC, fourni par l'diteur du SGBD ou par des diteurs de logiciels indpendants
R. Grin JDBC page 5

Types de drivers
Type 1 : pont JDBC-ODBC Type 2 : driver qui fait appel des fonctions natives non Java (le plus souvent en langage C) de l'API du SGBD que l'on veut utiliser Type 3 : driver qui permet l'utilisation d'un serveur middleware Type 4 : driver crit entirement en Java, qui utilise le protocole rseau du SGBD

R. Grin

JDBC

page 6

Type 1 : pont JDBC-ODBC


Application Java Driver JDBC Driver ODBC Les mthodes du driver JDBC font appel des fonctions en langage C d'un driver ODBC (en Java) (pas en Java)

Type 2 : utilise une API native


Application Java Partie en Java Partie native (en Java) (pas en Java)

Les mthodes du driver JDBC font appel des fonctions d'une API du SGBD crite dans un autre langage que Java

Driver

Protocole du SGBD

SGBD
R. Grin JDBC page 7 R. Grin JDBC

SGBD
page 8

Type 3 : accs un serveur middleware


Application Java

Type 4 : 100 % Java avec accs direct au SGBD


Application Java Driver en Java

Les mthodes du driver JDBC se connectent par socket au serveur middleware et lui envoient les requtes SQL ; le serveur middleware les traitent en se connectant au SGBD

Driver en Java Protocole du serveur middleware Serveur middleware

Les mthodes du driver JDBC utilisent des sockets pour dialoguer avec le SGBD selon son protocole rseau
SGBD

Protocole du SGBD

SGBD
R. Grin JDBC page 9 R. Grin JDBC

page 10

Types de drivers et applet untrusted


Une applet ne peut pas charger distance du code natif (non Java) ; elle ne peut donc pas utiliser les drivers de type 1 et 2 Pour des raisons de scurit, une applet untrusted ne peut changer des donnes par sockets qu'avec la machine d'o elle provient, ce qui implique des contraintes avec les drivers de type 3 et 4

Driver de type 3 et applet untrusted


Le serveur middleware doit tre sur la mme machine que le serveur HTTP Code Java Applet Driver en Java connexion par socket Serveur HTTP Serveur middleware

SGBD
R. Grin JDBC page 11 R. Grin JDBC page 12

Driver de type 4 et applet untrusted


Code Java Le serveur HTTP doit tre sur la mme machine que le SGBD Driver en Java Applet

Travailler avec JDBC


connexion par socket

Serveur HTTP

SGBD
JDBC page 13 R. Grin JDBC page 14

R. Grin

Pour utiliser JDBC


A lexcution, ajouter le chemin des classes du (des) driver dans le classpath (option -classpath de la commande java) Par exemple, si Oracle est install dans /oracle, le driver peut tre dans le fichier
/oracle/jdbc/lib/ojdbc14.jar

Dans les classes qui utilisent JDBC


Importer le paquetage java.sql (et java.math si on utilise la classe BigDecimal) :
import java.sql.*;

Charger en mmoire la classe du (des) driver (driver de type 4 fourni par Oracle pour cet exemple) avant d'utiliser JDBC :
Class.forName( "oracle.jdbc.driver.OracleDriver");

et lapplication sera lance par la commande


java classpath /oracle/jdbc/lib/ojdbc14.jar ...

Inutile avec JDBC 4 !

R. Grin

JDBC

page 15

R. Grin

JDBC

page 16

tapes du travail avec une base de donnes avec JDBC


1. Ouvrir une connexion (Connection) 2. Crer des instructions SQL (Statement, PreparedStatement ou CallableStatement) 3. Lancer l'excution de ces instructions :
n n n

Classes et interfaces de JDBC

interroger la base (executeQuery()) ou modifier la base (executeUpdate()) ou tout autre ordre SQL (execute())

4. Fermer la connexion (close())


R. Grin JDBC page 17 R. Grin JDBC page 18

Avertissement
Nous tudierons tout d'abord les classes et mthodes de base de JDBC Les nouvelles possibilits de JDBC 2 et 3, en particulier celles qui sont lies SQL3, seront abordes dans une autre partie Dans la suite du cours on utilise des raccourcis du type instance de Connection Comme Connection est une interface, il faut traduire par instance dune classe qui implmente Connection

R. Grin

JDBC

page 19

R. Grin

JDBC

page 20

Interfaces principales
Driver : renvoie une instance de Connection Connection : connexion une base Statement : ordre SQL PreparedStatement : ordre SQL paramtr CallableStatement : procdure stocke sur le SGBD ResultSet : lignes rcupres par un ordre SELECT ResultSetMetaData : description des lignes rcupres par un SELECT DatabaseMetaData : informations sur la base de donnes
R. Grin JDBC page 21

Classes principales
DriverManager : gre les drivers, lance les connexions aux bases Date : date SQL Time : heures, minutes, secondes SQL TimeStamp : date et heure, avec une prcision la microseconde Types : constantes pour dsigner les types SQL (pour les conversions avec les types Java)

R. Grin

JDBC

page 22

Exceptions
SQLException : erreurs SQL SQLWarning : avertissements SQL (classe fille de SQLException) ; le mcanisme de rcupration des avertissements est tudi plus loin DataTruncation : avertit quand une valeur est tronque lors d'un transfert entre Java et le SGBD (classe fille de SQLWarning)

Interface Driver
La mthode connect() de Driver prend en paramtre un URL et renvoie une instance de l'interface Connection Cette instance de Connection permettra de lancer des requtes vers le SGBD connect renvoie null si le driver ne convient pas pour se connecter la base dsigne par l'URL

Utilise par DriverManager ; pas visible par lutilisateur de lAPI


R. Grin JDBC page 23 R. Grin JDBC page 24

URL d'une base de donnes


Un URL pour une base de donnes est de la forme : jdbc:sous-protocole:base de donne Par exemple, pour Oracle : jdbc:oracle:thin:@sirocco.unice.fr:1521:INFO n oracle:thin est le sous-protocole (driver thin ; Oracle fournit aussi un autre type de driver) n @sirocco.unice.fr:1521:INFO dsigne la base de donnes INFO situe sur la machine sirocco (le serveur du SGBD coute sur le port 1521) La forme exacte des parties sous-protocole et base de donnes dpend du SGBD cible
R. Grin JDBC page 25

Gestionnaire de drivers
La classe DriverManager gre les drivers (instances de Driver) disponibles pour les diffrents SGBD utiliss par le programme Java Pour qu'un driver soit utilisable, on doit charger sa classe en mmoire :
Class.forName("oracle.jdbc.driver.OracleDriver");

La classe cre alors une instance d'elle mme et enregistre cette instance auprs de la classe DriverManager
R. Grin JDBC page 26

Obtenir une connexion


Pour obtenir une connexion un SGBD, on demande cette connexion la classe gestionnaire de drivers :
static final String url = "jdbc:oracle:thin:@sirocco.unice.fr:1521:INFO"; Connection conn = DriverManager.getConnection(url, "toto", "mdp");

Connexions et threads
Les connexions sont des ressources coteuses, et surtout longues obtenir On peut donc tre tent de les rutiliser dans plusieurs threads diffrents Mais, attention, les connexions ne peuvent tre partages par plusieurs threads la place, utiliser les pools de connexions fournis avec les sources de donnes (tudies dans une autre partie du cours)
R. Grin JDBC page 28

La classe DriverManager s'adresse tour de rle tous les drivers qui se sont enregistrs (mthode connect), jusqu' ce qu'un driver lui fournisse une connexion (ne renvoie pas null)
R. Grin JDBC page 27

Transactions
Par dfaut la connexion est en auto-commit : un commit est automatiquement lanc aprs chaque ordre SQL qui modifie la base Le plus souvent il faut enlever l'auto-commit : conn.setAutoCommit(false) Il faut alors explicitement valider ou annuler la transaction par n conn.commit() n conn.rollback()
R. Grin JDBC page 29 R. Grin

Niveau disolation
Le niveau disolation dune transaction peut tre modifi :
conn.setTransactionIsolation( Connection.TRANSACTION_SERIALIZABLE);

JDBC

page 30

Instruction SQL simple


Instance de l'interface Statement La cration est effectue par la mthode createStatement() de Connection : Statement stmt = connexion.createStatement();

Excution de linstruction SQL simple


La mthode appeler dpend de la nature de l'ordre SQL que lon veut excuter : n consultation (select) : executeQuery() renvoie un ResultSet pour rcuprer les lignes une une n modification des donnes (update, insert, delete) ou ordres DDL (create table,) : executeUpdate() renvoie le nombre de lignes modifies n si on ne connat pas l'excution la nature de l'ordre SQL excuter ou si l'ordre peut renvoyer plusieurs rsultats : execute()
page 31 R. Grin JDBC page 32

R. Grin

JDBC

Consultation des donnes (SELECT)


Statement stmt = conn.createStatement(); // rset contient les lignes renvoyes ResultSet rset = stmt.executeQuery("SELECT nomE FROM emp"); // On rcupre chaque ligne une une while (rset.next()) System.out.println (rset.getString(1)); // ou . . . (rset.getString("nomE")); stmt.close(); La premire colonne a le numro 1 Voir plus loin le transparent sur la R.fermeture des ressources Grin

Interface ResultSet
executeQuery() renvoie une instance de ResultSet ResultSet va permettre de parcourir toutes les lignes renvoyes par le select Au dbut, ResultSet est positionn avant la premire ligne et il faut donc commencer par le faire avancer la premire ligne en appelant la mthode next() Cette mthode permet de passer la ligne suivante ; elle renvoie true si cette ligne suivante existe et false sinon
R. Grin JDBC page 34

JDBC

page 33

Interface ResultSet
Quand ResultSet est positionn sur une ligne les mthodes getXXX permettent de rcuprer les valeurs des colonnes de la ligne : n getXXX(int numroColonne) n getXXX(String nomColonne) (nom simple dune
colonne, pas prfix par un nom de table ; dans le cas dune jointure utiliser un alias de colonne)

ResultSet - performances
Quand le rseau est lent et que lon veut rcuprer de nombreuses lignes, il est parfois possible damliorer sensiblement les performances en modifiant le nombre de lignes rcupres chaque fois par le ResultSet (il faut effectuer des tests pour chaque cas) Pour cela, on utilise la mthode setFetchSize de Statement Cest seulement une indication quon donne au driver ; il nest pas oblig den tenir compte
R. Grin JDBC page 36

XXX dsigne le type Java de la valeur que l'on va rcuprer, par exemple String, Int ou Double Par exemple, getInt renvoie un int
R. Grin JDBC page 35

Types JDBC/SQL
Tous les SGBD n'ont pas les mmes types SQL ; mme les types de base peuvent prsenter des diffrences importantes Pour cacher ces diffrences, JDBC dfinit ses propres types SQL dans la classe Types, sous forme de constantes nommes Ils sont utiliss par les programmeurs quand ils doivent prciser un type SQL (setNull, setObject, registerOutParameter) Le driver JDBC fait la traduction de ces types dans les types du SGBD
R. Grin JDBC page 37

Types JDBC/SQL (classe Types)


CHAR, VARCHAR, LONGVARCHAR BINARY, VARBINARY, LONGVARBINARY BIT, TINYINT, SMALLINT, INTEGER, BIGINT REAL, DOUBLE, FLOAT DECIMAL, NUMERIC DATE, TIME, TIMESTAMP
BLOB, CLOB ARRAY, DISTINCT, STRUCT, REF JAVA_OBJECT
R. Grin JDBC

Types SQL3

page 38

Correspondances entre types Java et SQL


Il reste le problme de la correspondance entre les types Java et les types SQL Dans un programme JDBC, les mthodes getXXX, setXXX servent prciser cette correspondance Par exemple, getString indique que lon veut rcuprer la donne SQL dans une String C'est le rle du driver particulier chaque SGBD de faire les traductions correspondantes ; une exception peut tre lance si a nest pas possible
R. Grin JDBC page 39

Correspondances avec getXXX()


On a une grande latitude ; ainsi, presque tous les types SQL peuvent tre retrouvs par getString() Cependant, des mthodes sont recommandes ; voici des exemples :
n

n n n

CHAR et VARCHAR : getString, LONGVARCHAR : getAsciiStream et getCharacterStream BINARY et VARBINARY : getBytes, LONGVARBINARY : getBinaryStream REAL : getFloat, DOUBLE et FLOAT : getDouble DECIMAL et NUMERIC : getBigDecimal DATE : getDate, TIME : getTime, TIMESTAMP : getTimestamp
JDBC page 40

R. Grin

Types Date en Java et en SQL


java.sql contient une classe Date pour faciliter les changes de dates entre Java et la base de donnes Cette classe hrite de la classe java.util.Date Elle correspond un temps en millisecondes et elle permet JDBC didentifier quil a affaire une date SQL ; pour se conformer au type DATE de SQL ce temps est tronqu 0 heure dans la journe Pour passer de java.util.Date java.sql.Date, utiliser la mthode getTime()
R. Grin JDBC page 41

Manipulation des dates


Un petit rappel sur les dates en Java : n mise en forme avec la classe java.text.DateFormat
n

calculs sur les dates avec la classe java.util.Calendar

Voir le cours sur les dates dans le support Complments divers

R. Grin

JDBC

page 42

Valeur NULL
Statement stmt = conn.createStatement(); ResultSet rset = stmt.executeQuery( "SELECT nomE, comm FROM emp"); while (rset.next()) { nom = rset.getString(1); commission = rset.getDouble(2); if (rset.wasNull()) System.out.println(nom + ": pas de comm"); else System.out.println(nom + " a " + commission + " de commission"); }
R. Grin JDBC page 43

Modification des donnes (INSERT, UPDATE, DELETE)


Statement stmt = conn.createStatement(); String ville = "NICE"; int nbLignesModifiees = stmt.executeUpdate( "INSERT INTO dept (dept, nomD, lieu) " + "VALUES (70, 'DIRECTION'," + "'" + ville + "')"); N'oubliez pas stmt.close(); l'espace !

R. Grin

JDBC

page 44

Instruction SQL paramtre


La plupart des SGBD (dont Oracle) peuvent n'analyser qu'une seule fois une requte excute un grand nombre de fois durant une connexion JDBC permet de profiter de ce type de fonctionnalit par l'utilisation de requtes paramtres ou de procdures stockes Les requtes paramtres sont associes aux instances de l'interface PreparedStatement qui hrite de l'interface Statement
R. Grin JDBC page 45

Cration d'une requte paramtre


PreparedStatement pstmt = conn.prepareStatement("UPDATE emp SET sal = ?" + " WHERE nome = ?");

Les "?" indiquent les emplacements des paramtres Cette requte pourra tre excutes avec plusieurs couples de valeurs : (2500, DUPOND), (3000, DURAND), etc.

R. Grin

JDBC

page 46

Requte paramtre Valeurs des paramtres


Les valeurs des paramtres sont donnes par les mthodes setXXX(n, valeur) On choisit la mthode setXXX suivant le type Java de la valeur que l'on veut mettre dans la base de donnes C'est au programmeur de passer une valeur Java du bon type la mthode setXXX Le driver JDBC fait la conversion dans le bon format pour le SGBD
R. Grin JDBC page 47

Requte paramtre - Exemple


PreparedStatement pstmt = conn.prepareStatement( "UPDATE emp SET sal = ? " + "WHERE nomE = ?"); commence 1 et pas 0 for (int i=0; i<10; i++) { pstmt.setDouble(1,employe[i].getSalaire()); pstmt.setString(2, employe[i].getNom()); pstmt.executeUpdate(); }

R. Grin

JDBC

page 48

Requte paramtre - NULL


Pour passer la valeur NULL la base de donne, on peut n utiliser la mthode setNull(n, type) (type de la classe Types) n ou passer la valeur Java null si la mthode setXXX() attend un objet en paramtre

Avantages des PreparedStatement


Leur traitement est plus rapide sils sont utiliss plusieurs fois avec plusieurs paramtres Ils amliorent aussi la portabilit car les mthodes setXXX grent les diffrences entre SGBD En effet, les SGBD nutilisent pas tous les mmes formats de date ('JJ/MM/AA' ou 'AAAA-MM-JJ' par exemple) ou de chanes de caractres (pour les caractres d chappement ) Mais on peut aussi utiliser pour cela la syntaxe (un peu lourde) SQL Escape (voir plus loin)
R. Grin JDBC page 50

R. Grin

JDBC

page 49

Procdures stockes
Les procdures stockes permettent non seulement de prcompiler des ordres SQL mais aussi de les regrouper Comme les accs rseau aux bases de donnes ralentissent les applications, les procdures stockes permettent souvent damliorer les performances Mais elles nuisent aussi souvent la portabilit des applications
R. Grin JDBC page 51

Exemple de procdure stocke (Oracle)


create or replace procedure augmenter (unDept in integer, pourcentage in number, cout out number) is begin select sum(sal) * pourcentage / 100 into cout from emp where dept = unDept; update emp set sal = sal * (1 + pourcentage / 100) where dept = unDept; end;
R. Grin JDBC page 52

Cration d'une procdure stocke


Les procdures stockes sont associes aux instances de l'interface CallableStatement qui hrite de l'interface PreparedStatement La cration d'une instance de CallableStatement se fait par l'appel de la mthode prepareCall de la classe Connection On passe cette mthode une chane de caractres qui dcrit comment sera appele la procdure stocke, et si la procdure renvoie une valeur ou non
R. Grin JDBC page 53

Syntaxe pour les procdures stockes


La syntaxe de l'appel des procdures stockes n'est pas standardise ; elle diffre suivant les SGBD JDBC utilise sa propre syntaxe pour pallier ce problme : n si la procdure renvoie une valeur : Le driver { ? = call nom-procdure(?, ?,...) } traduira n si elle ne renvoie aucune valeur : dans la { call nom-procdure(?, ?,...) } syntaxe du SGBD n si on ne lui passe aucun paramtre : { call nom-procdure }
R. Grin JDBC page 54

Exemple
CallableStatement cstmt = conn.prepareCall("{? = call augmenter(?,?)}");

Lancement d'une procdure stocke


L'appel de la procdure est prcd du passage la procdure des paramtres in et in/out par les mthodes setXXX() (idem requtes paramtres) On doit indiquer le type des paramtres out et in/out par la mthode registerOutParameter() Ensuite on lance la procdure par une des mthodes executeQuery(), executeUpdate() ou execute(), suivant le type de commande SQL que la procdure contient On rcupre les paramtres out et in/out par les mthodes getXXX() (idem requtes paramtres)
R. Grin JDBC page 56

R. Grin

JDBC

page 55

Utilisation d'une procdure stocke


CallableStatement csmt = conn.prepareCall( "{ call augmenter(?, ?, ?) }");
// 2 chiffres aprs la virgule pour 3me paramtre

Procdures stockes contenant plusieurs ordres SQL


Une procdure stocke peut contenir plusieurs ordres SQL de divers types Pour retrouver tous les rsultats de ces ordres (ResultSet ou nombre de lignes modifies), on utilise la mthode getMoreResults() de la classe Statement Ainsi, si elle contient 2 ordres SELECT, on rcupre le 1er ResultSet par getResultSet ; on passe la 2me requte par getMoreResults et on rcupre son ResultSet par getResultSet
R. Grin JDBC page 58

csmt.registerOutParameter(3, Types.DECIMAL, 2);


// Augmentation de 2,5 % des salaires du dept 10

csmt.setInt(1, 10); csmt.setDouble(2, 2.5); csmt.executeQuery(); // ou execute double cout = csmt.getDouble(3); System.out.println("Cout total augmentation : " + cout);
R. Grin JDBC page 57

Ordre SQL quelconque


On peut ne pas savoir quels ordres SQL sont contenus dans une procdure stocke Dans ce cas, on utilise le fait que
n n

Schma de code
boolean retval = cstmt.execute(); do { if (retval == false) { // pas un ResultSet int count = cstmt.getUpdateCount(); if (count == -1) break; // cest fini ! else { // traite lordre SQL . . . } } else { // ResultSet ResultSet rs = cstmt.getResultSet(); . . . // traite le ResultSet } retval = cstmt.getMoreResults(); while (true);
R. Grin JDBC page 60

execute renvoie true si le 1er rsultat est un ResultSet getMoreResults renvoie true si le rsultat suivant est un ResultSet getUpdateCount() : renvoie le nombre de lignes modifies, ou -1 s'il n'y a plus de rsultat (ou si le rsultat est un ResultSet)

On peut excuter tous les ordres dans une boucle dont la condition de fin est
!getMoreResults() && getUpdateCount() == -1
R. Grin JDBC page 59

10

Renvoyer un ResultSet dune procdure stocke avec Oracle


Attention, les 4 transparents qui suivent sur ce sujet sont particuliers Oracle ; consultez le manuel de votre SGBD si vous travaillez avec un autre SGBD Il faut utiliser le type ref cursor dOracle et des extensions JDBC fournies avec le driver distribu par Oracle Le curseur Oracle sera ferm quand linstance de CallableStatement sera ferme
R. Grin JDBC page 61

Fonction qui renvoie un curseur


1. 2.

Il faut Crer un type pour la rfrence de curseur quon va renvoyer Crer la fonction qui renvoie la rfrence de curseur

R. Grin

JDBC

page 62

Crer le type rfrence de curseur


Crer un nom de type pour la rfrence de curseur quon va renvoyer Pour utiliser ensuite le type, il faut le crer dans un paquetage :
create or replace package Types AS type curseur_type is ref cursor; end Types;

Crer la fonction
create or replace function listdept(num integer) return Types.curseur_type is empcursor Types.curseur_type; begin open empcurseur for select dept, nomE from emp where dept = num; return empcurseur; end;

R. Grin

JDBC

page 63

R. Grin

JDBC

page 64

Utiliser la fonction dans JDBC


CallableStatement cstmt = conn.prepareCall("{ ? = call list(?) }"); cstmt.setInt(2, 10); cstmt.registerOutParameter(1, OracleTypes.CURSOR); cstmt.execute(); ResultSet rs = ((OracleCallableStatement)cstmt) .getCursor(1); while (rs.next()) { System.out.println(rs.getString("nomE") + ";" + rs.getInt("dept")); }
R. Grin JDBC page 65

Fermer les ressources


Toutes les ressources JDBC doivent tre fermes ds quelles ne sont plus utilises Le plus souvent la fermeture doit se faire dans un bloc finally pour quelle ait lieu quel que soit le droulement des oprations (avec ou sans erreurs) Les ressources sont automatiquement fermes par le ramasse-miettes mais il faut les fermer explicitement (on ne sait quand/si il va tre lanc)
R. Grin JDBC page 66

11

Les ressources fermer


Connection : leur fermeture est indispensable car cest la ressource la plus coteuse ; si on utilise un pool de connexions, la fermeture rend la connexion au pool Statement, et les sous-interfaces PreparedStatement et CallableStatement ResultSet : il est automatiquement ferm lorsque le statement qui la engendr est ferm ou rexcut, ou utilis pour retrouver le prochain rsultat (getMoreResults)
R. Grin JDBC page 67

Syntaxe spciale de JDBC


( SQL Escape syntax )
Comme avec les procdures stockes, JDBC a une syntaxe spciale pour ne pas dpendre de particularits des diffrents SGBD :
n n n

dates : {d '2000-10-5'} appels de fonctions : {fn concat("Hot", "Java")} jointures externes : con.createStatement("SELECT * FROM" + " {oj EMP RIGHT OUTER JOIN DEPT" + " ON EMP.DEPT = DEPT.DEPT}"); caractre dchappement utilis par LIKE : WHERE Id LIKE '_%\\' {escape '\'}
JDBC page 68

R. Grin

Les Meta donnes


JDBC permet de rcuprer des informations sur le type de donnes que l'on vient de rcuprer par un SELECT (interface ResultSetMetaData), mais aussi sur la base de donnes elle-mme (interface DatabaseMetaData) Les donnes que l'on peut rcuprer avec DatabaseMetaData dpendent du SGBD avec lequel on travaille

ResultSetMetaData
ResultSet rs = stmt.executeQuery("SELECT * FROM emp"); ResultSetMetaData rsmd = rs.getMetaData(); int nbColonnes = rsmd.getColumnCount(); for (int i = 1; i <= nbColonnes; i++) { String typeColonne = rsmd.getColumnTypeName(i); String nomColonne = rsmd.getColumnName(i); System.out.println("Colonne " + i + " de nom " + nomColonne + " de type " + typeColonne); }
R. Grin JDBC page 70

R. Grin

JDBC

page 69

DatabaseMetaData
private DatabaseMetaData metaData; private java.awt.List listTables = new List(10); . . . metaData = conn.getMetaData(); String[] types = { "TABLE", "VIEW" }; ResultSet rs = metaData.getTables(null, null, "%", types); String nomTables; Joker pour while (rs.next()) { noms des nomTable = rs.getString(3); tables et vues listTables.add(nomTable); }
R. Grin JDBC page 71

Ordre SQL dynamiques


Au moment o il crit le programme, le programmeur peut ne pas connatre, le type SQL des valeurs insres ou retrouves dans la base de donnes Pour cela, JDBC a prvu les mthodes getObject() et setObject() qui effectuent des conversions automatiques (ou non) entre les types Java et SQL

R. Grin

JDBC

page 72

12

Introduction Correspondance Objet - Relationnel


Universit de Nice Sophia-Antipolis
Version 0.9.2 11/9/06

Richard Grin

Ce cours explique les problmes de base qui se posent quand on veut faire correspondre n les donnes contenues dans un modle objet n avec les donnes contenues dans une base de donnes relationnelle Le cours sur JPA (Java Persistence API) donnera un exemple concret doutil qui automatise en grande partie cette correspondance
R. Grin Mapping objet-relationnel page 2

Prsuppos
La base de donnes relationnelle manipule par une application objet peut dj exister ou non au moment de la conception de lapplication objet Le cours qui suit suppose plutt que la base nexiste pas, mais le plus souvent les adaptations une base existante ne sont pas trs complexes et sont pris en charge par les outils de mapping
Une association

Dpartement numro : int nom : String lieu : String ajouterEmploy(Employe) : void 1 +contient

Une classe Une classeassociation Multiplicit


Projet codeP : String nomP : String ajouterEmploye(Employe)

Agrgation
+subordonn

Unidirectionnel 0..*
hierarchie

0..*

appartient

Participation fonctionP : String

Employe matricule : int nom : String poste : String 0..1 dateEmbauche : date salaire : double +suprieur getSuperieur() setSuperieur(Employe) getMatricule()

0..* +participe

0..*

Rle pour lassociation


Commercial commission : double setCommission(double)

Hritage
Directeur Administratif

R. Grin

Mapping objet-relationnel

page 3

R. Grin

Mapping objet-relationnel

page 4

2 paradigmes
Les paradigmes objet et relationnel sont bien distincts Le modle objet est plus riche (hritage, associations en particulier) Pas toujours simple de faire correspondre des objets et des donnes de tables relationnelles

Quelques problmes du passage R Objet


Identit des objets Traduction des associations Traduction de lhritage Navigation entre les objets

R. Grin

Mapping objet-relationnel

page 5

R. Grin

Mapping objet-relationnel

page 6

Problme de base
Les objets persistants doivent tre enregistrs dans la base de donnes relationnelle Un objet a une structure complexe qui peut tre reprsente par un graphe Le plus souvent ce graphe est un arbre dont la racine correspond lobjet et les fils correspondent aux valeurs des variables dinstance qui sont persistantes Il faut aplatir ce graphe pour le ranger dans la base de donnes relationnelle
R. Grin Mapping objet-relationnel page 7

Plan
1. 2. 3. 4. 5. 6.

Exemple simple de traduction dune classe en une table Identification Traduction des associations Traduction de lhritage Navigation entre les objets Objet dpendant

R. Grin

Mapping objet-relationnel

page 8

Traduction dune classe en une table Exemple simple de traduction dune classe en une table
Dans les cas les plus simples une classe est traduite en une table Chaque objet est conserv dans une ligne de la table Exemple : la classe Dpartement est traduite par la table DPARTEMENT(numro, nom, lieu)

R. Grin

Mapping objet-relationnel

page 9

R. Grin

Mapping objet-relationnel

page 10

En SQL
create table departement ( numero smallint constraint pk_dept primary key, nom varchar(15), lieu varchar(15))

Identification

R. Grin

Mapping objet-relationnel

page 11

R. Grin

Mapping objet-relationnel

page 12

Identification dans le monde Objet


Tout objet est identifiable simplement dans les langages objets (adresse de lemplacement mmoire) 2 objets distincts peuvent avoir exactement les mmes valeurs pour leurs proprits

Identification dans le monde relationnel


Seules les valeurs des colonnes peuvent servir identifier une ligne Si 2 lignes ont les mmes valeurs, il est impossible de les diffrencier Dans les schmas relationnels toute table devrait donc comporter une cl primaire pour identifier une ligne parmi toutes les autres lignes de la mme table

R. Grin

Mapping objet-relationnel

page 13

R. Grin

Mapping objet-relationnel

page 14

Proprit cl primaire pour les objets


Pour effectuer la correspondance objetrelationnel, il peut tre ncessaire dajouter un identificateur un objet Cet identificateur permet de conserver la cl primaire de la ligne de la base de donnes qui correspond lobjet

viter les identificateurs significatifs


Rappel du cours de L3 Mme si les objets peuvent tre distingus par leurs proprits, un identificateur sera souvent rajout pour viter les identificateurs significatifs Surtout si la cl significative est compose de plusieurs proprits

R. Grin

Mapping objet-relationnel

page 15

R. Grin

Mapping objet-relationnel

page 16

Problme des duplications


Une mme ligne de la base de donnes ne doit pas tre reprsente par plusieurs objets en mmoire centrale (ou alors le code doit le savoir et en tenir compte) Si elle nest pas gre, cette situation peut conduire des pertes de donnes

Exemple de duplication
Un objet p1 de la classe Produit de code s003 est cr en mmoire loccasion dune navigation partir dune ligne de facture On peut retrouver le mme produit en navigant depuis une autre facture, ou en cherchant tous les produits qui vrifient un certain critre Une erreur serait de crer en mmoire centrale un autre objet p2 indpendant du premier objet p1 dj cr
R. Grin Mapping objet-relationnel page 18

R. Grin

Mapping objet-relationnel

page 17

Pour viter des duplications


En mmoire, un objet cache rpertorie toutes les objets crs et conserve lidentit quils ont dans la base (la cl primaire) Lors dune navigation ou dune recherche dans la base, le cache intervient Si lobjet est dj en mmoire le cache le fournit, sinon, lobjet est cr avec les donnes rcupres dans la base de donnes
R. Grin Mapping objet-relationnel page 19

Objets insrs
Le modle objet peut avoir une granularit plus fine que le modle relationnel Les instances de certaines classes peuvent tre sauvegardes dans la mme table quune autre classe Ces instances sont appeles des objets insrs (embedded) et ne ncessitent pas didentificateur cl primaire

R. Grin

Mapping objet-relationnel

page 20

Exemple
Une classe Adresse na pas de correspondance sous forme dune table spare dans le modle relationnel Les attributs de la classe Adresse sont insres dans la table qui reprsente la classe Client Les objets de la classe Adresse nont pas didentification lie la base de donnes

Traduction des associations

R. Grin

Mapping objet-relationnel

page 21

R. Grin

Mapping objet-relationnel

page 22

Les associations en objet


Dans le code objet une association peut tre reprsente par n une variable dinstance reprsentant lautre objet avec lequel se fait lassociation (associations 1:1 ou N:1) n une variable dinstance de type collection ou map reprsentant tous les autres objets avec lesquels se fait lassociation (associations 1:N ou M:N) n une classe association (M:N)
R. Grin Mapping objet-relationnel page 23

Exemples de classes pour une association 1:N (ou N:1)


class Dpartement { private Collection<Employ> employes; . . . } class Employ { private Dpartement dpartement; . . . }

R. Grin

Mapping objet-relationnel

page 24

Reprsentation dune association


Dans le monde relationnel, une association peut tre reprsente par n une ou plusieurs cls trangres (associations 1:1, N:1 ou 1:N) n une table association (associations M:N)

Exemples de tables
create table DEPT ( . . .) create table EMPLOYE ( . . . num_dept integer references DEPT)

R. Grin

Mapping objet-relationnel

page 25

R. Grin

Mapping objet-relationnel

page 26

Navigabilit des associations


Dans un modle objet, une association peut tre bi ou unidirectionnelle Exemple dassociation unidirectionnelle : la classe Employ peut avoir une variable dinstance donnant son dpartement mais la classe Dpartement peut navoir aucune collection demploys En partant dun dpartement, on na alors pas de moyen simple de retrouver ses employs
R. Grin Mapping objet-relationnel page 27

Navigabilit des associations


Dans un schma relationnel, une association est toujours bidirectionnelle : on peut toujours naviguer vers lautre bout dune association Par exemple, pour trouver les employs du dpartement 10 : select matr, nomE from employe where dept = 10

R. Grin

Mapping objet-relationnel

page 28

Association binaire M:N - Objet


On va dabord tudier le cas des associations M:N qui ncessitent une table association dans le monde relationnel 2 faons diffrentes pour reprsenter une association M:N : n une collection ou une map dans chacune (ou dans une, selon la directionnalit) des classes associes, qui rfrence les objets associs n une classe association qui reprsente une instance de lassociation Si lassociation contient des proprits, seule la 2me faon convient
R. Grin Mapping objet-relationnel page 30

R. Grin

Mapping objet-relationnel

page 29

Exemples de classes solution 1


class Employ { private Collection<Projet> projets; . . . } class Projet { private Collection<Employ> employs; . . . }

Solution 1 variante avec Map


class Projet { private Map<Integer, Employ> employs; . . . }

La cl peut, par exemple, reprsenter le matricule dun employ La variante avec map permet un accs rapide un des employs participant un projet La classe Projet reste identique la premire variante
R. Grin Mapping objet-relationnel page 32

R. Grin

Mapping objet-relationnel

page 31

Exemples de classes solution 2


class Employ { Employ ou/et Projet peuvent . . . contenir une collection de } Participation pour permettre class Projet { la navigation . . . } class Participation { private Employ employ; private Projet projet; . . . }
R. Grin Mapping objet-relationnel page 33

Association M:N - Relationnel


Une association M:N est traduite par une table association La cl primaire de cette table est forme des 2 cls des tables qui reprsentent les classes qui interviennent dans lassociation

R. Grin

Mapping objet-relationnel

page 34

Exemple de traduction dune association binaire M:N


PARTICIPATION(matr, codeP)

Classe association (cas M:N)


Si l'association a des proprits, elles sont ajoutes dans la classe association et dans la nouvelle table qui traduit lassociation

En SQL :
create table participation ( matr integer references emp, codeP varchar(2) references projet, primary key(matr, codeP))

Pour faciliter la lecture, la syntaxe est simplifie pour les contraintes


R. Grin Mapping objet-relationnel page 35 R. Grin Mapping objet-relationnel page 36

En objet
class Participation { private Employ employ; private Projet projet; private String fonction; . . . }

En relationnel
PARTICIPATION(matr, codeP, fonctionP)

En SQL :
create table participation ( matr integer references emp, codeP varchar(2) references projet, fonctionP varchar(15), primary key(matr, dept))

R. Grin

Mapping objet-relationnel

page 37

R. Grin

Mapping objet-relationnel

page 38

Association binaire dont une multiplicit maximum est 1 (N:1 ou 1:1) - Relationnel
On peut traduire les associations N:1 ou 1:1 en ajoutant une nouvelle relation, comme pour une association M:N Mais le plus simple est dajouter la cl de lautre classe dans la relation qui traduit la classe place du ct oppos la multiplicit 1 La 1re solution est plus souple mais plus coteuse (jointures)
R. Grin Mapping objet-relationnel page 39

Exemple dune association binaire N:1 - Relationnel


EMP(matr,, dept)

En SQL :
create table emp ( matr integer primary key, dept smallint references dept)

R. Grin

Mapping objet-relationnel

page 40

Classe association (cas N:1 ou 1:1)


Si l'association est reprsente par une classe association, on peut ajouter les attributs de classe dans la relation qui reoit la cl de l'autre classe (ou dans la nouvelle relation si on a choisi cette solution) Si les attributs de la classe association sont nombreux, il peut tre prfrable de traduire l'association par une relation part (comme pour une association M:N)
R. Grin Mapping objet-relationnel page 41

Association de degr > 2 - Objet


Une association de degr > 2 peut tre reprsente de plusieurs faons diffrentes Le plus simple est sans doute de reprsenter lassociation par une classe association qui contient des rfrences vers les objets qui participent lassociation Mais on peut aussi reprsenter une telle association par des collections de classes qui contiennent des collections ou des rfrences vers des classes qui contiennent des collections
R. Grin Mapping objet-relationnel page 42

Exemple dassociation de degr > 2


Une rservation dans une compagnie arienne peut tre considre comme une association entre les avions, les passagers et les numros de sige En effet, un passager peut occuper plusieurs siges (problme de sant par exemple)

Reprsentation par une classe


class Reservation { private Vol vol; private Passager passager; private int sige; . . . }

R. Grin

Mapping objet-relationnel

page 43

R. Grin

Mapping objet-relationnel

page 44

Autre reprsentation
class Vol { private Collection<Reservation> rsas; . . . } class Reservation { private Passager passager; private int sige; . . . }

Association de degr > 2 en relationnel


Dans le monde relationnel on cre une table pour traduire lassociation La cl primaire de cette table est forme d'un sous-ensemble des cls des tables qui traduisent les classes qui interviennent dans lassociation Le sous-ensemble peut tre strict si une dpendance fonctionnelle existe entre ces cls
page 45 R. Grin Mapping objet-relationnel page 46

R. Grin

Mapping objet-relationnel

Exemple de traduction dune association de degr > 2


RESERVATION(nVol, nSige, codePassager, )

Gestion des associations bidirectionnelles


Grer une association est plus complexe dans le monde objet que dans le monde relationnel, surtout si elle est bidirectionnelle Par exemple, si un employ change de dpartement, il suffit de changer le numro de dpartement dans la ligne de lemploy En objet, il faut en plus enlever lemploy de la collection des employs du dpartement et le rajouter dans la collection de son nouveau dpartement
R. Grin Mapping objet-relationnel page 48

En SQL :
create table reservation( nvol varchar(10) references vol, nsiege integer, codePassager varchar(10) references passager, primary key(nVol, nSiege, codePassager), ...)

R. Grin

Mapping objet-relationnel

page 47

Gestion automatique de l autre bout dune association


Certains framework (EJB 2 par exemple), automatisent une partie de la gestion des associations Ainsi, si le champ dept dun employ est modifi, lemploy est pass automatiquement de la collection des employs du dpartement dorigine dans celle du nouveau dpartement Dautres frameworks comme Hibernate ou EJB 3/JPA prfrent ne rien automatiser
R. Grin Mapping objet-relationnel page 49

Objet dpendant
Un objet dont le cycle de vie dpend du cycle de vie dun autre objet auquel il est associ, appel objet propritaire Aucun autre objet que le propritaire ne doit avoir de rfrence directe vers un objet dpendant En ce cas, la suppression de lobjet propritaire doit dclencher la suppression des objets qui en dpendent (dclenchement en cascade )
R. Grin Mapping objet-relationnel page 50

Exemple
Une ligne de facture ne peut exister quassocie une (en-tte de) facture Si on supprime une facture, toutes les lignes de la facture doivent tre supprimes Tous les outils de mapping, comme JPA, offrent la possibilit dautomatiser les suppressions en cascade dobjets dpendants

Traduction de lhritage

R. Grin

Mapping objet-relationnel

page 51

R. Grin

Mapping objet-relationnel

page 52

Exemple
Pour fixer les ides, et ;-) pour reprendre des dessins du trs bon livre de Martin Fowler cit dans la bibliographie, on travaillera sur lexemple suivant tir du monde anglophone : n des sportifs qui peuvent tre des footballeurs ou des joueurs de crickets n parmi les joueurs de crickets, on distingue les joueurs qui lancent la balle : les bowlers
Pour en savoir plus sur le cricket : http://www.eleves.ens.fr/home/mlnguyen/divers/crick et/rules.html
R. Grin Mapping objet-relationnel page 53

Classe abstraite

Exemple
Sportifs qui peuvent tre des footballeurs ou des joueurs de crickets n Parmi les joueurs de crickets, les joueurs qui lancent la balle : les bowlers
n

R. Grin

Mapping objet-relationnel

page 54

Plusieurs mthodes de traduction


Reprsenter toutes les classes dune arborescence dhritage par une seule table relationnelle Reprsenter chaque classe instanciable (concrte) par une table Reprsenter chaque classe, mme les classes abstraites, par une table

Accessibilit des variables


Cette remarque est valable quelle que soit la mthode de traduction de lhritage Toutes les variables dinstance ne sont pas ncessairement accessibles par toutes les classes filles (si elles ne sont pas protected et si elles ne possdent pas daccesseur protected ou public) Le code devra donc souvent trouver un moyen de demander chaque classe de la hirarchie dhritage de participer la persistance pour ses propres variables
R. Grin Mapping objet-relationnel page 56

R. Grin

Mapping objet-relationnel

page 55

Accessibilit des variables


Par exemple, si une instance dune classe fille veut se sauvegarder dans la base, il lui faudra trouver un moyen de rcuprer les variables dinstance de ses classes mres Un moyen est de faire appel une mthode de la classe mre par super. , cette mthode rcuprant les variables dinstance de la classe mre
Un autre moyen, utilis par les outils de mapping, est la rflexivit Java qui permet doutrepasser les restrictions daccs accoles aux variables dinstance
R. Grin Mapping objet-relationnel page 57

Polymorphisme
Association polymorphe : une classe contient une rfrence vers une classe mre abstraite Par exemple, une socit garde une rfrence vers un sportif (dun sport quelconque) quelle sponsorise Requte polymorphe : cas o on veut une information qui correspond une proprit qui appartient une classe mre Par exemple, on veut les noms de tous les joueurs
R. Grin Mapping objet-relationnel page 58

Toutes les classes traduites par une seule table

Avantages
Souvent la solution la plus simple mettre en place Cest dailleurs la solution la plus frquemment choisie Permet les requtes et associations polymorphes

Pour diffrencier les types de joueurs


R. Grin Mapping objet-relationnel page 59 R. Grin Mapping objet-relationnel page 60

10

Inconvnients
Oblige avoir de nombreuses colonnes qui contiennent la valeur NULL On ne peut dclarer ces colonnes NOT NULL , mme si cette contrainte est vraie pour une des sous-classes

Une table par classe

Colonne optionnelle
R. Grin Mapping objet-relationnel page 61 R. Grin Mapping objet-relationnel page 62

Prservation de lidentit
Un objet peut avoir ses attributs rpartis sur plusieurs tables (celles qui correspondent aux classes dune mme hirarchie dhritage) Son identit est alors prserve en donnant la mme cl primaire aux lignes qui correspondent lobjet dans les diffrentes tables Les cls primaires des tables correspondant aux classes filles sont des cls trangres vers la cl primaire de la classe mre
R. Grin Mapping objet-relationnel page 63

Prservation de lidentit
Pour rcuprer les informations sur une instance dune classe fille, il suffit de faire une jointure sur ces cls primaires

R. Grin

Mapping objet-relationnel

page 64

Avantages
Simple : bijection entre les classes et les tables Permet les requtes et associations polymorphes

Inconvnient
Si la hirarchie dhritage est complexe ncessite de nombreuses jointures pour reconstituer les informations parpilles dans de nombreuses tables Do des instructions complexes, mais surtout de mauvaises performances La colonne type de la table Players permet de limiter un peu ce problme ; il est possible, par exemple, de retrouver les noms des footballers sans faire de jointure
page 65 R. Grin Mapping objet-relationnel page 66

R. Grin

Mapping objet-relationnel

11

Une table par classe concrte

Remarque
Si une classe concrte se retrouve au milieu de larbre dhritage avec des classes filles (comme ici la classe Cricketer), il faudra que les classes filles concrtes aient la mme cl primaire que la classe mre concrte dans les tables correspondantes

R. Grin

Mapping objet-relationnel

page 67

R. Grin

Mapping objet-relationnel

page 68

Avantages
Cest la mthode la plus naturelle : une table par type dentit Pas de jointures pour retrouver les informations

Inconvnients
Ne peut traduire simplement les associations polymorphes Par exemple, une classe qui rfrence un joueur dun sport quelconque (joueur de football ou de cricket) En effet, aucune table relationnelle ne correspond un joueur dun sport quelconque et on ne peut donc imposer une contrainte dintgrit rfrentielle (cl trangre)
R. Grin Mapping objet-relationnel page 70

R. Grin

Mapping objet-relationnel

page 69

Solution
Aucune solution vraiment satisfaisante Des solutions partielles : n ignorer la contrainte dintgrit rfrentielle n mettre plusieurs colonnes dans la table qui rfrence, une pour chaque table concrte rfrence (mais a sera difficile dimposer lunicit de la rfrence ; sur lexemple, a sera difficile dimposer davoir une seule rfrence vers un joueur)
R. Grin Mapping objet-relationnel page 71

Autre problme
Dans le mme ordre dide, il est difficile dinterroger la base pour effectuer une requte polymorphe Par exemple, avoir le nom de tous les joueurs

R. Grin

Mapping objet-relationnel

page 72

12

Solution
On devra lancer plusieurs selects (un pour chaque sous-classe concrte) et utiliser une union de ces selects Le select sera donc plus complexe et sans doute moins performant

Une solution viter


Sauf pour des cas bien prcis o le polymorphisme nest pas important, il vaut mieux viter cette solution Dailleurs, la version actuelle de la spcification EJB 3 nimpose pas aux serveurs dapplication doffrir cette possibilit de traduction de lhritage

R. Grin

Mapping objet-relationnel

page 73

R. Grin

Mapping objet-relationnel

page 74

Variantes
Dans une arborescence dhritage ces stratgies peuvent tre mlanges On peut, par exemple, crer plusieurs tables pour plusieurs branches de larborescence dhritage Mais le risque est de retomber sur les problmes de la stratgie 3 (une table par classe concrte) avec les requtes et les associations polymorphes
R. Grin Mapping objet-relationnel page 75

Hritage multiple
Dans les cas o lhritage est traduit par des tables spares, lidentifiant dans les classes descendantes est lensemble des identifiants des classes mres

R. Grin

Mapping objet-relationnel

page 76

2 stratgies pour les associations


Lorsquun objet est cr partir des donnes rcupres dans la base de donnes, 2 stratgies vis--vis des objets associs cet objet : n rcupration immdiate et cration des objets associs n les objets associs ne sont pas crs tout de suite, mais seulement lorsque lapplication en a vraiment besoin
page 77 R. Grin Mapping objet-relationnel page 78

Navigation entre les objets

R. Grin

Mapping objet-relationnel

13

Une situation
Recherche dans la base de donnes dune facture qui vrifie un certain critre Un objet de la classe Facture qui correspond cette facture est cr Est-ce que les objets LigneFacture associs cette facture doivent aussi tre crs ? Et si la rponse est positive, faut-il crer aussi les objets Produit correspondants chaque ligne de facture ? Et si la rponse est positive,
R. Grin Mapping objet-relationnel page 79

Le problme
Le risque est de crer un trs grand nombre dobjets, peut-tre inutiles Par exemple, si on veut rcuprer cette facture pour connatre seulement la date de facturation, on voit que tous ces objets associs sont totalement inutiles Do de mauvaises performances, sans raisons valables

R. Grin

Mapping objet-relationnel

page 80

Rcupration paresseuse
La solution est le lazy loading , mot mot rcupration paresseuse , que lon peut traduire par rcupration la demande ou rcupration retarde

Rcupration paresseuse
Quand un objet est cr partir des donnes enregistres dans la BD, les objets associs ne sont pas immdiatement crs Lobjet cr contient juste linformation ncessaire pour retrouver ces objets associs (cl primaire) Ces objets ne seront crs que si cest vraiment indispensable

R. Grin

Mapping objet-relationnel

page 81

R. Grin

Mapping objet-relationnel

page 82

Exemple
Si on recherche la facture de numro 456, un objet f de la classe Facture est cr mais les objets correspondants aux lignes de la facture f ne sont pas crs Si le programme contient le code f.getLigne(i).getQuantite() lobjet LigneFacture correspondant la ime ligne de facture est cr et le message getQuantite() lui est envoy
R. Grin Mapping objet-relationnel page 83

Problme des N + 1 selects


On peut tomber sur le problme des N + 1 selects

R. Grin

Mapping objet-relationnel

page 84

14

Un exemple de N + 1 selects
On veut rcuprer la facture qui a le plus gros total, parmi 5000 factures Si la rcupration des lignes se fait la demande, les objets Facture sont dabord rcupres (1 select), puis, pour chacune des 5000 factures, les lignes de facture associes sont rcupres pour calculer le total (5000 selects) Do un total de 5001 selects, alors quon peut obtenir le rsultat avec un seul select !
R. Grin Mapping objet-relationnel page 85

Mauvaise solution pour les N + 1 selects


Indiquer que la rcupration pour cette association doit toujours tre immdiate (dans les fichiers de configuration) ne convient pas le plus souvent En effet, dans dautres circonstances, on ne souhaitera pas charger les lignes de factures pour viter de crer trop dobjets inutiles

R. Grin

Mapping objet-relationnel

page 86

Solutions possibles (1)


Lancer un ordre SQL ad hoc qui renvoie le total de la facture pour rsoudre le problme ponctuel (sans cration dobjets) Cest la solution la plus simple, mais elle peut ne pas convenir dans le cas o on veut des informations plus complexes sur les objets associs lobjet Il faut cependant retenir que, dans certaines circonstances, une bonne requte SQL vaut mieux que la cration de nombreux objets
R. Grin Mapping objet-relationnel page 87

Solutions possibles (2)


La plupart des outils de mapping permettent de spcifier une stratgie spciale pour une requte particulire On peut alors indiquer que, par dfaut, le mode de rcupration ne sera pas immdiate, tout en spcifiant que la rcupration des objets associs devra tre immdiate pour une requte particulire

R. Grin

Mapping objet-relationnel

page 88

Code avec JPA


String texteQuery = "select f from Facture f " + " join fetch f.lignes " + " where f.date > '1/1/06'"; Query query = em.createQuery(texteQuery); List<Facture> liste = (List<Facture>)query.getResultList(); System.out.println(liste.get(0).getLigne(0));

Code avec Hibernate


List results = session.createCriteria(Item.class) .add( Expression.eq("item.seller", user) ) .setFetchMode("bids", FetchMode.EAGER).list(); // vite duplication de rsultats (due au outer join) Iterator items = new HashSet(results).iterator(); List maxAmounts = new ArrayList(); while (items.hasNext()) { Item item = (Item) items.next(); BigDecimal max = new BigDecimal("0"); Iterator b = item.getBids().iterator(); while (b.hasNext()) { Bid bid = (Bid) b.next(); if ( bid.getAmount().compareTo(max) == 1 ) max = bid.getAmount(); } maxAmounts.add(new MaxAmount(item.getId(), max)); }
R. Grin Mapping objet-relationnel page 90

Ne gnrera aucune requte SQL

R. Grin

Mapping objet-relationnel

page 89

15

Conclusion de cette section


La correspondance entre le modle objet et le modle relationnel nest pas une tche facile Les outils et framework ORM (tudis la fin de ce cours) rduisent grandement le code qui permet cette correspondance et facilitent donc les adaptations mutuelles des 2 modles

R. Grin

Mapping objet-relationnel

page 91

16

Types dapplications pour la persistance


Universit de Nice Sophia-Antipolis
Version 0.7 16/9/06

Toutes les applications nont pas une complexit qui ncessite une architecture ntiers Ce cours dcrit les grands modles dapplications qui utilisent une base de donnes relationnelle

Richard Grin

Richard Grin

Types dapplication pour la persistance

page 2

Base de donnes prexistante ?


La conception de lapplication va sans doute tre diffrente si la base de donnes est prexistante ou non Et si elle prexiste, si le dveloppeur de lapplication peut en modifier la structure ou non

3 modles
Modle procdural Modle objet simple Modle objet avec utilisation dun outil de mapping videmment, ce dcoupage est trs schmatique Chacun de ces modles peut utiliser ou non des passerelles (DAO par exemple) pour isoler davantage le code qui gre la persistance
Richard Grin Types dapplication pour la persistance page 4

Richard Grin

Types dapplication pour la persistance

page 3

Autour des procdures


Pour les applications aux fonctionnalits les plus simples et pour un dveloppement rapide Le plus souvent la base de donnes est prexistante Lapplication est organise autour de procdures qui accdent directement la base de donnes quand cest ncessaire Utilisation possible de procdures stockes pour encapsuler les scnarios des cas dutilisation
page 5 Richard Grin Types dapplication pour la persistance page 6

Modle procdural

Richard Grin

Types dapplication pour la persistance

Exemple : classe GestionEmployes


Mthode void ajouter(int matricule, String nom,) ajoute un nouvel employ, en ajoutant une nouvelle ligne dans la base Mthode double getTotalDept(int dept) renvoie le total des salaires pour un dpartement, en lanant une requte SQL qui ramne le rsultat On peut se passer dune classe Employe
Richard Grin Types dapplication pour la persistance page 7

Pour des modles mtier simples


Les traitements de lapplication doivent tre pauvres en traitements mtier et essentiellement lis la persistance des donnes : n ajouts et suppressions denregistrements n modifications simples de donnes effectues directement par lutilisateur

Richard Grin

Types dapplication pour la persistance

page 8

Ce modle est limit


On est dans ce cas trs loign du modle objet ; on ne profite donc pas de ses atouts : n hritage n polymorphisme n facilit de rutilisation des objets n relations entre objets n Quand lapplication se complexifie il est difficile de lenrichir avec de nouvelles fonctionnalits et de rutiliser/partager du code
Richard Grin Types dapplication pour la persistance page 9 Richard Grin

Modle objet simple

Types dapplication pour la persistance

page 10

Un modle objet simple


La correspondance entre les tables et les classes est le plus souvent bijective Chaque classe contient le code pour grer la persistance de ses propres instances Pattern appel active record par Martin Fowler

Exemple : classe Employe


La table EMPLOYE lui est associ Elle contient la mthode dinstance ajouter() (on pourrait lappeler ajouteToiDansLaBase) qui ajoute une ligne dans la table EMPLOYE ; cette ligne contient les valeurs des attributs de linstance La classe contient aussi des mthodes sauvegarder() (ou modifier()), supprimer()
Richard Grin Types dapplication pour la persistance page 12

Richard Grin

Types dapplication pour la persistance

page 11

Mthodes pour la recherche


Elles peuvent tre mises : n dans une classe qui se charge des recherches (un finder) n en static dans la classe mtier qui correspond au type renvoy n dans le cas particulier o le critre de recherche correspond une des classes mtier, la mthode peut tre mise dans cette classe mtier (choix 3 du transparent suivant)
Richard Grin Types dapplication pour la persistance page 13

Exemple
Une mthode qui recherche tous les employs dun dpartement Choix 1 :
List<Employe> rechercher(Dept dept)

dans la classe RechercheEmploye Choix 2 :


static List<Employe> rechercher(Dept dept)

de la classe Employe
Choix 3 : List<Employe> getEmployes() de la classe Departement
Richard Grin Types dapplication pour la persistance page 14

Dsavantages
Le dsavantage est que les classes mtier sont trop lies au support de persistance utilis Problme principal : tout refactoring entranant une modification de la hirarchie va obliger revoir le code de la persistance Mais ce refactoring est rare si le modle objet est simple Lutilisation du pattern DAO peut amliorer la situation, mais seulement partiellement
Richard Grin Types dapplication pour la persistance page 15

Utilisation dun outil de mapping

Richard Grin

Types dapplication pour la persistance

page 16

Un modle objet complexe avec outil de mapping


Pour les modles objets complexes avec beaucoup dhritage et de relations entre classes le modle prcdent se rvle vite difficile implmenter et maintenir Un outil de mapping ou un framework permet dautomatiser la correspondance objetrelationnel

Outils de mapping
La correspondance objet-relationnel est dcrite dans des fichiers des configuration ou par des annotations La persistance peut devenir presque transparente pour le dveloppeur qui crit le code Java Difficile dcrire soi-mme de tels outils car ils sont trs complexes

Richard Grin

Types dapplication pour la persistance

page 17

Richard Grin

Types dapplication pour la persistance

page 18

JPA
Spcification standard pour la persistance de objets Java (tudi la fin de ce cours) Implmentation de rfrence construite au dessus de Toplink Fait partie de la spcification EJB 3, framework pour les applications dentreprise

Hibernate
Avec Toplink, loutil de mapping le plus utilis dans le monde Java Utilise un gestionnaire de persistance, lintrospection et lenrichissement de code lexcution pour rcuprer les valeurs des proprits des objets et grer leur persistance En cours dadaptation au standard JPA

Richard Grin

Types dapplication pour la persistance

page 19

Richard Grin

Types dapplication pour la persistance

page 20

Autres possibilits
JDO (Java Data Objects) est une autre API qui offre des possibilits semblables JPA Utilise lenrichissement de code pendant la phase de compilation

Framework (cadre de
dveloppement)
Ensemble de classes et ressources prexistantes que le dveloppeur doit complter Utilisation dune librairie : lexcution est dirige par le code crit par le dveloppeur, qui fait appel aux classes de la librairie Utilisation dun framework : lexcution est dirige par le framework qui fait appel au code crit par le dveloppeur
Richard Grin Types dapplication pour la persistance page 22

Richard Grin

Types dapplication pour la persistance

page 21

EJB
Le framework standard pour les applications Java dentreprise, EJB (Entreprise Java Beans), est fourni par J2EE, la version dentreprise de Java Il ncessite lutilisation dun serveur dapplication qui est un logiciel lourd rserver pour les grosses applications dentreprises

EJB
Les EJB sont des classes Java qui dcrivent le comportement des objets mtier Le dveloppeur crit le code li aux fonctionnalits des objets mtier, sans soccuper des services techniques (scurit, distribution sur plusieurs machines, transactions, persistance,) Le serveur dapplications utilise ce code pour y ajouter tous les services techniques indispensables au bon fonctionnement de lapplication
Richard Grin Types dapplication pour la persistance page 24

Richard Grin

Types dapplication pour la persistance

page 23

EJB Entits
Il existe plusieurs types dEJB Les EJB entits correspondent aux objets mtier persistants Leur persistance peut tre entirement prise en charge par le container dEJB fourni par le serveur dapplication

Problmes EJB entits version 2


Les classes persistantes doivent hriter de certaines classes fournies par le framework Elles ne peuvent donc hriter dautres classes Le framework ne peut prendre en charge la persistance dobjets des classes Java ordinaires (POJO : Plain Old Java Object) Il est aussi difficile, sinon impossible, dutiliser les classes persistantes en dehors du container, en particulier pour les tests
Richard Grin Types dapplication pour la persistance page 26

Richard Grin

Types dapplication pour la persistance

page 25

EJB version 3
EJB 3 revoit en grande partie les EJB entits Sappuie sur JPA pour la persistance (tudi dans la suite du cours) Les beans entits nont plus hriter de classes spciales et peuvent tre tests en dehors du serveur dapplications

Avantages EJB entits


Lavantage dutiliser les EJB entits est que la prise en charge est complte (scurit, transaction, distribution, accs concurrents,) Il est plus facile de maintenir le code lorsque lapplication monte en charge (plus grand nombre de connexions, distribution des serveurs sur plusieurs machines,)

Richard Grin

Types dapplication pour la persistance

page 27

Richard Grin

Types dapplication pour la persistance

page 28

Passerelle
Classe qui contient tout le code pour grer la persistance Chaque table a une classe passerelle qui lui correspond Le reste de lapplication fait appel aux passerelles pour grer la persistance

Passerelles

Richard Grin

Types dapplication pour la persistance

page 29

Richard Grin

Types dapplication pour la persistance

page 30

Utilisation
Isolent la persistance du reste de lapplication Facilitent les changements de SGBD et/ou permet dallger le code des classes mtier Peuvent tre utilises avec les 3 modles vus prcdemment

2 types de passerelle
Une instance de passerelle par table (le plus frquent) Une instance de passerelle par ligne de table Le pattern DAO (Data Access Object), trs utilis et tudi plus loin dans ce cours, correspond au type une passerelle par table

Richard Grin

Types dapplication pour la persistance

page 31

Richard Grin

Types dapplication pour la persistance

page 32

Exemple de passerelle
La classe EmployeDAO gre la persistance des instances de la classe Employe et correspond la table employe Elle contient la mthode ajouter(int matricule, String nom,) La mthode prend en paramtre les informations sur lemploy ajouter car il existe une seule instance de la classe EmployeDAO pour tous les employs
Richard Grin Types dapplication pour la persistance page 33 Richard Grin

Exemple de passerelle
Avec une instance de passerelle par ligne, on aurait une mthode ajouter() car la passerelle aurait toutes les informations sur lemploy auquel elle est lie

Types dapplication pour la persistance

page 34

Bibliographie
Patterns of Entreprise Application Architecture de Martin Fowler Addison Wesley

Richard Grin

Types dapplication pour la persistance

page 35

Quelques patterns pour la persistance des objets avec DAO


Universit de Nice Sophia-Antipolis
Version 1.1 6/10/06

Ce cours prsente des modles de conception utiliss pour effectuer la persistance des objets

Richard Grin

R. Grin

Mapping objet-relationnel

page 2

Principe de base
Il est plus frquent de changer le modle de donnes des supports de persistance que de changer le modle mtier Pour faciliter ces changements il faut sparer le plus possible les entres-sorties des classes mtiers

DAO
Le code pour la persistance est isol dans des objets spcifiques, les DAO (Data Acess Objects)

R. Grin

Mapping objet-relationnel

page 3

R. Grin

Mapping objet-relationnel

page 4

Utilit des DTOs


Les DAOs sont situs sur une couche proche de la base de donnes Le code utilisateur des DAOs est souvent situ sur une autre couche distante Les DTOs peuvent tre utiliss pour transporter les donnes entre les diffrentes couches distantes

Le modle de conception DTO (Data Transfer Object)

R. Grin

Mapping objet-relationnel

page 5

R. Grin

Mapping objet-relationnel

page 6

DTO
Un DTO contient ltat dun ou de plusieurs objets mtier, mais pas leur comportement Synonyme : Transfert Object (TO)

Exemples dutilisation des DTO


Transporter les donnes dun objet distant pas transportable sur le rseau (pas srialisable) Transporter plusieurs objets distants en un seul appel distant ; par exemple une facture avec toutes les lignes de facture et les informations sur les produits Il faut viter les DTOs si lapplication est locale (pas distribue) : complications inutiles

R. Grin

Mapping objet-relationnel

page 7

R. Grin

Mapping objet-relationnel

page 8

Un fait important
Les appels de mthode distants sont beaucoup plus coteux que les appels locaux Le cot dpend peu de la quantit de donnes transfre chaque appel

Le problme rsoudre
Un client souhaite rcuprer des donnes en interrogeant des objets distants non facilement transportables sur le rseau Exemple : rcuprer les nom, prnom, salaire et lieu de travail dun employ Sil utilise les accesseurs des classes des objets (getNom, getPrenom, getSalaire, getLieu), plusieurs appels distants sont ncessaires
R. Grin Mapping objet-relationnel page 10

R. Grin

Mapping objet-relationnel

page 9

La solution
Le client demande un DTO la couche base de donnes , proche de la base de donnes qui contient toutes les valeurs dont il a besoin Cet objet est construit sur la couche base de donnes et pass en une seule fois au client

La solution
Un DTO peut aussi tre utilis, plus gnralement pour modifier un ou plusieurs objets distants (ou les donnes de la base de donnes) : n le DTO est cr ou modifi sur une couche de lapplication n il est pass une couche distante qui utilise ses donnes pour modifier un ou plusieurs objets distants (ou la base de donnes)
R. Grin Mapping objet-relationnel page 12

R. Grin

Mapping objet-relationnel

page 11

Le problme rsoudre
Le code pour la persistance varie beaucoup n avec le type de stockage (BD relationnelles, BD objet, fichiers simples, etc.) n avec les implmentations des fournisseurs de SGBD Si les ordres de persistance sont imbriqus avec le code mtier , il est difficile de changer de source de donnes

Le modle de conception DAO (Data Access Object)

R. Grin

Mapping objet-relationnel

page 13

R. Grin

Mapping objet-relationnel

page 14

La solution
Encapsuler le code li la persistance des donnes dans des objets DAO dont linterface est indpendante du support de la persistance Le reste de lapplication utilise les DAOs pour grer la persistance, en utilisant des interfaces abstraites, indpendantes du support de persistance ; par exemple, Employe getEmploye(int matricule)

DAO
Quand lapplication a besoin deffectuer une opration lie la persistance dun objet, elle fait appel un objet DAO qui elle passe les informations ncessaires pour effectuer lopration Chaque classe dobjet mtier a son propre type de DAO (DAOEmploye, DAODepartement, ) Mais le mme objet DAO peut tre utilis pour tous les objets dune classe dobjet mtier
R. Grin Mapping objet-relationnel page 16

R. Grin

Mapping objet-relationnel

page 15

Utilit des DAOs


Plus facile de modifier le modle de la base de donnes Factorise le code daccs la base de donnes Plus facile pour le spcialiste des BD doptimiser les accs (ils nont pas parcourir toute lapplication pour examiner les ordres SQL) Sans doute le modle de conception le plus utilis dans le monde de la persistance
R. Grin Mapping objet-relationnel page 17

Emplacement des DAOs


Les DAOs sont placs dans la couche dite daccs aux donnes qui est souvent sur une autre machine que la couche des objets mtiers Les changes de messages entre les DAOs et les objets mtiers engendrent donc souvent des appels distants et des DTO peuvent donc tre utiliss pour amliorer la vitesse des changes
R. Grin Mapping objet-relationnel page 18

CRUD
Cet acronyme, souvent utilis dans le monde de la persistance, dsigne les 4 oprations de base de la persistance qui sont implmentes dans un DAO : create, retrieve, update et delete Les DAO peuvent aussi grer les connexions/dconnexions la source de donnes et les transactions

CRUD
Create pour crer une nouvelle entit dans la base Retrieve pour retrouver une ou plusieurs entits de la base Update pour modifier une des entits de la base Delete pour supprimer une entit de la base Plusieurs variantes pour les signatures de ces mthodes dans les DAOs
R. Grin Mapping objet-relationnel page 20

R. Grin

Mapping objet-relationnel

page 19

create
Prend en paramtre ltat de la nouvelle entit Cet tat peut tre donn n par une srie de paramtres des types des donnes : create(int id, String nom,) n par un DTO : create(DTOxxx dto) n par lobjet mtier que lon veut rendre persistant : create(Article article)

create comparaison des variantes


La 1re variante est sans doute la plus frquemment utilise et la plus souple La dernire variante ne convient que si lobjet mtier a toutes ses proprits publiques et sil est facilement transportable Mais elle peut tre pratique et performante dans les cas o elle est applicable

R. Grin

Mapping objet-relationnel

page 21

R. Grin

Mapping objet-relationnel

page 22

create
Le type retour peut tre n void (la variante la plus utilise) n boolean, pour indiquer si la cration a pu avoir lieu n lidentificateur de lentit ajoute (utile si lidentificateur est gnr automatiquement) n un objet mtier ou un DTO correspondant lentit ajoute La variante avec objet mtier a les mmes inconvnients (et avantages) que pour le passage de paramtre dun objet mtier
R. Grin Mapping objet-relationnel page 23

retrieve
3 types de finder, suivant quil retourne n un seul objet n une collection dobjets n une valeur calcule partir de plusieurs entits (agrgation)

R. Grin

Mapping objet-relationnel

page 24

Finder qui retourne un objet


On lui passe en paramtre un identificateur de lentit cherche Il retourne un objet mtier qui correspond lentit cherche, ou un DTO qui contient les donnes de lentit cherche

Finder qui retourne une collection


On lui passe en paramtre le critre de slection, sous une forme quelconque n objet ou valeurs critre de slection n objet exemple Le type retour peut tre trs divers : n ResultSet n RowSet n Collection (Collection, List, Set,) dobjets mtier ou de DTOs n tableau (rare)
R. Grin Mapping objet-relationnel page 26

R. Grin

Mapping objet-relationnel

page 25

Finder qui retourne une valeur calcule


Les valeurs calcules partir des donnes de plusieurs entits (exemple : total des salaires) peuvent sobtenir partir dobjets chargs en mmoire Mais il peut tre prfrable de ne pas crer les objets et dinterroger directement la base de donnes qui est optimise pour ce type de requte Un DAO peut ainsi comporter une mthode qui renvoie le total des salaires des employs
R. Grin Mapping objet-relationnel page 27

update
Des variantes diverses pour les paramtres : n identificateur + valeurs (plusieurs paramtres pour les valeurs ou un seul DTO) n lobjet mtier dont on veut sauvegarder les modifications (ncessite un accs public aux valeurs qui seront modifies) Le type retour peut tre n void n boolean pour indiquer si la modification a pu avoir lieu
R. Grin Mapping objet-relationnel page 28

delete
Pour les paramtres : n identificateur de lentit supprimer dans la base n lobjet mtier (ou un DTO) correspondant lentit supprimer dans la base Pour le type retour : n void n boolean pour indiquer si la suppression a pu avoir lieu
R. Grin Mapping objet-relationnel page 29

DAO et exceptions
Les mthodes des DAO peuvent lancer des exceptions puisquelles effectuent des oprations dentres-sorties Les exceptions ne doivent pas tre lies un type de DAO particulier si on veut pouvoir changer facilement de type de DAO

R. Grin

Mapping objet-relationnel

page 30

DAO et exceptions
Pour cela, on cre une ou plusieurs classes dexception indpendantes du support de persistance, dsignons-les par DAException (ou DataAccessException ou DaoException) Les mthodes des DAO attrapent les exceptions particulires, par exemple les SQLException, et relancent des DAException (auxquels sont chanes les exceptions dorigine pour faciliter la mise au point)
R. Grin Mapping objet-relationnel page 31

2 stratgies dutilisation des DAOs


1.

2.

Chaque objet mtier a une rfrence son DAO et lutilise pour sa propre persistance. Le programme qui manipule les objets mtier ne connat pas les DAOs Le programme qui manipule les objets mtier utilise directement les DAOs. Les objets mtier nont pas de rfrence un DAO (stratgie sans doute la plus frquemment utilise)

R. Grin

Mapping objet-relationnel

page 32

Stratgie 1
Les programmes qui manipulent les objets mtier ne sont pas modifis par rapport un programme qui nutilise pas de DAO Seuls les objets mtier connaissent leur DAO Les objets mtier doivent avoir une rfrence vers le DAO quils utilisent Cette rfrence peut tre obtenue par une mthode static de la classe DAO (ce qui peut permettre de partager un DAO entre tous les objets mtier dune mme classe)
R. Grin Mapping objet-relationnel page 33

Exemple de code
class Stylo { private StyloDAO dao; ... on peut aussi public void sauvegardeToi() { construire un dao = getDAO(); TO pour le dao.insertOrUpdate(this); passer au DAO } private StyloDAO getDAO() { if (dao == null) Pour simplifier, on ne StyloDAO.getDAO(); tient pas compte des return dao; exceptions }
R. Grin Mapping objet-relationnel page 34

Stratgie 2
On rencontre le plus souvent la stratgie 2 On perd sans doute de la puret de la programmation objet

Exemple de code
// ou styloDAO = new StyloDAO() StyloDAO styloDAO = StyloDAO.getDAO(); int idStylo = styloDAO.create("Marker", "noir ", DTO ou objet 120,...); mtier . . . Stylo stylo = styloDAO.findById(idStylo); Nouvelles styloDAO.update(idStylo, ...); List<Stylo> l = styloDAO.findAll(); valeurs pour le stylo

R. Grin

Mapping objet-relationnel

page 35

R. Grin

Mapping objet-relationnel

page 36

Exemple de code (variante)


// ou styloDAO = new StyloDAO() StyloDAO styloDAO = StyloDAO.getDAO(); styloDAO.create(145, "Marker", "noir ", 120,...); . . . Stylo stylo = styloDAO.findById(1234); stylo.setPrix(45); styloDAO.update(stylo); List<Stylo> l = styloDAO.findAll();

Diagramme de classes (avec utilisation de TO)

Cette image (et les suivantes) sont extraites du Core J2EE Pattern Catalog de Sun
page 37 R. Grin Mapping objet-relationnel page 38

R. Grin

Mapping objet-relationnel

Diagramme de squences

DAO et connexions
Une connexion peut tre ouverte au dbut des mthodes du DAO, et ferme la fin des mthodes Cette stratgie peut coter cher si un pool de connexions nest pas utilis Le DAO peut aussi contenir des mthodes pour ouvrir et fermer une connexion ; en ce cas, une connexion peut tre utilise par plusieurs mthodes du DAO

Modification de plusieurs attributs persistants en utilisant un DTO : cration du DAO, puis rcupration des valeurs actuelles, R. Grin page 39 puis modification de ces Mapping objet-relationnel valeurs

R. Grin

Mapping objet-relationnel

page 40

DAO et transactions
Le plus souvent le DAO dmarre et termine lui-mme les transactions chaque mthode Dans les cas complexes, plusieurs DAOs associs plusieurs types dobjets mtier peuvent intervenir dans une transaction Dans ce cas, cest le client qui va grer les transactions Avec JDBC, a implique que les connexions ne sont pas ouvertes et fermes pour chaque mthode ; JTA na pas cette limitation
R. Grin Mapping objet-relationnel page 41

Transactions gres par le client


Le client peut grer les transactions dans le cas dune application qui utilise JDBC, sans serveur dapplications, en lanant les mthodes commit() ou rollback() de la classe Connection Pour cela, il utilise linstance de Connection renvoye par la mthode du DAO qui ouvre une connexion (ou par une mthode getConnection() du DAO) Avec les serveurs dapplications, il existe des mthodes pour obtenir la transaction en cours
R. Grin Mapping objet-relationnel page 42

DAO et hritage
Le problme : une classe a des classes mres qui ont des proprits persistantes qui ne sont pas visibles de lextrieur (private, sans accesseurs visibles) Comment le DAO va pouvoir grer la persistance des instances de cette classe ?

DAO et hritage
La solution est de crer une hirarchie parallle de classes mappers dont les instances contiendront les mmes donnes que la hirarchie de la classe dont le DAO gre la persistance (voir le pattern Inheritance Mappers dans le livre de Martin Fowler donn dans la bibliographie) Chacune des classes mappers se charge des donnes qui la concerne pour fournir au DAO les donnes ncessaires aux changes avec la base de donnes
R. Grin Mapping objet-relationnel page 44

R. Grin

Mapping objet-relationnel

page 43

Patterns pour rcuprer les DAO


Comment associer le bon DAO chaque classe mtier ? Si on change de SGBD, on doit changer de type de DAO Le pattern fabrique (factory) convient bien pour crer/rcuprer un DAO car il permet de cacher le type concret de la classe dune instance que lon cre Par exemple, une fabrique de DAOs peut retourner un DaoOracle ou un DaoDb2 suivant les circonstances
page 45 R. Grin Mapping objet-relationnel page 46

Le modle de conception fabrique abstraite

R. Grin

Mapping objet-relationnel

Exemple
La classe FabriqueDaoStylo contient une mthode getDao() qui renvoie un DaoStyloOracle ou un DaoStyloDb2 selon lenvironnement

Fabrique abstraite
Le pattern fabrique abstraite permet de changer facilement de source de donnes En une seule ligne de code tous les DAOs peuvent tre remplacs par des DAOs adapts la nouvelle source

R. Grin

Mapping objet-relationnel

page 47

R. Grin

Mapping objet-relationnel

page 48

Fabrique abstraite
Une fabrique abstraite est un type abstrait qui permet de cacher les types rels dun ensemble de fabriques concrtes Chaque fabrique concrte fournit tous les DAOs (DAOStylo, DAORamette,) associs une certaine source de donnes Dans la ligne de code, on rcupre la bonne fabrique de DAOs, associe la bonne source de donnes
R. Grin Mapping objet-relationnel page 49

Le type abstrait

Code client (dbut)

La ligne de code pour DAOFactory daoFactory = changer de SGBD DAOFactory.getDAOFactory( DAOFactory.TypeDao.MYSQL); styloDAO = daoFactory.getStyloDAO(); // cre un nouveau stylo dans la base int styloNo = styloDAO.create(...); // Trouve un stylo StyloTO styloTO = styloDAO.find(...); // Modifie des valeurs du TO styloTO.setPrix(125); // Modifie le stylo dans la base styloDAO.update(styloTO);
R. Grin Mapping objet-relationnel page 50

Code client (suite)


// Supprime un stylo de la base styloDAO.delete(styloNo); // Trouve tous les stylos dune marque StyloTO styloEx = new StyloTO(); styloEx.setMarque("Marker"); Collection listeStylos = styloDAO.selectTO(styloEx);

Fabrique abstraite 1 DAO


La fabrique abstraite Les fabriques concrtes

...
Les DAOs crs
R. Grin Mapping objet-relationnel page 51 R. Grin Mapping objet-relationnel page 52

Fabrique abstraite 1 source de donnes

Fabrique abstraite schma global

Une fabrique concrte cre tous les DAOs associs une source de donnes

R. Grin

Mapping objet-relationnel

page 53

R. Grin

Mapping objet-relationnel

page 54

Code pour fabrique abstraite


Le code qui suit est un exemple schmatique de lutilisation du pattern DAO, avec le pattern fabrique abstraite (inspir fortement dun exemple donn par Sun) Il utilise aussi le pattern TO Important : ce pattern TO peut tre vit si les objets persistants peuvent tre transports entre les diffrentes couches dune application (par exemple, pour une application locale, ou en utilisant les objets dtachs de Hibernate)
R. Grin Mapping objet-relationnel page 55

La fabrique abstraite
public abstract class DAOFactory { public enum TypeDao {MYSQL, ORACLE}; public abstract StyloDAO getStyloDAO(); public abstract FactureDAO getFactureDAO(); ... public static DAOFactory getDAOFactory(TypeDao typeDao) { switch (typeFabrique) { case MYSQL: return new MysqlDAOFactory(); case ORACLE: return new OracleDAOFactory(); default: ... ; // erreur } } }
R. Grin Mapping objet-relationnel page 56

Une fabrique concrte


public class MySQLDAOFactory extends DAOFactory { @Override public StyloDAO getStyloDAO() { return new MySQLStyloDAO(); } @Override public FactureDAO getFactureDAO() { return new MySQLFactureDAO(); } ... }
R. Grin Mapping objet-relationnel page 57

Interface des DAO pour Stylo


public interface StyloDAO { public int insert(...); public boolean delete(...); public StyloTO find(...); public boolean update(...); public RowSet selectRS(...); public Collection selectTO(...); ... }

R. Grin

Mapping objet-relationnel

page 58

DAO concret pour Stylo


import java.sql.*; public class MySQLStyloDAO implements StyloDAO { public MySQLStyloDAO() { ... } public int insert() { ... } public boolean delete() { ... } public StyloTO find() { ... } public boolean update(...); public RowSet selectRS(...); public Collection selectTO(...); ... }
R. Grin Mapping objet-relationnel page 59

TO pour Stylo
import java.io.Serializable; public class StyloTO implements Serializable { private String reference; private String name; ... // Accesseurs et modificateurs public String getReference() {...} public void setReference(String ref) {...} ... }
R. Grin Mapping objet-relationnel page 60

10

Bibliographie
Patterns of Entreprise Application Architecture de Martin Fowler Addison Wesley Prsentation du pattern DAO et implmentation en Java, par Sun : http://java.sun.com/blueprints/corej2eepattern s/Patterns/DataAccessObject.html

R. Grin

Mapping objet-relationnel

page 61

11

Modle objet - relationnel SQL99


Universit de Nice Sophia-Antipolis
Version 0.9.5 16/9/06

Introduction

Richard Grin

R. Grin

Objet-relationnel

page 2

Modle objet-relationnel
Le modle objet-relationnel (OR) reprend le modle relationnel en ajoutant quelques notions qui comblent les plus grosses lacunes du modle relationnel La compatibilit est ascendante : les anciennes applications relationnelles fonctionnent dans le monde OR La norme SQL99 (SQL3) reprend beaucoup d'ides du modle OR
R. Grin Objet-relationnel page 3

Pourquoi tendre le modle relationnel ?


La reconstitution dobjet complexes clats en tables relationnelles est trs coteuse car elle occasionne de nombreuses jointures Pour chapper aux clatements-jointures, l'OR rhabilite n les rfrences qui permettent d'implanter des structures complexes n les attributs multivalues (tableaux, ensembles ou listes)
R. Grin Objet-relationnel page 4

Pourquoi tendre le modle relationnel ?


L'utilisation de rfrences facilite aussi l'utilisation des donnes trs volumineuses du multimdia en permettant leur partage simplement et moindre cot (sans jointure)

Pourquoi tendre le modle relationnel ?


Limpossibilit de crer de nouveaux types implique un manque de souplesse et une interface difficile avec les applications orientes objet L'OR permet de dfinir de nouveaux types utilisateur simples ou complexes (User data type), avec des fonctions ou procdures associes comme dans les classes des langages objet
R. Grin Objet-relationnel page 6

R. Grin

Objet-relationnel

page 5

Pourquoi tendre le modle relationnel ?


L'OR supporte l'hritage de type pour profiter du polymorphisme et faciliter la rutilisation

Pourquoi ne pas passer directement aux SGBD Objet ?


Le relationnel a ses avantages, en particulier n sa grande facilit et efficacit pour effectuer des recherches complexes dans des grandes bases de donnes n la facilit de spcifier des contraintes dintgrit sans programmation n une thorie solide et des normes reconnues

R. Grin

Objet-relationnel

page 7

R. Grin

Objet-relationnel

page 8

Pourquoi ne pas passer directement aux SGBD Objet ?


Inertie de l'existant : de trs nombreuses bases relationnelles en fonctionnement Manque de normalisation pour les SGBDO ; trop de solutions propritaires Moins souple que le relationnel pour sadapter plusieurs applications et laugmentation de charge
Peu d'informaticiens forms aux SGBDO

Les nouvelles possibilits de lOR


Dfinir de nouveaux types complexes avec des fonctions pour les manipuler Une colonne peut contenir une collection (ensemble, sac, liste) Ligne considre comme un objet, avec un identificateur (Object Identifier OID) Utilisation de rfrences aux objets Extensions du langage SQL (SQL3 ou SQL99) pour la recherche et la modification des donnes
R. Grin Objet-relationnel page 10

Le modle OR peut permettre un passage en douceur R. Grin Objet-relationnel page 9

Les problmes de l'OR


Ne s'appuie pas sur une thorie solide comme le modle relationnel Manque de standard de fait : implantations diffrentes, et encore partielles, dans les divers SGBDs

SQL99 (SQL3)
Cette partie du cours sappuie autant que possible sur les spcifications de SQL99 Le langage de programmation SQL99 ajoute SQL2 des variables et instructions de contrle pour en faire un langage procdural complet ; ce cours ne porte pas sur ces extensions Les exemples concrets sont donns dans le langage SQL de la version 10g dOracle ; les diffrences avec SQL99 seront signales
R. Grin Objet-relationnel page 12

R. Grin

Objet-relationnel

page 11

Nouveaux types prdfinis


Le relationnel objet ajoute des types prdfinis la norme SQL (tudis plus loin dans le cours) : n rfrence n collection n LOB (li aux objets de grande taille)

Types dfinis par lutilisateur

R. Grin

Objet-relationnel

page 13

R. Grin

Objet-relationnel

page 14

Les types utilisateur


Le dveloppeur peut aussi crer ses propres types de donnes : n types distincts n types structurs

Types distincts
Ces types permettent de mieux diffrencier les domaines des colonnes ; ils sont forms partir des types de base :
CREATE TYPE codePays as char(2); CREATE TYPE matricule as integer;

Par exemple, pour diffrencier le domaine des colonnes matricule et numDept Ces types sutilisent exactement avec les mmes instructions que le type de base sousjacent
R. Grin Objet-relationnel page 15 R. Grin Objet-relationnel page 16

Types structurs
Correspondent aux classes des langages objets Ils peuvent contenir des constructeurs, attributs ( variables dinstances), fonctions et procdures ( mthodes) Les membres peuvent tre public, protected ou private Les fonctions et procdures peuvent tre crites en SQL ou en un autre langage

Cration dun type de donnes


La syntaxe est semblable celle de la cration dune table :
CREATE TYPE departement_type AS OBJECT (numDept integer, nomD varchar(30), lieu varchar(30));

Un type ne peut contenir de contrainte dintgrit La commande create or replace type permet de redfinir un type sil existe dj
R. Grin Objet-relationnel page 18

R. Grin

Objet-relationnel

page 17

Fonctions dans les types


CREATE TYPE departement_type AS OBJECT (numDept integer, nomD varchar(30), lieu varchar(30), MEMBER FUNCTION getLieu RETURN varchar); CREATE TYPE BODY departement_type AS MEMBER FUNCTION getLieu RETURN varchar IS begin return lieu; end; end;
R. Grin Objet-relationnel page 19

Hritage
Les types supportent lhritage multiple avec le mot-cl UNDER :
create type employe_type as object (matr integer, nom varchar(30), sal numeric(8,2)) not final; create type commercial_type under employe_type (comm numeric(8,2)) not final;

Un type est final par dfaut


R. Grin Objet-relationnel page 20

Ajout dun attribut dans un type


alter type employe_type add attribute date_naissance date cascade; Propage aux tables dj construites partir du type

Ajout dune mthode/fonction un type


alter type employe_type add member function age return integer cascade;

R. Grin

Objet-relationnel

page 21

R. Grin

Objet-relationnel

page 22

Type de ligne
SQL99 possde aussi la notion de type de ligne qui correspond aux structures du C : cest un ensemble non encapsul dattributs Le type peut tre nomm ou non

Type de ligne non nomm


create table EMP (nomE varchar(35), adresse ROW(numero integer, rue varchar(30),))

R. Grin

Objet-relationnel

page 23

R. Grin

Objet-relationnel

page 24

Type de ligne nomm


CREATE ROW TYPE adresse_t (numero integer, rue varchar(30),) On peut ensuite utiliser ce type pour une dclaration dattribut ou mme pour crer une table partir de ce type (comme pour les autres types)

Vues du dictionnaire des donnes


USER_TYPES pour les types (et les collections) USER_TYPE_ATTRS pour attributs des types USER_TYPES_METHODS pour les mthodes des

types
USER_OBJECT_TABLES pour les tables objet-

relationnelles Sous sqlplus de Oracle : describe departement_type

R. Grin

Objet-relationnel

page 25

R. Grin

Objet-relationnel

page 26

Cration dune table partir dun type Tables


Les donnes dun type ne sont persistantes que si elles sont ranges dans une table On peut crer des tables comme en SQL92 On peut aussi crer des tables partir dun type de donnes

R. Grin

Objet-relationnel

page 27

R. Grin

Objet-relationnel

page 28

Cration dune table partir dun type


Soit le type employe_type :
CREATE TYPE employe_type AS OBJECT (matricule integer, nom varchar(30), . . . dept integer);

Hritage de tables
Une table peut hriter dune ou plusieurs tables Pas support par Oracle 10g

On peut crer une table partir de ce type et indiquer des contraintes dintgrit :
create table employe OF employe_type (primary key (matricule));
R. Grin Objet-relationnel page 29 R. Grin Objet-relationnel page 30

Cration de table partir dun type driv


create table commerciaux of commercial_type (constraint pk_com primary key(matr));

Caractristiques dune table objet-relationnelle


Une table est une table objet-relationnelle si elle a t construite partir dun type (create table OF) Les lignes de ces tables sont considres comme des objets avec un identifiant (OID) On peut utiliser des rfrences pour dsigner les lignes de ces tables (pas possible pour les autres tables)
R. Grin Objet-relationnel page 32

R. Grin

Objet-relationnel

page 31

Vues du dictionnaire des donnes


USER_OBJECT_TABLES pour les tables objet-

Insertion de donnes
On ajoute des donnes comme avec une table normale : insert into commerciaux (matr, nom, sal, comm) values (234, 'TITI', 3200, 600);

relationnelles

R. Grin

Objet-relationnel

page 33

R. Grin

Objet-relationnel

page 34

Insertion avec constructeur


On peut aussi utiliser le constructeur du type avec lequel la table a t construite : insert into employe values ( employe_type(125, 'Dupond', ...)); Si le type est un type utilis par un autre type, lutilisation du constructeur du type est obligatoire

Modifications
Utiliser la notation pointe comme en SQL92 :
update employe set employe.salaire = 12000 where employe.nom = 'Dupond';

SQL99 fournit aussi la notation .. pour dsigner un attribut dune colonne de type structur :
update employe set employe.adresse..numero = 12 where employe.nom = 'Dupond';

R. Grin

Objet-relationnel

page 35

R. Grin

Objet-relationnel

page 36

Appel de procdure ou fonction


select e.nom, age(e) from employe e where age(e) < 40 Sous Oracle : select e.nom, e.age() from employe e where e.age() < 40
Le this est pass en paramtre

Rfrences

R. Grin

Objet-relationnel

page 37

R. Grin

Objet-relationnel

page 38

Rfrences
On peut indiquer dans la dfinition dun type quun attribut contient des rfrences (et non des valeurs) des donnes dun autre type ; la syntaxe est REF nom-du-type :
create type employe_type as object (matricule integer, nom varchar(30), . . . dept REF dept_type);

Exemple de select avec rfrence


La notation pointe permet de rcuprer les attributs dun type dont on a un pointeur Lieu de travail des employes (avec Oracle) :
select nom, e.dept.lieu from employe e

En SQL99 :
select nom, e.dept->lieu from employe e

Attention, lalias e est indispensable

R. Grin

Objet-relationnel

page 39

R. Grin

Objet-relationnel

page 40

Insertions avec rfrence


insert into employe values ( 1230, 'Durand', , NULL); pointeur NULL

Modifications avec rfrence


update employe set dept = (select REF(d) from dept d where numDept = 10) where matricule = 7500;

insert into employe(matricule, nom, dept) select 1240, 'Dupond', REF(d) from dept d where dept.numDept = 10; rfrence vers le dept de numro 10
R. Grin Objet-relationnel page 41

Attention, cette instruction peut trs bien mettre la valeur NULL dans la colonne dept car le select renvoie NULL si le dpartement de numro 10 nexiste pas !
R. Grin Objet-relationnel page 42

Contrainte NOT NULL


Pour viter le problme de lexemple prcdent, il faut ajouter la contrainte NOT NULL sur la colonne dept :
dept REF dept_type NOT NULL

Contrainte sur les rfrences


Le type REF dept_type restreint le type rfrenc mais pas la table rfrence Une telle rfrence peut rfrencer une valeur de nimporte quelle colonne de table qui a le type dept_type La clause SCOPE restreint la colonne rfrence ; elle peut tre ajoute lors de la dfinition dune table

R. Grin

Objet-relationnel

page 43

R. Grin

Objet-relationnel

page 44

Exemple de SCOPE
dept REF dept_type scope is dept_table

Rfrence perdue
SCOPE ne suffit pas pour imposer une contrainte stricte Ainsi la rfrence peut tre pendante (dangling) ou perdue , cest--dire ne pas correspondre une ligne existante, si la ligne rfrence au dpart a t ensuite supprime

indique que dept rfrencera une ligne de la table dept_table (et pas une ligne dune autre table cre partir du type dept_type)

R. Grin

Objet-relationnel

page 45

R. Grin

Objet-relationnel

page 46

References
Pour viter les rfrences perdues il faut remplacer la contrainte SCOPE par une contrainte REFERENCES (comme avec les tables relationnelles) :
dept REF dept_type references dept_table

Collections

R. Grin

Objet-relationnel

page 47

R. Grin

Objet-relationnel

page 48

Types de collections
Pour reprsenter une colonne multivalue, on peut utiliser les collections : n ensembles (au sens mathmatiques ; pas de doublons) n sacs (avec des doublons) n listes (ordonnes et indexes par un entier) Dautres types de collections peuvent tre ajoutes par les SGBD

Exemple de collection
create type employe_type (matricule integer, nom varchar(30), prenoms LIST(varchar(15)), enfants SET(personne), . . .);

R. Grin

Objet-relationnel

page 49

R. Grin

Objet-relationnel

page 50

Utilisation dune collection


On peut utiliser une collection comme une table en la faisant prcder par le mot-cl TABLE :
select nom from employe E where nom in (select * from TABLE(E.prenoms))

Les collections avec Oracle 10g


Oracle 10g noffre que 2 types de collections : n table imbrique (NESTED TABLE) qui est une collection non ordonne et non limite en nombre dlments n tableau prdimensionn (VARRAY) qui est une collection dlments de mme type, ordonne et limite en taille

On peut aussi faire afficher une collection comme un tout :


select nom, prenoms from employe

R. Grin

Objet-relationnel

page 51

R. Grin

Objet-relationnel

page 52

Tables imbriques
Une table relationnelle (pas ncessairement OR) peut contenir une ou plusieurs tables imbriques Pas tudi dans ce cours ; se reporter au manuel Oracle pour plus de prcisions

Tableaux dimensionns
Un VARRAY est une collection ordonne et limite en nombre, dlments dun mme type On peut imbriquer plusieurs tableaux dimensionns en utilisant des pointeurs sur des tableaux

R. Grin

Objet-relationnel

page 53

R. Grin

Objet-relationnel

page 54

Exemple de VARRAY
create type telephones_type as VARRAY(3) OF varchar(10); insert into personne (nom, telephones) values('Dupond', telephones_type('0492077987', '0492074567'));

Rfrence
Programmer objet avec Oracle de Christian Soutou Vuibert

R. Grin

Objet-relationnel

page 55

R. Grin

Objet-relationnel

page 56

10

Plan de cette partie

JDBC avanc
Universit de Nice - Sophia Antipolis
Version 1.8 14/10/06 Richard Grin

Transaction et exception Gnration des cls ResultSet avanc RowSet Regrouper les modifications BLOB et CLOB Pool de connexions, source de donnes Transaction distribue
R. Grin JDBC avanc page 2

Exception Rollback ?
Une exception ne provoque pas le rollback dune transaction Cest le code Java qui doit explicitement appeler la mthode rollback() sil le faut Une exception peut signaler un problme rcuprable ; en ce cas le programme peut choisir une alternative pour terminer correctement la transaction

Transactions et exceptions

R. Grin

JDBC avanc

page 3

R. Grin

JDBC avanc

page 4

Quelques rgles usuelles


Les exceptions non contrles correspondent souvent des erreurs non rcuprables ; en ce cas le catch correspondant lancera un rollback Les exceptions contrles sont parfois rcuprables ; par exemple, si la cl existe dj, on peut changer de cl, ou faire un update la place dun insert Chaque cas est particulier et peut suivre dautres rgles
R. Grin JDBC avanc page 5

Exemple
try { ... conn.commit(); } catch(SQLException e) { // La situation ne permet pas // de corriger le problme conn.rollback(); }

R. Grin

JDBC avanc

page 6

Exemple
try { ... conn.commit(); } catch(SQLException e) { // La situation est rcuprable. // Le code qui suit corrige le problme . . . conn.commit(); }
R. Grin JDBC avanc page 7

Gnration automatique de cls et JDBC

R. Grin

JDBC avanc

page 8

Gnration de cls
La gnration automatique de cls nest pas standardis Oracle utilise des squences (comme DB2 et PostgreSQL) Dautres SGBD utilisent dautres mthodes : n attribut AUTO_INCREMENT sur une colonne pour MySQL n attribut IDENTITY pour SQL Server n
R. Grin JDBC avanc page 9

Une situation courante


Une situation peut ncessiter la connaissance dune cl gnre automatiquement Exemple : une facture est compose dune table pour len-tte de la facture (numro de la facture, client, date,) et dune table pour les lignes de la commande Pour crire les lignes de la facture on a besoin de connatre la cl de len-tte de la facture (chaque ligne contient une cl trangre vers cette cl de len-tte) et cette cl est gnre automatiquement
R. Grin JDBC avanc page 10

Une situation courante


La rcupration dune cl automatique ne devrait pas ncessiter de lancer une requte SQL avec un accs la base de donnes (toujours coteux)

getGeneratedKeys
Linterface Statement contient une mthode ResultSet getGeneratedKeys() qui renvoie toutes les cls gnres par lordre SQL, indpendamment de la manire dont elles ont t gnres, et sans accs supplmentaire la base de donnes Le ResultSet renvoy est vide si aucune cl na t gnre

R. Grin

JDBC avanc

page 11

R. Grin

JDBC avanc

page 12

Lecture des cls gnres


2 choses faire si on a besoin de connatre la cl gnre automatiquement par le SGBD au moment de linsertion dune nouvelle ligne : 1. indiquer la mthode executeUpdate que les cls gnres seront rcupres 2. utiliser la mthode getGeneratedKeys() aprs linsertion

Pour executeUpdate
Pour indiquer executeUpdate que lon souhaite rcuprer les cls gnres on doit indiquer dans un 2me paramtre n soit la valeur Statement.RETURN_GENERATED_KEYS n soit un tableau dentiers int[] indiquant les numros des colonnes du insert qui contiennent les cls gnrs que lon veut rcuprer
R. Grin JDBC avanc page 14

R. Grin

JDBC avanc

page 13

Exemple
Ajout dune nouvelle facture dans la base On a besoin de la cl gnre pour la facture pour la mettre en cl trangre dans les lignes de la facture (ne marche pas avec Oracle ; utiliser plutt seq.currval)

Exemple
Statement stmt = conn.createStatement(); // Ne pas oublier le 2me paramtre optionnel stmt.executeUpdate( "INSERT INTO facture VALUES(...)", Statement.RETURN_GENERATED_KEYS); ResultSet rsCles = stmt.getGeneratedKeys(); if ( rsCles.next() ) { int cle = rsCles.getInt(1); } // cle sera utilis pour insrer les // lignes de facture
R. Grin JDBC avanc page 16

R. Grin

JDBC avanc

page 15

Problme dimplmentation ?
Il semble que peu de drivers implmentent la mthode getGeneratedKeys Par exemple, le driver Oracle ne limplmente pas

Cls gnres et Oracle


Pour Oracle on peut n rcuprer la valeur courante (ou prochaine) de la squence seq avec seq.currval (ou seq.nextval) dans une colonne dun select, n utiliser cette valeur dans les ordres insert de la facture et des lignes de facture Rappel : currval ne dpend que des cls gnres dans la session courante (ne dpend pas des cls gnres par dautres sessions)
R. Grin JDBC avanc page 18

R. Grin

JDBC avanc

page 17

Nouvelles possibilits de JDBC 2.0 et 3.0


Parcourir un ResultSet dans les 2 sens Modifier les donnes de la base correspondant aux donnes renvoyes par un ResultSet directement par des mthodes de ResultSet, sans utiliser SQL Regrouper plusieurs ordres SQL pour les envoyer au SGBD Pools de connexions
R. Grin JDBC avanc page 19 R. Grin

ResultSet

JDBC avanc

page 20

Types de ResultSet
3 types de ResultSet : n TYPE_FORWARD_ONLY : ne peut pas tre parcouru que dans un sens n TYPE_SCROLL_INSENSITIVE : peut tre parcouru dans les 2 sens, mais ne reflte pas les modifications faites dans la base aprs la rcupration du ResultSet n TYPE_SCROLL_SENSITIVE : peut tre parcouru dans les 2 sens, et reflte les modifications faites dans la base aprs la rcupration du ResultSet
R. Grin JDBC avanc page 21

Types de ResultSet
Paralllement ces types, un ResulSet peut tre n CONCUR_READ_ONLY : on ne peut pas modifier les donnes en passant par le ResultSet n CONCUR_UPDATABLE : on peut modifier les donnes en passant par le ResultSet On peut donc avoir 6 types (3 x 2) de ResultSet En fait, tous les drivers ne les permettent pas avec de bonnes performances
R. Grin JDBC avanc page 22

Choix dun type de ResultSet


Des variantes des mthodes createStatement, prepareStatement et prepareCall de la classe Connection permettent de faire ce choix

Permettre le parcours double sens dans un ResultSet


Statement stmt = conn.createStatement( ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY); ResultSet srs = stmt.executeQuery( "SELECT nomE, salaire FROM emp");

R. Grin

JDBC avanc

page 23

R. Grin

JDBC avanc

page 24

Parcours en avant dans un ResultSet


Les transparents suivants montrent les possibilits offertes par les ResultSet scrollable (ceux qui permettent de se dplacer o lon veut dans les lignes)
// A ajouter si on ne vient pas de rcuprer // le ResultSet : srs.beforeFirst() while (srs.next()) { String nomE = srs.getString("nomE"); double salaire = srs.getFloat("salaire"); System.out.println(nomE + " ; " + salaire); }

R. Grin

JDBC avanc

page 25

R. Grin

JDBC avanc

page 26

Parcours en arrire dans un ResultSet


srs.afterLast(); while (srs.previous()) { String nomE = srs.getString("nomE"); double salaire = srs.getFloat("salaire"); System.out.println(nomE + " ; " + salaire); }

Positionnement absolu et relatif dans un ResultSet


srs.absolute(-2); // avant-dernire ligne srs.absolute(4); int numLigne = srs.getRow(); // rowNum = 4 srs.relative(-3); int numLigne = srs.getRow(); // rowNum = 1 srs.relative(2); int numLigne = srs.getRow(); // rowNum = 3 Les numros de lignes et de colonnes commencent 1 (pas 0)

R. Grin

JDBC avanc

page 27

R. Grin

JDBC avanc

page 28

ResultSet modifiable
Si le select et si la colonne du select le permettent, il est possible de modifier la valeur dune colonne dune ligne renvoye par le select et denregistrer cette modification dans la base de donnes Sinon, la mthode updateXXX ou la mthode updateRow lancera une exception

ResultSet modifiable
Le select dun ResultSet modifiable doit (cf. conditions sur les vues) n ne pas contenir de jointure ou de group by
n contenir la cl primaire de la table Les expressions des colonnes modifies doivent tre de simples noms de colonnes de tables Exemple de colonne non modifiable : une colonne qui contient une expression avec une fonction SQL
R. Grin JDBC avanc page 30

R. Grin

JDBC avanc

page 29

Cration d'un ResultSet modifiable


Statement stmt = con.createStatement( ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet uprs = stmt.executeQuery( "SELECT nomE, salaire FROM emp");

Modifier des lignes par un ResultSet


uprs.last(); uprs.updateDouble("salaire", 10000); uprs.cancelRowUpdates(); // annule uprs.updateDouble(2, 12000); uprs.updateRow(); // enregistre modifs dans BD

Ne pas oublier updateRow() ! updateNull permet de donner la valeur NULL


R. Grin JDBC avanc page 31 R. Grin JDBC avanc page 32

Insrer des lignes par un ResultSet Va dans le buffer


dans lequel seront uprs.moveToInsertRow(); ranges les valeurs de la nouvelle ligne uprs.updateInt("matr", 150); uprs.updateString("nomE", "Kleber"); uprs.updateDouble("salaire", 10000); . . . uprs.insertRow();

Supprimer la ligne courante dun ResultSet


uprs.absolute(4); uprs.deleteRow();

R. Grin

JDBC avanc

page 33

R. Grin

JDBC avanc

page 34

Validation des modifications


Comme pour les autres commandes de modification des donnes de la base, les modifications doivent tre valides (resp. invalides) par un appel de la mthode commit() (resp. rollback()) de la connexion en cours (sauf si la connexion est en mode autocommit, ce qui nest pas recommand)

RowSet

R. Grin

JDBC avanc

page 35

R. Grin

JDBC avanc

page 36

Prsentation
ResulSet qui ont lavantage de se conformer au modle des Java Beans (srialisables, avec proprits, et observables par des couteurs) Reprsents dans lAPI par des interfaces, dont linterface racine javax.sql.RowSet hrite de ResultSet Le JDK 5 fournit des implmentations des diffrentes sous-interfaces de RowSet

Rowset dconnectable
Certains rowsets peuvent tre dconnects de la base aprs avoir rcupr des donnes dans la base On peut alors modifier leurs donnes en mode dconnect Le rowset peut ensuite se reconnecter et enregistrer les modifications dans la base

R. Grin

JDBC avanc

page 37

R. Grin

JDBC avanc

page 38

Sous-interfaces de RowSet
Interfaces du paquetage javax.sql.rowset : n JDBCRowSet : rowset qui reste connect n CachedRowSet : rowset dconnectable n WebRowSet : fille de CachedRowSet qui peut se sauvegarder au format XML n JoinRowSet et FilterRowSet : filles de WebRowSet qui reprsentent des rowsets sur lesquels on peut effectuer des jointures et des slections quand ils sont dconnects
R. Grin JDBC avanc page 39

JdbcRowSet
Cest essentiellement une enveloppe autour dun ResultSet, qui a les proprits dun Java bean Le rowset est modifiable (si le select le permet) et peut tre parcouru dans les 2 sens, mme sil enveloppe un resultSet qui ne le permettait pas Une implmentation est fournie avec la distribution Java : com.sun.rowset.JdbcRowSetImpl
R. Grin JDBC avanc page 40

JdbcRowSet
2 constructeurs : n avec un ResultSet en paramtre, pour envelopper un ResultSet existant n sans paramtre ; il faudra ensuite donner les informations pour la connexion la base et pour indiquer les donnes rcuprer

JdbcRowSet constructeur avec un paramtre ResultSet


Statement stmt = conn.createStatement(); ResultSet r = stmt.executeQuery("select ... "); JdbcRowSet rs = new JdbcRowSetImpl(r); while (rs.next()) { String nom = rs.getString(1); ... }
R. Grin JDBC avanc page 42

R. Grin

JDBC avanc

page 41

JdbcRowSet constructeur sans paramtre


JdbcRowSet rs = new JdbcRowSetImpl(); rs.setUsername(...); Initialisation rs.setPassword(...); rs.setUrl(...); rs.setCommand("select ... "); rs.execute(); Rcupration des donnes while (rs.next()) { String nom = rs.getString(1); ... }
R. Grin JDBC avanc page 43

Jokers dans la commande


Outre le ResultSet, un rowset cr avec le constructeur sans paramtre enveloppe aussi un PreparedStatement La chane quon passe en paramtre de setCommand peut comporter des joker ? On peut passer les valeurs correspondantes par des mthodes setXXX comme pour les PreparedStatement

R. Grin

JDBC avanc

page 44

Exemple
rs.setCommand("select nome, salaire " + " from employe where dept = ?"); rs.setInt(1, 20); rs.execute();

Dplacement
Un rowset peut tre toujours tre parcouru dans les 2 sens La syntaxe est semblable celle de ResultSet

R. Grin

JDBC avanc

page 45

R. Grin

JDBC avanc

page 46

Modifications
Les donnes contenues dans le rowset peuvent tre modifies avec les mthodes habituelles de ResultSet Les mthode commit et rollback de JDBCRowSet valident ou invalident les modification de la transaction courante Elles ne doivent tre utilises que si la transaction nest pas en autoCommit ; voir mthodes {get|set}AutoCommit de JDBCRowSet (par dfaut la connexion est en autoCommit)
R. Grin JDBC avanc page 47

Exemple
rs.absolute(4); rs.updateString("nom", "Dupond"); rs.updateRow(); rs.beforeFirst(); rs.next(); rs.updateInt(3, 135); rs.updateRow(); rs.commit()

R. Grin

JDBC avanc

page 48

RowSet dconnectable
Interface CachedRowSet Il se connecte la base juste le temps de rcuprer des donnes Il peut tre dconnect de la base ; il est alors possible de lire, modifier, supprimer des donnes du rowset (mme syntaxe que ResultSet) en local Il peut ensuite se reconnecter pour rpercuter dans la base les modifications faites pendant la dconnexion (mthode acceptChanges())
R. Grin JDBC avanc page 49

Remplir un CachedRowSet
Un CachedRowSet peut tre rempli avec les donnes dun ResultSet par la mthode populate(ResultSet) Cependant le plus simple est souvent dinitialiser le CachedRowSet pour quil puisse se connecter la base (mthodes setUsername, setPassword, setUrl ou setDataSourceName), et indiquer la commande pour rcuprer les donnes (setCommand) On peut ensuite lancer cette commande par la mthode execute
R. Grin JDBC avanc page 50

Connexion dun rowset


Lutilisation de la mthode populate ne renseigne pas le rowset sur la faon de se connecter la base Un connexion ncessite donc de renseigner le rowset avec les mthodes setUsername, setPassword ; la base est indique par son URL (setUrl) ou par son nom de source de donnes (setDataSourceName ; voir la section sur les sources de donnes plus loin dans ce support)
R. Grin JDBC avanc page 51

Connexions la base
Les mthodes execute et acceptChanges peuvent recevoir en paramtre une connexion la base En ce cas, cette connexion est utilise pour lire ou crire les donnes dans la base de donnes Sinon, le rowset ouvre une connexion en interne en utilisant les proprits de connexion du rowset

R. Grin

JDBC avanc

page 52

Modifier les donnes


Les donnes dun CachedRowSet peuvent tre modifies par divers mthodes updateXXX hrites de ResultSet Si la commande SQL le permet (contraintes semblables aux contraintes pour les vues modifiables), les modifications peuvent ensuite tre enregistres dans la base de donnes grce la mthode acceptChanges Le rowset se reconnecte la base, enregistre les modifications, puis se dconnecte
R. Grin JDBC avanc page 53

Validation des modifications


Un commit est effectu chaque appel de acceptChanges

R. Grin

JDBC avanc

page 54

Annulations de modifications
Les mthode undoInsert(), undoDelete() et undoUpdate() annulent la dernire modification de type insert, delete ou update effectue sur le rowset Il est ainsi possible dannuler plusieurs modifications qui ont t effectue depuis le dernier acceptChanges

Table modifie
Avec certains SGBD (Oracle en particulier) il peut tre ncessaire dindiquer la table sur laquelle les modifications seront faites, par la mthode setTableName(String) Avec dautres, le rowset peut avoir cette information par les mta donnes Des implmentations (Creator de Sun par exemple) utilisent cette mthode pour restreindre une seule table ce qui est insr dans la base lorsque le select du rowset concerne plusieurs tables (permet de modifier
des rowset qui ont un select avec jointure)
R. Grin JDBC avanc page 56

R. Grin

JDBC avanc

page 55

Conflits la reconnexion
Il peut videmment y avoir des conflits au moment de la reconnexion la base si les donnes initialement lues par le rowset ont t modifies pendant sa dconnexion Le traitement de ces conflits dpend de limplmentation du rowset Limplmentation de CachedRowSet fournie par dfaut utilise un blocage optimiste

Traitement optimiste des conflits


Quand le rowset rcupre les donnes dans la base, il enregistre ces donnes comme valeurs originales Au moment de lenregistrement des modifications (acceptChanges) ces valeurs originales sont compares aux valeurs actuelles de la base Il ny a pas de conflit sil y a galit Sinon, cest que les donnes ont t modifies dans la base par un tiers, et il y a conflit
R. Grin JDBC avanc page 58

R. Grin

JDBC avanc

page 57

Colonnes pour identifier les lignes


Si le CachedRowSet doit tre modifi et si on veut rpercuter ces modifications dans la base, il est indispensable dindiquer une (ou plusieurs) colonne qui servira didentificateur de ligne dans le rowset par la mthode setKeyColumns Le CachedRowSet pourra ainsi comparer les lignes du rowset avec les lignes de la base pour vrifier sil ny a pas de conflit
R. Grin JDBC avanc page 59

Code pour donner les colonnes identifiantes


// La 1re colonne servira identifier rs.setKeyColumns(new int[] {1});

R. Grin

JDBC avanc

page 60

10

Schma pour enregistrer les modifications


... // Plusieurs modifications des donnes rs.updateInt(2, 134); rs.updateRow(); ... try { rs.acceptChanges(); } catch(SyncProviderException e) { // Traitement des conflits ... // voir transparent suivant }
R. Grin JDBC avanc page 61

Traitement des conflits


SyncResolver resolv = e.getSyncResolver(); while (resolv.nextConflict()) { if (resolv.getStatus() == SyncResolver.UPDATE_ROW_CONFLICT) { int row = resolv.getRow(); rs.absolute(row); int nbCol = rs.getMetaData().getColumnCount(); // Traitement des conflits dune ligne

R. Grin

JDBC avanc

page 62

Traitement des conflits dune ligne


Pour les lignes qui ont provoqu un conflit, le resolver (SyncResolver) contient la valeur actuelle dans la base pour les colonnes de la ligne qui ont chang de valeur Pour les autres colonnes, le resolver a la valeur null

Traitement des conflits dune ligne


for (int j = 1; j <= nbCol; j++) { if (resolv.getConflictValue(j) != null) { Object valRs = rs.getObject(j); Object valResolv = resolv.getConflictValue(j); // Dcide ce quil faut faire . . . resolv.setResolvedValue(j, ...); } } La valeur quon a dcid de mettre dans la base
R. Grin JDBC avanc page 64

R. Grin

JDBC avanc

page 63

Rsolution des confllits


La mthode setResolvedValue met la valeur originale du rowset la valeur actuelle de la base de donnes Ainsi, au prochain appel de la mthode acceptChanges, il ny aura plus de conflit (si la valeur dans la base na pas nouveau t modifie entre-temps) Attention, aprs avoir rsolu tous les conflits il ne faut pas oublier dappeler acceptChanges pour enregistrer dans la base les valeurs choisies
R. Grin JDBC avanc page 65

Autres possibilits
release permet de vider un CachedRowSet : il ne contient plus aucune donnes (mais les informations sur la connexion ne sont pas touches)

R. Grin

JDBC avanc

page 66

11

Autres possibilits
CachedRowSet permet aussi dajouter des observateurs et de les avertir si on change de ligne, si une ligne est modifie ou si le rowset est rempli avec dautres donnes (add/removeRowSetListener, cursorMoved, rowChanged, rowSetChanged) Il est aussi possible de rcuprer les donnes dans la base page par page lorsquil y a une grande quantit de donnes rcuprer (setPageSize, nextPage, previousPage)
R. Grin JDBC avanc page 67 R. Grin

Regrouper des modifications

JDBC avanc

page 68

Performances
Dans les applications distribues il est important de rduire le nombre daccs distants aux bases de donnes pour amliorer les performances Les procdures stockes le permettent mais elles provoquent des problmes de portabilit On peut aussi regrouper plusieurs ordres SQL de type DML (insert, update, delete) pour les envoyer en une fois au SGBD Un driver JDBC peut ne pas implmenter cette fonctionnalit
R. Grin JDBC avanc page 69

Les mthodes
3 mthodes de linterface Statement (et donc aussi de ses sous-interfaces) permettent de manipuler les regroupements dordres SQL Elles peuvent lancer une SQLException void addBatch(String sql) : ajoute un ordre SQL la liste des ordres excuter int[] executeBatch() : excute les ordres SQL void clearBatch() : enlve toutes les ordres de la liste
R. Grin JDBC avanc page 70

Mthode executeBatch
Elle retourne un tableau dentiers qui indique le nombre de lignes modifies par chacun des ordres regroups ; la valeur peut tre ngative sil y a eu des problmes (voir javadoc pour plus de prcisions) Si une des commandes na pu tre excute correctement, une BatchUpdateException est renvoye ; les ordres SQL suivants sont excuts ou non suivant le driver (consulter la documentation du driver) ; on peut alors choisir de valider ou non la transaction
R. Grin JDBC avanc page 71

Exemple de regroupement
Statement stmt = conn.createStatement(); stmt.addBatch( "INSERT INTO DEPT " + "VALUES(70, 'Finances', 'Nancy')"); stmt.addBatch( "INSERT INTO DEPT " + "VALUES(80, 'Comptabilit', 'Nice')"); int[] nbLignes = stmt.executeBatch(); conn.commit();

R. Grin

JDBC avanc

page 72

12

Avec des requtes paramtres


PreparedStatement pstmt = conn.prepareStatement( "INSERT INTO DEPT VALUES(?, ?, ?)"); pstmt.setInt(1, 70); pstmt.setString(2, 'Finances'); pstmt.setString(3, 'Nancy'); pstmt.addBatch(); // Ajout dautres dpartements avec pstmt . . . int[] nbLignes = stmt.executeBatch(); conn.commit();
R. Grin JDBC avanc page 73 R. Grin

Nouveaux types de donnes de SQL3

JDBC avanc

page 74

Types de donnes de SQL3


JDBC supporte les types suivants de SQL3 : n BLOB (Binary Large Object) n CLOB (Character Large Object) n ARRAY n types structurs dfinis par lutilisateur n rfrences vers des instances de types structurs Les 3 derniers types sont tudis dans le cours sur JDBC et lobjet-relationnel
R. Grin JDBC avanc page 75

Blob et Clob
La plupart des SGBD fournissait dj les types BLOB et CLOB mais n ces types n'taient pas normaliss n l'accs par JDBC n'tait pas normalis n les possibilits de manipulation de ces types taient restreintes (pas de recherche sur le contenu, par exemple) Il existe maintenant des types BLOB et CLOB et des interfaces Java Blob et Clob normaliss
R. Grin JDBC avanc page 76

Interface Clob
On peut lire le contenu d'une colonne de type Clob comme un flot de caractres ASCII ou Unicode par les mthodes (valable seulement jusqu' la fin de la transaction)
InputStream getAsciiStream() Reader getCharacterStream()

Exemple de rcupration de Clob


Statement stmt = conn.createStatement(); ResultSet rset = stmt.executeQuery( "select * from livre where isbn = 1421"); if (rset.next()) { Clob clob = rset.getClob("resume"); long l = clob.length(); // Affiche par paquets de 80 caractres for (long i = 0; i < l; i += 80) { String pRes = clob.getSubString(i, 80); System.out.println(pRes); } } // Il reste afficher le dernier paquet
R. Grin JDBC avanc page 78

On peut aussi lire un Clob comme une String ; on peut rechercher la position d'une sous-chane de caractres dans un Clob, et extraire une partie du Clob :
long position(String sousCh, long debut) String getSubString(long pos, int longueur)
R. Grin JDBC avanc page 77

13

Enregistrer un Clob ou un Blob


La mthode setClob(int, Clob) de PreparedStatement met les objets de type Clob dans la base de donnes Pour les Blob, utiliser setBlob() Chaque driver peut fournir un constructeur de Blob et de Clob, par exemple partir de tableau doctets ou de caractres On peut aussi enregistrer un Blob ou un Clob partir de tableaux, avec la mthode setObject()
R. Grin JDBC avanc page 79

Avertissement
Les dernires parties de ce support ne sont que des survols rapides de possibilits avances offertes par JDBC et ses extensions Le but est de faire connatre lexistence de ces possibilits pour que le lecteur intress puisse approfondir leur tude par dautres sources

R. Grin

JDBC avanc

page 80

Politique de connexion Pools de connexions et sources de donnes


Une connexion une base de donnes est une ressource rare et coteuse qui ne peut tre partage par des threads Il faut donc rflchir la politique des connexions quand on crit une application qui utilise une base de donnes : n quand faut-il ouvrir et fermer une connexion ? n faut-il garder une connexion ouverte entre 2 utilisations de la base ?
page 81 R. Grin JDBC avanc page 82

R. Grin

JDBC avanc

Pool de connexions
Les choix pour une politique de connexion sont facilits si on travaille avec un pool de connexions dj ouvertes et disponibles pour les clients Lorsque le client na plus besoin de la connexion, il appelle la mthode close() qui la restitue au pool (la connexion nest pas ferme)

Comment obtenir un pool de connexions


On peut utiliser un des nombreux projets open source qui fournit le code pour grer un pool de connexion Le plus souvent un tel pool est fourni par une source de donnes de type DataSource

R. Grin

JDBC avanc

page 83

R. Grin

JDBC avanc

page 84

14

Source de donnes
Depuis JDBC 3 (mais dj en extension de JDBC 2), on peut obtenir une connexion dune instance de javax.sql.DataSource (une interface) au lieu de lobtenir de la classe DriverManager Une DataSource reprsente une base de donnes (mais elle peut aussi reprsenter un simple fichier texte) Tout driver JDBC 2 doit fournir une implmentation de DataSource ; oracle.jdbc.pool.OracleDataSource pour Oracle
R. Grin JDBC avanc page 85

Mthode getConnection
La mthode principale de DataSource est getConnection(String utilisateur, String motDePasse) qui renvoie une Connection (et peut lancer une SQLException) Si le nom et le mot de passe de lutilisateur ont t entrs en dur dans la configuration de la source, on peut aussi utiliser la mthode getConnection()
R. Grin JDBC avanc page 86

Utilisation dune DataSource


La connexion renvoye par getConnection peut tre une connexion ordinaire mais le plus souvent cest une connexion renvoye par un pool de connexion Lutilisation dune telle connexion se fait exactement comme une connexion ordinaire ; tout est transparent pour lutilisateur Une diffrence essentielle est que, lorsque le client appelle la mthode close de la connexion, celle-ci nest pas ferme mais remise dans le pool des connexions disponibles
R. Grin JDBC avanc page 87

Exemple dutilisation
OracleDataSource ds = new OracleDataSource(); ds.setURL("jdbc:oracle:thin:@sirocco.unic e.fr:1521:INFO"); ds.setUser("toto"); ds.setPassword("*****"); Connection conn = null; conn = ds.getConnection(); // Le reste est identique au code qui // nutilise pas de source de donnes . . .
R. Grin JDBC avanc page 88

Obtenir une DataSource


Le plus souvent, la source de donnes est enregistre auprs dun registre JNDI On lobtient en donnant la cl du registre qui lui correspond :
DataSource source = (DataSource) new InitialContext() .lookup("MaSource");

Configurer une DataSource


Le plus souvent elle se configure par un fichier XML de configuration ; voir le manuel des logiciels que vous utilisez Exemple : fichier server.xml de Tomcat Elle peut aussi se configurer par programmation ; voir la javadoc de la classe qui implmente DataSource

Ce code ne peut fonctionner que dans un environnement dans lequel fonctionne un registre JNDI (serveur dapplications le plus souvent)
R. Grin JDBC avanc page 89

R. Grin

JDBC avanc

page 90

15

Exemple avec Tomcat : server.xml


<Context path="/BDTest" ...> <Resource name="jdbc/TestDB" auth="Container" type="javax.sql.DataSource"/> <ResourceParams name="jdbc/TestBD"> <parameter> <name>factory</name> <value>org.apache.commons.dbcp.BasicDataSource Factory </value> </parameter>
R. Grin JDBC avanc page 91

Exemple avec Tomcat : server.xml


<! Le plus grand nombre de connexions dans le pool. Mettre 0 si pas de limite. --> <parameter> <name>maxActive</name> <value>100</value> </parameter>

etc

Voir la documentation Tomcat pour le reste du fichier server.xml

R. Grin

JDBC avanc

page 92

Exemple avec Tomcat : web.xml


<?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE web-app PUBLIC ...> <web-app> <description>TestDB</description> <resource-ref> <description>DB Connection</description> <res-ref-name>jdbc/TestBD</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> </resource-ref> </web-app>
R. Grin JDBC avanc page 93

Exemple avec Tomcat code servlet


import javax.naming.*; import javax.sql.*; ... Context context = new InitialContext(); DataSource ds = (DataSource)ctx.lookup( "jdbc/TestBD" ); Connection conn = ds.getConnection( "toto", "mdp" ); ... finally { if( conn != null ) { conn.close(); } }
R. Grin JDBC avanc page 94

Limite des transactions JDBC


Les transactions JDBC ne permettent pas une transaction de couvrir plusieurs connexions des bases de donnes diffrentes Pourtant, lexistence de nombreuses bases de donnes hrites du pass conduisent parfois les applications dentreprise travailler avec des transactions qui couvrent plusieurs bases de donnes la fois
page 95 R. Grin JDBC avanc page 96

(Java Transaction API)

Transactions JTA

R. Grin

JDBC avanc

16

JTA
Cette API fournit les classes pour travailler avec des transactions distribues sur plusieurs bases de donnes, ou mme des ressources qui ne sont pas des bases de donnes Elle est utilise par les serveurs dapplications

Rfrences sur les JTA


JTA nest pas tudie en dtails dans ce cours 2 rfrences : http://java.sun.com/products/jta/ http://www.theserverside.com/articles/article.ts s?l=Nuts-and-Bolts-of-Transaction-Processing

R. Grin

JDBC avanc

page 97

R. Grin

JDBC avanc

page 98

17

Types de donnes de SQL3

JDBC et relationnel-objet
Universit de Nice - Sophia Antipolis
Version 1.5 24/10/05 Richard Grin

JDBC supporte les types suivants de SQL3 qui sont des ouvertures vers le relationnelobjet : n ARRAY n types structurs dfinis par lutilisateur n rfrences vers des instances de types structurs

R. Grin

JDBC et relationnel-objet

page 2

Array
Le type de collection VARRAY dOracle permet d'avoir des colonnes multivalues Ils correspondent en Java la classe java.sql.Array

Rcuprer un Array
Un Array enregistr dans une base de donnes peut tre rcupr en Java sous la forme dune instance de la classe Array par les mthodes suivantes de ResultSet n getArray(String colonne nom) n getArray(int n) On rcupre ainsi une rfrence qui peut servir obtenir les valeurs de larray

R. Grin

JDBC et relationnel-objet

page 3

R. Grin

JDBC et relationnel-objet

page 4

Rcuprer les lments dun Array


On peut ensuite rcuprer dans un tableau Java des lments d'un Array sans charger tout le tableau en mmoire par les mthodes de linterface Array
Object getArray(long debut, int longueur) ou en utilisant un ResultSet par ResultSet getResultSet()

Enregistrer un Array
void setArray(int i, Array x) de PreparedStatement permet denregistrer un Array On peut enregistrer un tableau Java sous forme de Array avec la mthode setObject

On peut aussi rcuprer un tableau Java entier par la mthode Object getArray() de Array
R. Grin JDBC et relationnel-objet page 5 R. Grin JDBC et relationnel-objet page 6

Enregistrer un tableau
String[] data; // remplit le tableau . . . PreparedStatement ps = conn.prepareStatement( "Update table1 " + "set tableau = ? where num = 5"); ps.setObject(1, data);

Lire des lments d'un Array


String[] data; Statement stmt = conn.createStatement(); ResultSet rset = stmt.executeQuery( "select * from table1 where num = 5"); if (rset.next()) { Array tab = rset.getArray("tableau"); // ne rcupre que les lments 5 et 6 du tableau data = (String[])tab.getArray(4, 2); for (int i = 0; i < data.length; i++) { System.out.println(data[i]); } }
page 7 R. Grin JDBC et relationnel-objet page 8

R. Grin

JDBC et relationnel-objet

Lire des lments d'un Array


On peut aussi utiliser un ResultSet pour lire les lments d'un tableau dj rcupr :
String[] data; Statement stmt = conn.createStatement(); ResultSet rset = stmt.executeQuery("select . . ."); if (rset.next()) { Array tab = rset.getArray("tableau"); // ne rcupre que les lments 5 et 6 du tableau ResultSet data = tab.getResultSet(4, 2); while (data.next()) { System.out.println(data.getString(2)); } }
R. Grin JDBC et relationnel-objet page 9

Type utilisateur
SQL 3 a introduit 2 formes de nouveaux types crs par l'utilisateur : n type distinct , construit simplement partir d'un type de base n type structur , plus complexe, construit sur le modle d'une classe Java

R. Grin

JDBC et relationnel-objet

page 10

Type distinct
Ces types permettent de mieux diffrencier les domaines des colonnes, qu'avec les types de base :
create type codePays as char(2); create type matricule as integer;

Type structur
Ces types rapprochent les SGBD relationnels du monde objet Ils sont crs par la commande SQL 3 create type :
create type departement_type ( numDept integer, nomDept varchar(15), lieu varchar(20))

On peut ainsi, par exemple, diffrencier le domaine des colonnes matricule et numDept On utilise ces types exactement avec les mmes instructions que le type de base

R. Grin

JDBC et relationnel-objet

page 11

R. Grin

JDBC et relationnel-objet

page 12

Utilisation des types distinct et structur dans la dfinition d'une table


create table emp ( matr matricule constraint pkEmp primary key, nomE varchar(15), . . . dept departement_type)

Utilisation des types structurs pour la persistance des classes Java


Pour faciliter la persistance des classes Java 1. Crer un type structur SQL de mme structure que la classe 2. La classe Java doit implmenter l'interface java.sql.SQLData 3. Indiquer le type structur qui correspond la classe Java

R. Grin

JDBC et relationnel-objet

page 13

R. Grin

JDBC et relationnel-objet

page 14

Utilisation des types structurs pour la persistance des classes Java


La lecture et lcriture dans une base de donnes des donnes dune instance de la classe Java seffectue alors en un seul appel de mthode getObject ou setObject

Interface SQLData
public interface SQLData { void readSQL(SQLInput stream, String typeName) throws SQLException ; void writeSQL(SQLOutput stream) throws SQL Exception; String getSQLTypeName() throws SQLException; }

R. Grin

JDBC et relationnel-objet

page 15

R. Grin

JDBC et relationnel-objet

page 16

Implmenter linterface SQLData


public class Dept implements SQLData { private int numDept; private String nomDept, lieu; private String nomTypeSQL; // Constructeurs et autres mthodes de Dept
. . .

Interface SQLData (suite)


// Les 3 mthodes de l'interface SQLData public void readSQL(SQLInput flot, String type) throws SQLException { nomTypeSQL = type; numDept = flot.readInt(); nomDept = flot.readString(); L'ordre de lecture lieu = flot.readString(); (et d'criture) } doit tre celui donn dans la dfinition du type structur
R. Grin JDBC et relationnel-objet page 18

R. Grin

JDBC et relationnel-objet

page 17

Interface SQLData (suite)


public void writeSQL(SQLOutput flot) throws SQLException { flot.writeInt(numDept); flot.writeString(nomDept); flot.writeString(lieu); } public String getSQLTypeName() { return nomTypeSQL ; } }
R. Grin JDBC et relationnel-objet page 19

Correspondance entre les classes Java et les types structurs


Pour faciliter l'enregistrement dans la base des donnes d'un type structur, il faut indiquer le nom (complet, avec le paquetage) de la classe Java qui correspond ce type On utilise pour cela une Map utilise en interne par la connexion :
Map map = conn.getTypeMap(); map.put("schema1.departement", Dept.class);

R. Grin

JDBC et relationnel-objet

page 20

Lecture d'un type structur


Il est alors simple de lire et d'crire des valeurs du type structur :
Statement stmt = conn.createStatement(); ResultSet rset = stmt.executeQuery( "SELECT * FROM EMP"); while (rset.next()) { Dept dept = (Dept)rset.getObject("DEPT"); System.out.println("Lieu du dept : " + dept.getLieu()); }

criture d'un type structur


Dept dept = new Dept(); . . . PreparedStatement ps = conn.createStatement( "INSERT INTO EMP" + "(matricule, , dept)" + " VALUES (?, , ?)"); ps.setInt(1, matricule); . . . ps.setObject(8, dept);

R. Grin

JDBC et relationnel-objet

page 21

R. Grin

JDBC et relationnel-objet

page 22

Sans utilisation de la Map


On peut aussi lire une valeur d'un type structur sans utiliser la Map qui fait la correspondance entre les classes Java et les types structurs Dans ce cas, on doit lire colonne par colonne en utilisant linterface java.sql.Struct

Lecture sans utiliser la Map


Statement stmt = conn.createStatement(); ResultSet rset = stmt.executeQuery("SELECT * FROM emp"); while (rset.next()) { Struct struct = (Struct)rset.getObject("DEPT"); Object[] valeurs = struct.getAttributes(); System.out.println("Lieu du dept : " + valeurs[2]); } 3me champ
R. Grin JDBC et relationnel-objet page 24

R. Grin

JDBC et relationnel-objet

page 23

Rfrences en SQL 3
Le processus de normalisation conduit clater les donnes en plusieurs tables Lorsque lon veut retrouver des informations, on doit alors souvent effectuer des jointures, par exemple pour savoir dans quelle ville les employs travaillent En SQL3 on peut le faire sans que cela ne ncessite de jointure En effet, SQL3 permet de manipuler les rfrences une information
R. Grin JDBC et relationnel-objet page 25

Nouveau type de table SQL 3


Si on veut pouvoir rfrencer les lignes d'une table T dans une autre table, il faut crer cette table T partir d'un type structur Par exemple, partir du type structur dept_type, on peut crer la table dept :
create table dept of departement_type ( constraint pk_dept primary key dept)

R. Grin

JDBC et relationnel-objet

page 26

Insertion dans les nouvelles tables


insert into dept (numDept, nomDept, lieu) values (10, 'COMPTABILITE', 'NICE');

Utilisation des rfrences dans la dfinition d'une table


create table emp ( matr matricule constraint pkEmp primary key, nomE varchar(15), . . . dept ref departement_type )

R. Grin

JDBC et relationnel-objet

page 27

R. Grin

JDBC et relationnel-objet

page 28

Rcupration d'une rfrence


On peut rcuprer une rfrence grce la mthode getRef Ensuite il est possible dutiliser la rfrence pour interroger la table vers laquelle pointe la rfrence en utilisant setRef

Rcupration de rfrences en JDBC


java.sql.Ref refDept; Statement stmt = conn.createStatement(); ResultSet rset1 = stmt.executeQuery( "SELECT dept from emp " + "where matricule = 105"); if (rset1.next()) { refDept = rset1.getRef("dept");
// Dans le transparent suivant, on rcupre // le lieu du dpartement partir de refDept

R. Grin

JDBC et relationnel-objet

page 29

R. Grin

JDBC et relationnel-objet

page 30

Rcupration de rfrences en JDBC


PreparedStatement ps = conn.prepareStatement( "SELECT lieu FROM dept" + " WHERE REF(dept) = ?"); ps.setRef(1, refDept); ResultSet rset2 = ps.executeQuery(); if (rset2.next()) { System.out.println(rset1.getString("nomE") + "travaille " + rset2.getString(1));
} // if (rset2 } // if (rset1
R. Grin JDBC et relationnel-objet page 31

Problmes avec JDBC


JDBC ne contrle pas les ordres SQL passs au SGBD Une faute de frappe dans le nom dune table ou une faute de syntaxe dans un ordre SQL ne seront donc repres qu lexcution

APIs au-dessus de JDBC


Universit de Nice - Sophia Antipolis Richard Grin
Version 0.2 14/10/05

R. Grin

JDBC

page 2

Problmes avec JDBC


La correspondance entre les classes Java et les tables relationnelles est un travail de bas niveau Le programmeur doit faire attention des dtails et crire de nombreuses lignes pour travailler avec les donnes de la base Pourtant une grande partie de ce travail rptitif peut tre automatis

Autres API
Dautres API ont t construites au-dessus de JDBC pour corriger les problmes de JDBC : n SQLJ n JDO n outils de mapping n et bien dautres

R. Grin

JDBC

page 3

R. Grin

JDBC

page 4

SQLJ
SQLJ est un standard promu par un consortium dditeurs de SGBD (Oracle, IBM et Sun en particulier) compos de 3 parties La partie 0 de SQLJ fait partie de SQL3 Cette partie dfinit des extensions de SQL pour permettre dinsrer directement des ordres SQL au milieu dun programme Java Par exemple, une variable Java peut recevoir une valeur retourne par une requte SQL
page 5 R. Grin JDBC page 6

SQLJ

R. Grin

JDBC

Exemple de code avec SQLJ


import sqlj.runtime.ref.*; import java.sql.*; . . . String nom; int matricule = 1500; #sql { select NOME into :nom from EMP where MATRICULE = :matricule}; System.out.println("Nom : " + nom);

Prcompilateur SQLJ
Un prcompilateur transforme les ordres SQL en instructions Java contenant des appels de mthodes JDBC Le rsultat est un programme source Java que lon peut compiler avec un compilateur Java ordinaire Ce prcompilateur contrle la validit des ordres SQL ; il en faut donc un par SGBD cible

R. Grin

JDBC

page 7

R. Grin

JDBC

page 8

Principe de SQLJ
Fichier de ressources Fichier source .java

Avantages de SQLJ sur JDBC


Code SQL bien spar du code Java Moins de lignes de code Code plus lisible Plus de portabilit Code plus orient objet Syntaxe des instructions SQL et cohrence avec la structure de la base vrifies pendant la prcompilation, et pas lexcution (par exemple, existence et type des colonnes)
R. Grin JDBC page 10

Fichier source Prcompilateur .sqlj SQLJ

Compilateur Java

Fichier .class

Ce procd est dj utilis pour de nombreux langages (C, Cobol, Ada,) pour insrer des instructions SQL

R. Grin

JDBC

page 9

Avantages de JDBC sur SQLJ


JDBC permet de crer dynamiquement un ordre SQL (en manipulant des chanes de caractres) Avec SQLJ, on doit connatre l'ordre SQL au moment o on crit le code Compilation plus lourde en SQLJ (mais la tche est facilite par des utilitaires de type make ou Ant)

JDO

R. Grin

JDBC

page 11

R. Grin

JDBC

page 12

JDO
JDO est un projet plus ambitieux que SQLJ puisquil souhaite rendre en grande partie transparente la persistance des objets Java Le code Java crit par les dveloppeurs ne soccupe pas de la persistance JDO ncessite une infrastructure complexe, la compilation, et durant lexcution, fournie par une implmentation JDO

Transparence de la persistance
Les classes qui pourront avoir des instances persistantes sont dites capables de persistantes Le principe de base de JDO est que le programmeur ncrit aucun code pour grer la persistance Le code source dune classe est exactement le mme, que la classe soit capable de persistance ou non
R. Grin JDBC page 14

R. Grin

JDBC

page 13

Rendre une instance persistante


Pour rendre une instance persistante, il suffit dutiliser la mthode makePersistent (voir code
plus loin)

Portabilit
La persistance peut seffectuer sur un support logique quelconque : SGBD relationnel ou objet, ou mme fichiers ordinaires Il suffit davoir une implmentation JDO (qui joue le rle dun driver JDBC) adapte ce support La persistance ne tient compte que de la description logique des classes persistantes (mta-donnes), fournie par un fichier XML crit par le dveloppeur Il est ainsi trs facile de changer de support
R. Grin JDBC page 16

En fait la plupart des instances sont rendues persistantes automatiquement, par rfrence (by reachability) : si on rend persistant une instance de Employe, dont la classe possde un champ capable de persistance de type Adresse, son adresse devient automatiquement persistante
R. Grin JDBC page 15

Enrichissement JDO
Les classes capables de persistance sont indiques dans un fichier XML de configuration Elles doivent tre enrichies par un programme spcial, fourni par l'implmentation de JDO et adapt un SGBD cible Cet enrichissement ajoute les mthodes qui permettront limplmentation JDO de grer la persistance des instances pendant lexcution

Exemple de code avec JDO


Ce code va ajouter une adresse dans une base de donne La classe Adresse nest pas donne car elle est semblable une classe Java normale Le schma de la base doit comporter une table dont la structure correspond aux champs persistants de la classe Adresse

R. Grin

JDBC

page 17

R. Grin

JDBC

page 18

Outils JDO
Les implmentations JDO fournissent des outils (pas obligatoires) pour n crer automatiquement des schmas de base de donnes compatibles avec les classes persistantes, n ou inversement, pour crer des classes compatibles avec des tables existantes

Fichier des mta-donnes


<?xml version="1.0"?> <!DOCTYPE jdo SYSTEM "jdo.dtd"> <jdo> <package name="fr.truc.projet1"> <class name="Adresse"> <field name="rue"/> <field name="ville"/> <field name="codePostal"/> </class> </package> </jdo>
R. Grin JDBC page 20

R. Grin

JDBC

page 19

Rcuprer un gestionnaire de persistance


// Cre fabrique de gestionnaire de persistance PersistenceManagerFactory pmf = JDOHelper.getPersistenceManagerFactory( jdoProperties); pmf.setConnectionURL(DBURL); pmf.setConnectionDriverName(DBDRIVER); // Retrouve le gestionnaire de persistance PersistenceManager pm = pmf.getPersistenceManager();

Exemple (suite)
// Dmarrer une transaction Transaction t = pm.currentTransaction(); t.begin(); // Cre une nouvelle Adresse Adresse adresse = new Adresse("58 rue Victor Hugo", "Nice", "06100"); //... et la rend persistante pm.makePersistent(adresse); // adresse automatiquement enregistre dans la // base au commit ! t.commit(); // Fermeture du gestionnaire de persistance pm.close();
R. Grin JDBC page 22

R. Grin

JDBC

page 21

Outils de mapping
Ils automatisent la correspondance entre les donnes correspondant ltat des objets et les donnes enregistres dans les BDR Trs la mode en ce moment (hibernate en particulier) Ils sont tudis dans une autre partie du cours (mapping objet-relationnel)

R. Grin

JDBC

page 23

Plan de cette partie

(Java Persistence API)


Universit de Nice - Sophia Antipolis
Version 0.9.8 17/11/06 Richard Grin

JPA

Prsentation de JPA Entits persistantes Gestionnaire de persistance Complments sur les entits : identit, associations, hritage Langage dinterrogation Modifications en volume Exceptions Configuration
R. Grin JPA page 2

Plan de cette partie


Transaction Concurrence Entits dtaches Optimisation Callbacks Fichiers de configuration XML JPA dans les serveurs dapplications

Prsentation de JPA

R. Grin

JPA

page 3

R. Grin

JPA

page 4

EJB 3.0
Java EE 5 (Enterprise Edition) est une plateforme de dveloppement et un ensemble de spcifications pour le dveloppement dapplications dentreprises multi-tiers EJB 3.0 fait partie de Java EE 5 ; cest une spcification rcente (mai 2006) dun cadre (framework) pour lutilisation de composants mtier rutilisables par des serveurs dapplication Java Utilisation importante des annotations
R. Grin JPA page 5

JPA
JPA (Java persistence API) est la partie de la spcification EJB 3.0 qui concerne la persistance des composants Neffectue la persistance que dans une base de donnes relationnelle (JDO permet le choix dautres types de SGBD) Peut sappliquer sur toutes les applications Java, mme celles qui sexcutent en dehors dun serveur dapplication

R. Grin

JPA

page 6

JPA
JPA va sans doute devenir un standard pour la persistance des objets Java Pour plus de prcisions, lire la spcification ladresse http://jcp.org/aboutJava/communityprocess/pfd/js r220/index.html

Avertissement
JPA est le plus souvent utilis dans le contexte dun serveur dapplication Ce cours tudie lutilisation de JPA par une application autonome, en dehors de tout serveur dapplication Des informations sur lutilisation de JPA avec un serveur dapplications sont donnes la fin de ce support

R. Grin

JPA

page 7

R. Grin

JPA

page 8

Fournisseur de persistance
Comme pour JDBC, lutilisation de JPA ncessite un fournisseur de persistance qui implmente les classes et mthodes de lAPI GlassFish, est limplmentation de rfrence de la spcification EJB 3 GlassFish utilise TopLink essentials comme fournisseur de persistance pour JPA Dautres implmentations : TopLink, Hibernate Entity Manager, BEA Kodo
R. Grin JPA page 9

Entits
Les classes dont les instances peuvent tre persistantes sont appeles des entits dans la spcification de JPA Le dveloppeur indique quune classe est une entit en lui associant lannotation @Entity Ne pas oublier dimporter javax.Persistence.Entity dans les classes entits (idem pour toutes les annotations)
R. Grin JPA page 10

Vocabulaire
Dans la suite de ce cours et quand il ny aura pas ambigut, entit dsignera soit une classe entit, soit une instance de classe entit, suivant le contexte

Exemple dentit les champs


@Entity public class Departement { private int id; private String nom; private String lieu; private Collection<Employe> employes = new List<Employe>();

R. Grin

JPA

page 11

R. Grin

JPA

page 12

Exemple dentit lidentificateur


@Id @GeneratedValue public int getId() { return id; } public void setId(int id) { this.id = id; }

Exemple dentit une proprit


public String getNom() { return nom; } public void setNom(String nom) { this.nom = nom; }

R. Grin

JPA

page 13

R. Grin

JPA

page 14

Exemple dentit une association


Lassociation inverse dans la classe Employe @OneToMany(mappedBy="dept") public Collection<Employe> getEmployes() { return employes; } public void setEmployes(Collection<Employe> emps) { this.employes = emps; } }

Fichiers de configuration XML


Les annotations @Entity (et toutes les autres annotations JPA) peuvent tre remplaces ou/et surcharges (les fichiers XML lemportent sur les annotations) par des informations enregistres dans un fichier de configuration XML Exemple :
<table-generator name="empgen" table="ID_GEN" pk-column-value="EmpId"/>

La suite nutilisera que les annotations

R. Grin

JPA

page 15

R. Grin

JPA

page 16

Gestionnaire dentits
Classe javax.persistence.EntityManager Le gestionnaire dentits (GE) est linterlocuteur principal pour le dveloppeur Il fournit les mthodes pour grer les entits : les rendre persistantes, les supprimer de la base de donnes, retrouver leurs valeurs dans la base, etc.

Contexte de persistance
La mthode persist(objet) de la classe EntityManager rend persistant un objet Lobjet est alors gr par le GE : toute modification apporte lobjet sera enregistre dans la base de donnes par le GE Lensemble des entits gres par un GE sappelle un contexte de persistance

R. Grin

JPA

page 17

R. Grin

JPA

page 18

Exemple
EntityManagerFactory emf = Persistence. createEntityManagerFactory("employes"); EntityManager em = emf.createEntityManager(); EntityTransaction tx = em.getTransaction(); tx.begin(); Dept dept = new Dept("Direction", "Nice"); em.persist(dept); sera enregistr dans dept.setLieu("Paris"); la base de donnes tx.commit(); au moment du commit R. Grin JPA page 19

Exemple (suite)
String queryString = "SELECT e FROM Employe e " + " WHERE e.poste = :poste"; Query query = em.createQuery(queryString); query.setParameter("poste", "INGENIEUR"); List<Employe> liste = query.getResultList(); for (Employe e : liste) { System.out.println(e.getNom()); } em.close(); emf.close()
R. Grin JPA page 20

Caractristiques
Seules les entits peuvent tre n renvoyes par une requte (Query) n passes en paramtre dune mthode dun EntityManager ou dun Query n le but dune association n rfrences dans une requte JPQL Une classe entit peut utiliser dautres classes pour conserver des tats persistants (MappedSuperclass ou Embedded tudies plus loin)
page 21 R. Grin JPA page 22

Entits

R. Grin

JPA

Conditions pour les classes entits


Une classe entit doit avoir un constructeur sans paramtre protected ou public Elle ne doit pas tre final Aucune mthode ou champ persistant ne doit tre final Si une instance peut tre passe par valeur en paramtre dune mthode comme un objet dtach, elle doit implmenter Serializable Elle doit possder un attribut qui reprsente la cl primaire dans la BD
R. Grin JPA page 23

Conditions pour les classes entits


Une classe entit ne doit pas tre une classe interne Une entit peut tre une classe abstraite mais elle ne peut tre une interface

R. Grin

JPA

page 24

Convention de nommage JavaBean


Un JavaBean possde des proprits Une proprit est reprsente par 2 accesseurs ( getter et setter ) qui doivent suivre la convention de nommage suivante : si prop est le nom de la proprit, le getter doit tre getProp (ou isProp si la proprit est de type boolean) et le setter setProp Souvent une proprit correspond une variable dinstance
R. Grin JPA page 25

2 types daccs
Le fournisseur de persistance accdera la valeur dune variable dinstance n soit en accdant directement la variable dinstance (par introspection) n soit en passant par ses accesseurs (getter ou setter) Le type daccs est dtermin par lemplacement des annotations (associes aux variables dinstance ou aux getter)
R. Grin JPA page 26

Accs par proprit


Les accesseurs (setter et getter) doivent tre protected ou public Ils peuvent contenir dautres instructions que le seul code li la valeur de la variable sous-jacente Ces instructions seront excutes par le fournisseur de persistance Si une exception est leve par les accesseurs, la transaction est invalide ; les exceptions contrles sont enveloppes par une PersistenceException (non contrle, sous RuntimeException)
R. Grin JPA page 27

Vocabulaire JPA
Un champ dsigne une variable dinstance JPA parle de proprit lorsque laccs se fait en passant par les accesseurs (getter ou setter) Lorsque le type daccs est indiffrent, JPA parle dattribut

R. Grin

JPA

page 28

Choix du type daccs


Le choix doit tre le mme pour toutes les classes dune hirarchie dhritage (interdit de mlanger les 2 faons) En programmation objet il est conseill dutiliser plutt les accesseurs que les accs directs aux champs (meilleur contrle des valeurs) ; cest aussi le cas avec JPA

Attributs persistants
Par dfaut, tous les attributs dune entit sont persistants Lannotation @Basic indique quun attribut est persistant mais elle nest donc indispensable que si on veut prciser des informations sur cette persistance (par exemple, une rcupration retarde) Seuls les attributs dont la variable est transient ou qui sont annots par @Transient ne sont pas persistants
R. Grin JPA page 30

R. Grin

JPA

page 29

Cycle de vie dune instance dentit


Linstance peut tre n nouvelle (new) : elle est cre mais pas associe un contexte de persistance n gre par un gestionnaire de persistance ; elle a une identit dans la base de donnes (un objet peut devenir gr par la mthode persist, ou merge dune entit dtache, ou si cest une instance rcupre dans la base par une requte)
R. Grin JPA page 31

Cycle de vie dune instance dentit


dtache : elle a une identit dans la base mais elle nest plus associe un contexte de persistance (une entit peut devenir dtache la fin dune transaction ou par un passage par valeur en paramtre dune mthode distante) n supprime : elle a une identit dans la base ; elle est associe un contexte de persistance et ce contexte doit la supprimer de la base de donnes (passe dans cet tat par la mthode remove)
n
R. Grin JPA page 32

Cycle de vie dune entit

Les tables de la base de donnes


Dans les cas simples, une table correspond une classe n le nom de la table est le nom de la classe n les noms des colonnes correspondent aux noms des attributs persistants Par exemple, les donnes de la classe Departement sont enregistres dans la table Departement (ou DEPARTEMENT) dont les colonnes se nomment id, nom, lieu
page 33 R. Grin JPA page 34

Jai oubli o jai pris cette image merci de me donner la rfrence si vous le savez
R. Grin JPA

Configuration par exception


La configuration des classes entits suppose des valeurs par dfaut Il nest ncessaire dajouter des informations de configuration que si ces valeurs par dfauts ne conviennent pas Par exemple, @Entity suppose que la table qui contient les donnes des instances de la classe a le mme nom que la classe

Nom de table
Pour donner la table un autre nom que le non de la classe, il faut ajouter une annotation @Table Exemple :
@Entity @Table(name="AUTRENOM") public class Classe { ... }

R. Grin

JPA

page 35

R. Grin

JPA

page 36

Nom de colonne
Pour donner une colonne de la table un autre nom que le nom de lattribut correspondant, il faut ajouter une annotation @Column Cette annotation peut aussi comporter des attributs pour dfinir plus prcisment la colonne Exemple :
@Column(name="AUTRENOM", updatable=false, length=80) public String getTruc() { ... }
R. Grin JPA page 37

Classe Embeddable
Les entits persistantes ne sont pas les seules classes persistantes Il existe aussi des classes insres ou incorpores (embedded) dont les donnes nont pas didentit dans la BD mais sont insres dans une des tables associes une entit persistante Elles peuvent tre annotes comme les entits (avec @Column par exemple) Par exemple, une classe Adresse dont les valeurs sont insres dans la table Employe
R. Grin JPA page 38

Classe Embeddable
Comme les entits, ces classes doivent avoir un constructeur sans paramtre Les types permis pour leurs attributs sont les mmes que les types permis pour les attributs des entits

Exemple
@Embeddable public class Adresse { private int numero; private String rue; private String ville; . . . } @Entity public class Employe { @Embedded private Adresse adresse; ...
R. Grin JPA page 40

R. Grin

JPA

page 39

Restrictions
La version actuelle de JPA a plusieurs restrictions (peut-tre enleves dans une prochaine version) : n une entit ne peut possder une collection dobjets insrs n un objet insr ne peut rfrencer un autre objet insr ni avoir une association avec une entit Un objet insr ne peut tre rfrenc par plusieurs entits diffrentes
R. Grin JPA page 41

Classes insres partages


Si une classe insre est utilise par 2 classes entits, il est possible que les noms des colonnes soient diffrentes dans les tables associes aux 2 entits En ce cas, un champ annot par @Embedded peut tre complt par une annotation @AttributeOverride, ou plusieurs de ces annotations insres dans une annotation @AttributeOverrides

R. Grin

JPA

page 42

Exemple
@Entity public class Employe { @Embedded @AttributeOverrides({ @AttributeOverride( name="numero", column=@column(name="num")), @AttributeOverride(...) }) private Adresse adresse; ...
R. Grin JPA page 43

Annotation pour LOB


Lannotation @Lob permet dindiquer quun attribut est un LOB (Large OBject) : soit un CLOB (Character LOB, tel un long rsum de livre), soit un BLOB (Binary LOB, tel une image ou une squence vido) Le fournisseur de persistance pourra ainsi ventuellement traiter lattribut de faon spciale (utilisation de flots dentres-sorties par exemple) Exemple : @Lob private byte[] image
R. Grin JPA page 44

Annotation pour numration


Une annotation spciale nest pas ncessaire si un attribut est de type numration si lnumration est sauvegarde dans la BD sous la forme des numros des constantes de lnumration (de 0 n) Si on souhaite sauvegarder les constantes sous la forme de la forme dune String qui reprsente le nom de la valeur de lnumration, il faut utiliser lannotation @Enumerated
R. Grin JPA page 45

Exemple
@Enumerated(EnumType.STRING) private TypeEmploye typeEmploye;

R. Grin

JPA

page 46

Types temporels
Lorsqu'une classe entit a un attribut de type temporel (Calendar ou Date de java.util), il est obligatoire d'indiquer de quel type temporel est cet attribut par une annotation @Temporal Cette indication permettra au fournisseur de persistance de savoir comment dclarer la colonne correspondante dans la base de donnes : une date (un jour), un temps sur 24 heures (heures, minutes, secondes la milliseconde prs) ou un timeStamp (date + heure la microseconde prs)
R. Grin JPA page 47

Annotation pour les types temporels


3 types temporels dans lnumration TemporalType : DATE, TIME, TIMESTAMP Correspondent aux 3 types de SQL ou du paquetage java.sql : Date, Time et Timestamp

R. Grin

JPA

page 48

Exemple
@Temporal(TemporalType.DATE) private Calendar dateEmb;

Tables multiples
Il est possible de sauvegarder une entit sur plusieurs tables Voir @SecondaryTable dans la spcification JPA

R. Grin

JPA

page 49

R. Grin

JPA

page 50

Schma relationnel
Dans le cas o le schma relationnel est construit automatiquement partir des annotations, il est possible de prciser des informations sur les tables gnres ou les colonnes de ces tables Par exemple, une contrainte d'unicit, ou "not null", la longueur des colonnes de type varchar, la prcision des nombres virgule, ou mme le texte entier qui permet de dfinir une colonne Voir la spcification JPA pour plus de dtails
R. Grin JPA page 51

Exemple
@Entity @Table(name="PARTICIPATION2", uniqueConstraints = @UniqueConstraint( columnNames = {"EMPLOYE_ID", "PROJET_ID"}) ) public class Participation { ... }
R. Grin JPA page 52

Principe de base
La persistance des entits nest pas transparente Une instance dentit ne devient persistante que lorsque lapplication appelle la mthode approprie du gestionnaire dentit (persist ou merge) Cette conception a t voulue par les concepteurs de lAPI par souci de flexibilit et pour permettre un contrle fin de lapplication sur la persistance des entits
page 53 R. Grin JPA page 54

Gestionnaire dentits (Entity Manager), GE

R. Grin

JPA

Unit de persistance
Cest une configuration nomme qui contient les informations ncessaires lutilisation dune base de donnes Elle est associe un ensemble de classes entits

Configuration dune unit de persistance


Dans un environnent non gr par un serveur dapplications, les informations sur une unit de persistance sont donnes dans un fichier persistence.xml situ dans un sousrpertoire META-INF dun des rpertoires du classpath Voir section Configuration de lunit de persistance dans la suite du cours

R. Grin

JPA

page 55

R. Grin

JPA

page 56

Contexte de persistance
Un contexte de persistance est un ensemble dentits qui vrifie la proprit suivante : il ne peut exister 2 entits diffrentes qui reprsentent des donnes identiques dans la base Un contexte de persistance est gr par un gestionnaire dentits qui veille ce que cette proprit soit respecte Un contexte de persistance ne peut appartenir qu une seule unit de persistance Une unit de persistance peut contenir plusieurs contextes de persistance
R. Grin JPA page 57

Contexte de persistance
Cest la responsabilit de lapplication de sassurer quune entit nappartient qu un seul contexte de persistance Sinon, 2 entits de 2 contextes de persistance diffrents pourraient correspondre des donnes identiques dans la base de donnes

R. Grin

JPA

page 58

Contexte de persistance
Quand une entit est incluse dans un contexte de persistance (persist ou merge), ltat de lentit est automatiquement sauvegard dans la base au moment de la validation (commit) de la transaction

Interface EntityManager
Elle reprsente un GE Implmentation fournie par le fournisseur de persistance

R. Grin

JPA

page 59

R. Grin

JPA

page 60

10

Types de GE
GE gr par le container (uniquement disponible dans un serveur dapplications) n dlimit par les transactions (TRANSACTION) n peut survivre une fin de transaction (EXTENDED) ; ncessite un bean session avec tat (stateful) GE gr par lapplication (seul type disponible en dehors dun serveur dapplications) ; pas dlimit par les transactions
R. Grin JPA page 61

Ce cours prsente lutilisation de JPA en dehors du container dun serveur dapplication Voir la dernire section de ce cours pour des informations sur JPA dans une serveur dapplication

R. Grin

JPA

page 62

GE non gr par le conteneur


En dehors dun serveur dapplication, cest lapplication qui dcide de la dure de vie dun GE La mthode createEntityManager() de la classe EntityManagerFactory cr un GE Le GE est supprim avec la mthode close() de la classe EntityManager

Fabrique de GE
La classe Persistence permet dobtenir une fabrique de gestionnaire dentits par la mthode createEntityManagerFactory 2 variantes surcharges de cette mthode : n 1 seul paramtre qui donne le nom de lunit de persistance (dfinie dans le fichier persistence.xml) n Un 2me paramtre de type Map qui contient des valeurs qui vont craser les proprits par dfaut contenues dans persistence.xml
R. Grin JPA page 64

R. Grin

JPA

page 63

Mthodes de EntityManager
void persist(Object entit) <T> T merge(T entit) void remove(Object entit) <T> T find(Class<T> classeEntit, Object clPrimaire) <T> T getReference(Class<T> classeEntit, Object clPrimaire) void flush() void setFlushMode(FlushModeType flushMode)
R. Grin JPA page 65

Mthodes de EntityManager
void lock(Object entit, LockModeType lockMode) void refresh(Object entit) void clear() boolean contains(Object entit) Query createQuery(String requte) Query createNamedQuery(String nom)

R. Grin

JPA

page 66

11

Mthodes de EntityManager
Query createNativeQuery(String requte) Query createNativeQuery(String requte, Class classeRsultat) void joinTransaction() void close() boolean isOpen() EntityTransaction getTransaction()

flush
Toutes les modifications effectues sur les entits du contexte de persistance gres par le GE sont enregistres dans la BD lors dun flush du GE Au moment du flush, le GE tudie ce quil doit faire pour chacune des entits quil gre et il lance les commandes SQL adaptes pour modifier la base de donnes (INSERT, UPDATE ou DELETE)
R. Grin JPA page 68

R. Grin

JPA

page 67

flush
Un flush est automatiquement effectu au moins chaque commit de la transaction en cours Une exception TransactionRequiredException est leve si la mthode flush est lance en dehors dune transaction

flush
Soit X une des entits gre, avec une association de X vers une entit Y Si cette association est note avec cascade=persist ou cascade=all, Y est elle aussi flushe Sinon, si Y est new ou removed, une exception IllegalStateException sera leve et la transaction est invalide (rollback) Sinon, si Y est dtache et X possde lassociation, Y est flushe ; si Y est la propritaire, le comportement est indfini
R. Grin JPA page 70

R. Grin

JPA

page 69

Mode de flush
Normalement (mode FlushMode.AUTO) un flush des entits concernes par une requte est effectu avant la requte pour que le rsultat tienne compte des modifications effectues en mmoire sur ces entits Il est possible d'viter ce flush avec la mthode setFlushMode : em.setFlushMode(FlushMode.COMMIT); En ce cas, un flush ne sera lanc qu'avant un commit Il est possible de modifier ce mode pour une seule requte (voir Query)
R. Grin JPA page 71

persist
Une entit nouvelle devient une entit gre Ltat de lentit sera sauvegard dans la BD au prochain flush ou commit Aucune instruction ne sera ncessaire pour faire enregistrer au moment du commit dans la base de donnes les modifications effectues sur lentit par lapplication ; en effet le GE conserve toutes les informations ncessaires sur les entits quil gre
R. Grin JPA page 72

12

persist(A)
Si A est nouvelle, elle devient gre Si A tait dj gre, persist est ignore mais lopration persist cascade sur les entits associes si lassociation a lattribut CascadeType.PERSIST Si A est supprime, elle devient gre Si A est dtache, une IllegalArgumentException est lance Ne peut tre utilis que dans le contexte dune transaction
R. Grin JPA page 73 R. Grin

remove
Une entit gre devient supprime Les donnes correspondantes seront supprimes de la BD

JPA

page 74

remove(A)
Ignore si A est nouvelle ou supprime Si A est nouvelle, lopration cascade sur les associations qui ont lattribut CascadeType.REMOVE Si A est gre, elle devient supprime Si A est dtache, une IllegalArgumentException est lance Ne peut tre utilis que dans le contexte dune transaction
R. Grin JPA page 75

refresh
Le GE peut synchroniser avec la BD une entit quil gre en rafraichissant son tat en mmoire avec les donnes actuellement dans la BD : em.refresh(entite); Les donnes de la BD sont copies dans lentit Utiliser cette mthode pour sassurer que lentit a les mmes donnes que la BD Peut tre utile pour les transactions longues
R. Grin JPA page 76

refresh(A)
Ignore si A est nouvelle ou supprime Si A est nouvelle, lopration cascade sur les associations qui ont lattribut CascadeType.REFRESH Si A est dtache, une IllegalArgumentException est lance

find
La recherche est polymorphe : l'entit rcupre peut tre de la classe passe en paramtre ou d'une sous-classe Exemple : Article p = em.find(Article.class, 128); peut renvoyer un article de n'importe quelle sous-classe de Article (Stylo, Ramette,)

R. Grin

JPA

page 77

R. Grin

JPA

page 78

13

lock(A)
Le fournisseur de persistance gre les accs concurrents aux donnes de la BD reprsentes par les entits avec une stratgie optimiste lock ermet de modifier la manire de grer les accs concurrents une entit A Sera tudi plus loin dans la section sur la concurrence

En dehors dune transaction


Les mthodes suivantes (read only) peuvent tre lances en dehors dune transaction : find, getReference, refresh et requtes (query) Les mthodes persist, remove, merge peuvent tre excutes en dehors dune transaction mais elles seront enregistres pour un flush ds quune transaction est active Les mthodes flush, lock et modifications de masse (executeUpdate) ne peuvent tre lances en dehors dune transaction
R. Grin JPA page 80

R. Grin

JPA

page 79

Entit dtache (1)


Une application distribue sur plusieurs ordinateurs peut utiliser avec profit des entits dtaches Une entit gre par un GE peut tre dtache de son contexte de persistance Elle peut ainsi tre transfre en dehors de la porte du GE

Entit dtache (2)


Une entit dtache peut tre modifie Pour que ces modifications soient enregistres dans la BD, il est ncessaire de rattacher lentit un GE par la mthode merge

R. Grin

JPA

page 81

R. Grin

JPA

page 82

merge(A)
Si A est une entit dtache, son tat est copi dans une entit gre A qui a la mme identit que A (si A nexiste pas dj, il est cr) ; merge renvoie A Si A est nouvelle, une nouvelle entit gre A' est cr et ltat de A est copi dans A Si A est dj gre, merge est ignore mais merge cascade pour tous les associations avec lattribut CascadeType.MERGE Si A est supprime, une IllegalArgumentException est lance
R. Grin JPA page 83

merge(A)
Attention, la mthode merge nattache pas A Elle retourne une entit gre qui a la mme identit dans la BD que lentit passe en paramtre mais a nest pas le mme objet

R. Grin

JPA

page 84

14

Cl primaire
Une entit doit avoir un attribut qui correspond la cl primaire dans la table associe La valeur de cet attribut ne doit jamais tre modifie par lapplication Cet attribut doit tre dfini dans lentit racine dune hirarchie dhritage (uniquement cet endroit dans toute la hirarchie dhritage) Une entit peut avoir une cl primaire composite (pas recommand)
page 85 R. Grin JPA page 86

Identit des entits

R. Grin

JPA

Annotation
Lattribut cl primaire est dsign par lannotation @Id Pour une cl composite on utilise @EmbeddedId ou @IdClass

Type de la cl primaire
Le type de la cl primaire (ou des champs dune cl primaire compose) doit tre un des types suivants : n type primitif Java n classe qui enveloppe un type primitif n java.lang.String n java.util.Date n java.sql.Date Ne pas utiliser les types numriques non entiers

R. Grin

JPA

page 87

R. Grin

JPA

page 88

Gnration automatique de cl
Si la cl est de type numrique entier, lannotation @GeneratedValue indique que la cl primaire sera gnre automatiquement par le SGBD Cette annotation peut avoir un attribut strategy qui indique comment la cl sera gnre (il prend ses valeurs dans lnumration GeneratorType)

Types de gnration
AUTO : le type de gnration est choisi par le fournisseur de persistance, selon le SGBD (squence, table,) ; valeur par dfaut SEQUENCE : utilise une squence est utilise IDENTITY : une colonne de type IDENTITY est utilise TABLE : une table qui contient la prochaine valeur de lidentificateur est utilise On peut aussi prciser le nom de la squence ou de la table avec lattribut generator
R. Grin JPA page 90

R. Grin

JPA

page 89

15

Prcisions sur la gnration


Les annotations @SequenceGenerator et @TableGenerator permettent de donner plus de prcisions sur la squence ou la table qui va permettre de gnrer la cl Par exemple @SequenceGenerator permet de prciser la valeur initiale ou le nombre de cls rcupres chaque appel de la squence Voir la spcification de JPA pour plus de prcisions
R. Grin JPA page 91

Exemple
@Id @GeneratedValue( strategy = GenerationType.SEQUENCE, generator = "EMP_SEQ") public long getId() { return id; }

R. Grin

JPA

page 92

Cl composite
Pas recommand, mais une cl primaire peut tre compose de plusieurs colonnes Peut arriver quand la BD existe dj ou quand la classe correspond une table association (association M:N) 2 possibilits : n @IdClass n @EmbeddedId et @Embeddable

Classe pour la cl composite


Dans les 2 cas, la cl primaire doit tre reprsente par une classe Java dont les attributs correspondent aux composants de la cl primaire La classe doit tre public, possder un constructeur sans paramtre, tre srialisable et redfinir equals et hashcode

R. Grin

JPA

page 93

R. Grin

JPA

page 94

@EmbeddedId
@EmbeddedId correspond au cas o la classe entit comprend un seul attribut annot @EmbeddedId La classe cl primaire est annot par @Embeddable Le type daccs (par champs ou proprits) de la classe embeddable doit tre le mme que celui de lentit dont la cl primaire est dfinie
R. Grin JPA page 95

Exemple avec @EmbeddedId


@Entity public class Employe { @EmbeddedId private EmployePK employePK; ... } @Embeddable public class EmployePK { private String nom; private Date dateNaissance; ... }
R. Grin JPA page 96

16

@IdClass
@IdClass correspond au cas o la classe entit comprend plusieurs attributs annots par @Id La classe entit est annote par @IdClass qui prend en paramtre le nom de la classe cl primaire La classe cl primaire nest pas annote ; ses attributs ont les mmes noms et mmes types que les attributs annots @Id dans la classe entit
R. Grin JPA page 97

Exemple avec @IdClass


@Entity @IdClass(EmployePK) public class Employe { @Id private String nom; @Id Date dateNaissance; ... } public class EmployePK { private String nom; private Date dateNaissance; ... }
R. Grin JPA page 98

Quelle solution choisir ?


@IdClass existe pour assurer une compatibilit avec la spcification EJB 2.0 Quand c'est possible il vaut mieux utiliser @EmbeddedId @IdClass a aussi son utilit, par exemple, pour les associations M:N si on veut que la cl primaire de la table association soit compose des cls trangres vers les tables qui sont associes (voir section sur les associations)
R. Grin JPA page 99 R. Grin

Associations

JPA

page 100

Gnralits
Une association peut tre uni ou bidirectionnelle Elle peut tre de type 1:1, 1:N, N:1 ou M:N Les associations doivent tre indiques par une annotation sur la proprit correspondante, pour que JPA puisse les grer correctement

Exemple
@ManyToOne public Departement getDepartement() { ... }

R. Grin

JPA

page 101

R. Grin

JPA

page 102

17

Reprsentation des associations 1:N et M:N


Elles sont reprsentes par des collections ou maps qui doivent tre dclares par un des types interface suivants (de java.util) : n Collection n Set n List n Map Les variantes gnriques sont permises ; par exemple Collection<Employe>
R. Grin JPA page 103

Types utiliser
Le plus souvent Collection sera utilis Set peut tre utile pour liminer les doublons Les types concrets, par exemple HashSet ou ArrayList, ne peuvent tre utiliss que pour des entits nouvelles ; ds que lentit est gre, les types interfaces doivent tre utiliss List peut tre utilis pour conserver un ordre mais ncessite quelques prcautions
R. Grin JPA page 104

Ordre dans les collections


Lordre dune liste n'est pas ncessairement prserv dans la base de donnes De plus, lordre en mmoire doit tre maintenu par le code (pas automatique) Tout ce quon peut esprer est de rcuprer les entits associes dans la liste avec un certain ordre lors de la rcupration dans la base, en utilisant lannotation @OrderBy

@OrderBy
Cette annotation indique dans quel ordre sont rcupres les entits associes Il faut prciser un ou plusieurs attributs qui dterminent l'ordre Chaque attribut peut tre prcis par ASC ou DESC (ordre ascendant ou descendant); ASC par dfaut Les diffrents attributs sont spars par une virgule Si aucun attribut n'est prcis, l'ordre sera celui de la cl primaire
R. Grin JPA page 106

R. Grin

JPA

page 105

Exemples
@Entity public class Departement { ... @OneToMany(mappedBy="departement") @OrderBy("nomEmploye") public List<Employe> getEmployes() { ... @OrderBy("poste DESC, nomEmploye ASC")

Associations bidirectionnelles
Le dveloppeur est responsable de la gestion correcte des 2 bouts de lassociation Par exemple, si un employ change de dpartement, les collections des employs des dpartements concerns doivent tre modifies Un des 2 bouts est dit propritaire de lassociation

R. Grin

JPA

page 107

R. Grin

JPA

page 108

18

Bout propritaire
Pour les associations autres que M:N ce bout correspond la table qui contient la cl trangre qui traduit lassociation Pour les associations M:N le dveloppeur peut choisir arbitrairement le bout propritaire Lautre bout (non propritaire) est qualifi par lattribut mappedBy qui donne le nom de lattribut dans le bout propritaire qui correspond la mme association
R. Grin JPA page 109

Exemple
Dans la classe Employe :
@ManyToOne public Departement getDepartement() { return departement; }

Dans la classe Departement :


@OneToMany(mappedBy="departement") public Collection<Employe> getEmployes() { return employes; }

R. Grin

JPA

page 110

Annotation @JoinColumn
Cette annotation donne le nom de la colonne cl trangre qui reprsente l'association dans le modle relationnel Elle doit tre mise du ct propritaire Sans cette annotation, le nom est dfini par dfaut : <entit_but>_<cl_primaire_entit_but>

Exemple
Pour l'association qui dtermine le dpartement d'un employ Par dfaut, la colonne cl trangre place dans la table EMPLOYE s'appellera Departement_ID Pour changer ce nom (dans la classe Employe) :
@ManyToOne @JoinColumn(name="DEPT_ID") public Departement getDepartement() {
R. Grin JPA page 112

R. Grin

JPA

page 111

Persistance des objets associs


Lorsquun objet o est rendu persistant (mthode persist), les objets rfrencs par o devraient tre rendus eux-aussi persistants Ce concept sappelle la persistance par transitivit a serait un comportement logique : un objet nest pas vraiment persistant si une partie des valeurs de ses proprits nest pas persistante
R. Grin JPA page 113

Pas si simple
Maintenir une cohrence automatique des valeurs persistantes nest pas si simple en cas de persistance par transitivit Par exemple, que se passe-t-il si un objet supprim est rfrenc par un autre objet ?

R. Grin

JPA

page 114

19

Le choix de JPA
Par dfaut, JPA neffectue pas de persistance par transitivit Ce comportement permet plus de souplesse, et un meilleur contrle de lapplication sur ce qui est rendu persistant Pour que les objets associs un objet persistant deviennent automatiquement persistants, il faut lindiquer dans les informations de mapping de lassociation (attribut cascade)
R. Grin JPA page 115

Attribut cascade
Les annotations qui dcrivent les associations entre objets peuvent avoir un attribut cascade pour indiquer que certaines oprations de GE doivent tre appliques aux objets associs Ces oprations sont PERSIST, REMOVE, REFRESH et MERGE ; ALL correspond toutes ces oprations Par dfaut, aucune opration nest applique transitivement
R. Grin JPA page 116

Exemples
@OneToMany( cascade=CascadeType.PERSIST) @OneToMany( cascade={CascadeType.PERSIST, CascadeType.MERGE})

Association 1:1
Annotation @OneToOne Reprsente par une cl trangre dans la table qui correspond au ct propritaire Exemple :
@OneToOne public Adresse getAdresse() { }

R. Grin

JPA

page 117

R. Grin

JPA

page 118

Associations 1:N et N:1


Annotations @OneToMany et @ManyToOne Reprsente par une cl trangre dans la table qui correspond au ct propritaire (obligatoirement le ct Many )

Exemple
class Employe { ... @ManyToOne public Departement getDepartement() { ... } } class Departement { ... @OneToMany(MappedBy="departement") public List<Employe> getEmployes() { ... } }
R. Grin JPA page 120

R. Grin

JPA

page 119

20

Cas particulier
Une association monodirectionnelle 1:N est traduite pas une table association Cette faon de faire vite d'avoir une cl trangre dans la table qui reprsente le ct N (comme cest le cas si lassociation est bidirectionnelle) alors que la navigation nest pas possible partir de ce ct N

Association M:N
Annotation @ManyToMany Reprsente par une table association

R. Grin

JPA

page 121

R. Grin

JPA

page 122

Association M:N (1)


Les valeurs par dfaut : n le nom de la table association est la concatnation des 2 tables, spares par _ n les noms des colonnes cls trangres sont les concatnations de la table rfrence, de _ et de la colonne Id de la table rfrence

Association M:N (2)


Si les valeurs par dfaut ne conviennent pas, le ct propritaire doit comporter une annotation @JoinTable Lautre ct doit toujours comporter lattribut mappedBy

R. Grin

JPA

page 123

R. Grin

JPA

page 124

@JoinTable
Donne des informations sur la table association qui va reprsenter lassociation Attribut name donne le nom de la table Attribut joinColumns donne les noms des colonnes de la table qui rfrencent les cls primaires du ct propritaire de lassociation Attribut inverseJoinColumns donne les noms des colonnes de la table qui rfrencent les cls primaires du ct qui nest pas propritaire de lassociation
R. Grin JPA page 125

Exemple (classe Employe)


@ManyToMany @JoinTable( name="EMP_PROJET" joinColumns=@JoinColumn(name="matr") inverseJoinColumns= @JoinColumn(name="codeProjet") ) public Collection<Projet> getProjets() {

R. Grin

JPA

page 126

21

Exemple (classe Projet)


@ManyToMany(mappedBy="projets") public Collection<Employe> getEmps() {

Association M:N avec information porte par l'association


Une association M:N peut porter une information Exemple : Association entre les employs et les projets Un employ a une (et une seule) fonction dans chaque projet auquel il participe En ce cas, il n'est pas possible de traduire l'association en ajoutant 2 collections (ou maps) comme il vient d'tre dcrit
page 127 R. Grin JPA page 128

R. Grin

JPA

Classe association pour une association M:N


L'association sera traduite par une classe association 2 possibilits pour cette classe, suivant qu'elle contient ou non un attribut identificateur (@Id) unique Le plus simple est de n'avoir qu'un seul attribut identificateur

Exemple - 1 identificateur
Association entre les employs et les projets Cas d'un identificateur unique : la classe association contiendra les attributs id (int), employe (Employe), projet (Projet) et fonction (String) L'attribut id est annot par @Id Les attributs employe et projet sont annots par @ManyToOne Une contrainte d'unicit sur (EMPLOYE_ID, PROJET_ID) traduira le fait qu'un employ ne peut avoir 2 fonctions dans un mme projet
page 129 R. Grin JPA page 130

R. Grin

JPA

Exemple - 2 identificateurs (1)


Si la base de donnes existe dj, il sera frquent de devoir s'adapter une table association qui contient les colonnes suivantes (pas de colonne id): n employe_id, cl trangre vers EMPLOYE n projet_id, cl trangre vers PROJET n fonction et qui a (employe_id, projet_id) comme cl primaire
R. Grin JPA page 131

Exemple - 2 identificateurs (2)


En ce cas, la solution est plus complexe, et pas toujours portable dans l'tat actuel de la spcification JPA La solution donne dans les transparents suivants convient pour TopLink essentials La difficult vient de l'criture de la classe Participation L'ide est de dissocier la fonction de cl primaire des attributs employeId et projetId de leur rle dans les associations
R. Grin JPA page 132

22

Exemple - 2 identificateurs avec TopLink


La solution donne dans les transparents suivants convient pour TopLink essentials La difficult vient de l'criture de la classe Participation L'ide est de dissocier la fonction d'identificateur des attributs employeId et projetId de leur rle dans les associations avec les classes Projet et Employe Pour viter les doublons d'attributs, les identificateurs sont marqus non modifiables ni insrables (pas de persistance dans la BD)
R. Grin JPA page 133

Classes Employe et Projet


@Entity public class Employe { @Id public int getId() { ... } @OneToMany(mappedBy="employe") public Collection<Participation> getParticipations() { ... } . . . } @Entity public class Projet { @Id public int getId() { ... } @OneToMany(mappedBy="projet") public Collection<Participation> getParticipations() { ... } . . . }
R. Grin JPA page 134

Classe Participation (dbut)


@Entity @IdClass(ParticipationId.class) public class Participation { // Les identificateurs "read-only" @Id @Column(name="EMPLOYE_ID", insertable="false", updatable="false") public int getEmployeId() { } @Id @Column(name="PROJET_ID", insertable="false", updatable="false") public int getProjetId() { }
R. Grin JPA page 135

Classe Participation (fin)


// Les associations @OneToMany public Employe getEmploye() { } @OneToMany public Projet getProjet() { } . . . }

R. Grin

JPA

page 136

Classe ParticipationId
public class ParticipationId implements Serializable { private int employeId; private int projetId; public int getEmployeId() { ... } public void setEmployeId(int employeId) { ... } public int getProjetId() { ... } public void setProjetId(int projetId) { ... } // Redfinir aussi equals et hasCode
R. Grin JPA page 137

Rcupration des entits associes


Lorsquune entit est rcupre depuis la base de donnes par une requte (Query) ou par un find, est-ce que les entits associes doivent tre elles aussi rcupres ? Si elles sont rcupres, est-ce que les entits associes ces entits doivent elles aussi tre rcupres ? On voit que le risque est de rcuprer un trs grand nombre dentits qui ne seront pas utiles pour le traitement en cours
R. Grin JPA page 138

23

EAGER ou LAZY
JPA laisse le choix de rcuprer ou non immdiatement les entits associes, suivant les circonstances Il suffit de choisir le mode de rcupration de lassociation (LAZY ou EAGER) Une requte sera la mme, quel que soit le mode de rcupration Dans le mode LAZY les donnes associes ne sont rcupres que lorsque cest vraiment ncessaire
R. Grin JPA page 139

Rcupration retarde (LAZY)


Dans le cas o une entit associe nest pas rcupre immdiatement, JPA remplace lentit par un proxy , objet qui permettra de rcuprer lentit plus tard si besoin est Ce proxy contient la cl primaire qui correspond lentit non immdiatement rcupre Il est possible de lancer une requte avec une rcupration immdiate, mme si une association est en mode LAZY (join fetch de JPQL tudi plus loin)
R. Grin JPA page 140

Comportement par dfaut de JPA


Par dfaut, JPA ne rcupre immdiatement que les entits associes par des associations dont le but est One (une seule entit lautre bout) : OneToOne et ManyToOne (mode EAGER) Pour les associations dont le but est Many (une collection lautre bout), OneToMany et ManyToMany, par dfaut, les entits associes ne sont pas rcupres immdiatement (mode LAZY)
R. Grin JPA page 141

Indiquer le type de rcupration des entits associes


Lattribut fetch dune association permet dindiquer une rcupration immdiate des entits associes (FetchType.EAGER) ou une rcupration retarde (FetchType.LAZY) si le comportement par dfaut ne convient pas Exemple :
@OneToMany(mappedBy="departement", fetch=FetchType.EAGER) public Collection<Employe> getEmployes()
R. Grin JPA page 142

Mode de rcupration des attributs


Les attributs aussi peuvent tre rcuprs en mode retard Le mode de rcupration par dfaut est le mode EAGER pour les attributs (ils sont chargs en mme temps que lentit) Si un attribut est dun type de grande dimension (LOB), il peut aussi tre marqu par @Basic(fetch=FetchType.LAZY) ( utiliser avec parcimonie) Cette annotation nest quune suggestion au GE, quil peut ne pas suivre
R. Grin JPA page 143

Map pour association


A la place dune collection il est possible dutiliser une map En ce cas il faut annoter lassociation avec @MapKey qui prcise la cl de la map qui doit tre un des attributs de lentit contenue dans la map La classe de la cl doit avoir sa mthode hashCode compatible avec sa mthode equals et chaque cl doit tre unique parmi toutes les autres cls de la map
R. Grin JPA page 144

24

Map pour association


Si lassociation est traduite par une map mais na pas dannotation @KeyMap, la cl sera considre tre lidentificateur de lentit

Exemple
Les employs dun dpartement peuvent tre enregistrs dans une map dont les cls sont les noms des employs (on suppose que 2 employs nont pas le mme nom)
public class Departement { ... @OneToMany(mappedBy="nom") public Map<String,Employe> getEmployes(){ ... }

R. Grin

JPA

page 145

R. Grin

JPA

page 146

Stratgies
A ce jour, les implmentations de JPA doivent obligatoirement offrir 2 stratgies pour la traduction de lhritage : n une seule table pour une hirarchie dhritage (SINGLE_TABLE) n une table par classe ; les tables sont jointes pour reconstituer les donnes (JOINED) La stratgie une table distincte par classe concrte est seulement optionnelle (TABLE_PER_CLASS)
page 147 R. Grin JPA page 148

Hritage

R. Grin

JPA

Une table par hirarchie


Sans doute la stratgie la plus utilise Valeur par dfaut de la stratgie de traduction de lhritage Elle est performante et permet le polymorphisme Mais elle induit beaucoup de valeurs NULL dans les colonnes si la hirarchie est complexe

Exemple
A mettre dans la @Entity classe racine de @Inheritance(strategy= la hirarchie InheritanceType.SINGLE_TABLE) public abstract class Personne {...} @Entity Employe par dfaut @DiscriminatorValue("E") public class Employe extends Personne { ... }
R. Grin JPA page 150

R. Grin

JPA

page 149

25

Nom de la table
Si on choisit la stratgie une seule table pour une arborescence dhritage la table a le nom de la table associe la classe racine de la hirarchie

Colonne discriminatrice (1)


Une colonne de la table doit permettre de diffrencier les lignes des diffrentes classes de la hirarchie dhritage Cette colonne est indispensable pour le bon fonctionnement des requtes qui se limitent une sous-classe Par dfaut, cette colonne se nomme DTYPE et elle est de type Discriminator.STRING de longueur 31 (autres possibilits pour le type : CHAR et INTEGER)
R. Grin JPA page 152

R. Grin

JPA

page 151

Colonne discriminatrice (2)


Lannotation @DicriminatorColumn permet de modifier les valeurs par dfaut Ses attributs : n name n discriminatorType n columnDefinition fragment SQL pour crer la colonne n length longueur dans le cas o le type est STRING (31 par dfaut)
R. Grin JPA page 153

Exemple
@Entity @Inheritance @DiscriminatorColumn( name="TRUC", discriminatorType="STRING", length=5) public class Machin { }

R. Grin

JPA

page 154

Valeur discriminatrice
Chaque classe est diffrencie par une valeur de la colonne discriminatrice Cette valeur est passe en paramtre de lannotation @DiscriminatorValue Par dfaut cette valeur est le nom de la classe

Une table par classe


Toutes les classes, mme les classes abstraites, sont reprsentes par une table Ncessite des jointures pour retrouver les proprits dune instance dune classe Une colonne discriminatrice est ajoute dans la table qui correspond la classe racine de la hirarchie dhritage Cette colonne permet de simplifier certaines requtes ; par exemple, pour retrouver les noms de tous les employs (classe Personne la racine de la hirarchie dhritage)
page 155 R. Grin JPA page 156

R. Grin

JPA

26

Exemple
@Entity @Inheritance(strategy= InheritanceType.JOINED) public abstract class Personne {...} @Entity @DiscriminatorValue("E") public class Employe extends Personne { ... }

Une table par classe concrte


Stratgie seulement optionnelle Pas recommand car le polymorphisme est plus complexe obtenir (voir cours sur le mapping objet-relationnel) Chaque classe concrte correspond une seule table totalement spare des autres tables Toutes les proprits de la classe, mme celles qui sont hrites, se retrouvent dans la table
R. Grin JPA page 158

R. Grin

JPA

page 157

Exemple
@Entity @Inheritance(strategy= InheritanceType.TABLE_PER_CLASS) public abstract class Personne {...} @Entity @Table(name=EMPLOYE) public class Employe extends Personne { ... }

Entit abstraite
Une classe abstraite peut tre une entit (annote par @Entity) Son tat sera persistant et sera utilis par les sous-classes entits Comme toute entit, elle pourra dsigner le type retour dune requte (query) pour une requte polymorphe

R. Grin

JPA

page 159

R. Grin

JPA

page 160

Complments
Lannotation @Entity ne shrite pas Les sous-classes entits dune entit doivent tre annote par @Entity Une entit peut avoir une classe mre qui nest pas une entit ; en ce cas, ltat de cette classe mre ne sera pas persistant

Classe mre persistante


Une entit peut aussi avoir une classe mre dont ltat est persistant, sans que cette classe mre ne soit une entit En ce cas, la classe mre doit tre annote par @MappedSuperclass Ltat de cette classe mre sera rendu persistant avec ltat de la classe entit fille, dans la mme table que cette classe entit

R. Grin

JPA

page 161

R. Grin

JPA

page 162

27

Classe mre persistante


Cette classe mre ne pourra pas tre renvoye par une requte, ne pourra pas tre passe en paramtre dune mthode dun EntityManager ou dun Query et ne pourra tre le but dune association

Classe mre non persistante


Une classe entit peut aussi hriter dune classe mre dont ltat nest pas persistant En ce cas, ltat hrit de la classe mre ne sera pas persistant La classe mre ne comportera aucune annotation particulire lie la persistance

R. Grin

JPA

page 163

R. Grin

JPA

page 164

Chercher par identit


find et getReference (de EntityManager) permettent de retrouver une entit en donnant son identificateur dans la BD Elles prennent 2 paramtres de type n Class<T> pour indiquer le type de lentit recherche (le rsultat renvoy sera de cette classe ou d'une sous-classe) n Object pour indiquer la cl primaire Exemple :
Departement dept = em.find(Departement.class, 10);
R. Grin JPA page 165 R. Grin JPA page 166

Requtes - JPQL

getReference
getReference renvoie une rfrence vers une entit, sans que cette entit ne soit ncessairement initialise Le plus souvent il vaut mieux utiliser find

getReference
getReference peut tre (rarement) utilise pour amliorer les performances quand une entit non initialise peut tre suffisante, sans que lentit entire soit retrouve dans la base de donnes Par exemple, pour indiquer une association dont le but est unique (OneToOne ou ManyToOne) :
Departement dept = em.getReference(Departement.class, 10); Employe emp.setDepartement(dept);

R. Grin

JPA

page 167

R. Grin

JPA

page 168

28

tapes pour rcuprer des donnes


Souvent il est ncessaire de rechercher des donnes sur des critres plus complexes que la simple identit Les tapes sont alors les suivantes : 1. Dcrire ce qui est recherch (langage JPQL) 2. Crer une instance de type Query 3. Initialiser la requte (paramtres, pagination) 4. Lancer lexcution de la requte
R. Grin JPA page 169

Langage JPQL
Le langage JPQL (Java Persistence Query Language) permet de dcrire ce que lapplication recherche Il ressemble beaucoup SQL

R. Grin

JPA

page 170

Requtes sur les entits objet


Les requtes travaillent avec le modle objet et pas avec le modle relationnel Les identificateurs dsignent les classes et leurs proprits et pas les tables et leurs colonnes Les seules classes qui peuvent tre explicitement dsignes dans une requte (clause from) sont les entits

Alias
Le texte des requtes utilise beaucoup les alias de classe Les attributs des classes doivent tre prfixs par les alias Une erreur frquente du dbutant est doublier les alias en prfixe

R. Grin

JPA

page 171

R. Grin

JPA

page 172

Exemples de requtes
select e from Employe as e select e.nom, e.salaire from Employe e select e from Employe e where e.departement.nom = 'Direction' select d.nom, avg(e.salaire) from Departement d join d.employes e group by d.nom having count(d.nom) > 5

Type du rsultat
Lexpression de la clause select peut tre n une (ou plusieurs) expression entit , par exemple un employ (e par exemple) n une (ou plusieurs) expression valeur , par exemple le nom et le salaire dun employ (e.nom par exemple) Lexpression ne peut tre une collection (d.employes par exemple), bien que TopLink le permette !
R. Grin JPA page 174

R. Grin

JPA

page 173

29

Obtenir le rsultat de la requte


Pour le cas o une seule valeur ou entit est renvoye, le plus simple est dutiliser la mthode getSingleResult() ; elle renvoie un Object

Obtenir le rsultat de la requte


Pour le cas o une plusieurs valeurs ou entits peuvent tre renvoyes, il faut utiliser la mthode getResultList() Elle renvoie une liste raw (pas gnrique) des rsultats, instance de java.util.List Un message davertissement sera affich durant la compilation si le rsultat est rang dans une liste gnrique (Liste<Employe> par exemple)
R. Grin JPA page 176

R. Grin

JPA

page 175

Type dun lment du rsultat


Le type dun lment de la liste (ou de lunique valeur ou entit renvoye) est n Object si la clause select ne comporte quune seule expression n Object[] si elle comporte plusieurs expressions

Exemple
texte = "select e.nom, e.salaire " + " from Employe as e"; query = em.createQuery(texte); List<Object[]> liste = (List<Object[]>)query.getResultList(); for (Object[] info : liste) { System.out.println(info[0] + " gagne " + info[1]); }

R. Grin

JPA

page 177

R. Grin

JPA

page 178

Interface Query
Reprsente une requte Une instance de Query (dune classe implmentant Query) est obtenue par les mthodes createQuery, createNativeQuery ou createNamedQuery de linterface EntityManager

Mthodes de Query (1)


List getResultList() Object getSingleResult() int executeUpdate() Query setMaxResults(int nbResultats) Query setFirstResult(int positionDepart) Query setFlushMode(FlushModeType modeFlush)
R. Grin JPA page 180

R. Grin

JPA

page 179

30

Mthodes de Query (2)


Query setParameter(String nom, Object valeur) Query setParameter(String nom, Date valeur, TemporalType typeTemporel) Query setParameter(String nom, Calendar valeur, TemporalType typeTemporel)

Types temporels
On a vu que les 2 types java temporels du paquetage java.util (Date et Calendar) ncessitent une annotation @Temporal Ils ncessitent aussi un paramtre supplmentaire pour la mthode setParameter

R. Grin

JPA

page 181

R. Grin

JPA

page 182

Exemple
@Temporal(TemporalType.DATE) private Calendar dateEmb; em.createQuery("select e from employe e" + " where e.dateEmb between ?1 and ?2") .setParameter(1, debut, TemporalType.DATE) .setParameter(2, fin, TemporalType.DATE) .getResultList();

Types de requte
Requtes dynamiques dont le texte est donne en paramtre de createQuery Requtes natives particulires un SGBD (pas portables) ; requte SQL (pas JPQL) avec tables et colonnes (pas classes et attributs) Requtes nommes dont le texte est donne dans une annotation de lentit concerne et dont le nom est pass en paramtre de createNamedQuery ; une requte nomme peut tre dynamique ou native
R. Grin JPA page 184

R. Grin

JPA

page 183

Exemple de requte nomme


@Entity @NamedQuery{ name = "findNomsEmployes", query = "select e.nom from Employe as e where upper(e.departement.nom) = :nomDept" } public class Employe extends Personne { ... Query q = em.createNamedQuery("findNomsEmployes");
R. Grin JPA page 185

Paramtres des requtes


Un paramtre peut tre dsign par son numro (?n) ou par son nom (:nom) Les valeurs des paramtres sont donnes par les mthodes setParameter Les paramtres sont numrots partir de 1 Un paramtre peut tre utilis plus dune fois dans une requte Lusage des paramtres nomms est recommand (plus lisible)
R. Grin JPA page 186

31

Exemples
Query query = em.createQuery( "select e from Employe as e " + "where e.nom = ?1"); query.setParameter(1, "Dupond"); Query query = em.createQuery( "select e from Employe as e " + "where e.nom = :nom"); query.setParameter("nom", "Dupond");

Mode de flush
Normalement (mode FlushMode.AUTO) un flush des entits concernes par une requte est effectu avant la requte pour que le rsultat tienne compte des modifications effectues en mmoire sur ces entits Pour une requte il est possible d'viter ce flush avec la mthode setFlushMode : query.setFlushMode(FlushMode.COMMI T);

R. Grin

JPA

page 187

R. Grin

JPA

page 188

Clauses dun select


Les transparents suivants tudient en dtails le langage JPQL select : type des objets ou valeurs renvoyes from : o les donnes sont rcupres where : slectionne les donnes group by : regroupe des donnes having : slectionne les groupes (ne peut exister sans clause group by) order by : ordonne les donnes

R. Grin

JPA

page 189

R. Grin

JPA

page 190

Polymorphisme dans les requtes


Les mots-cls select, from, distinct, join, sont insensibles la casse Toutes les requtes sont polymorphes : un nom de classe dans la clause from dsigne cette classe et toutes les sous-classes Exemple : select count(a) from Article as a compte le nombre dinstances de la classe Article et de tous les sous-classes de Article

R. Grin

JPA

page 191

R. Grin

JPA

page 192

32

Expression de chemin
Les requtes peuvent contenir des expressions de chemin pour naviguer entre les entits en suivant les associations dclares dans le modle objet (les annotations @OneToOne, @OneToMany, ) La notation pointe est utilise

Exemples
Si e est un alias pour Employe, n e.departement dsigne le dpartement dun employ n e.projets dsigne la collection de projets auxquels participe un employ
select e.nom from Employe as e where e.departement.nom = 'Qualit'

R. Grin

JPA

page 193

R. Grin

JPA

page 194

distinct
Dans une clause select, indique que les valeurs dupliques sont limines (la requte ne garde quune seule des valeurs gales) Exemple : select distinct e.departement from Employe e

new
Il est possible de renvoyer des instances dune classe dont le constructeur prend en paramtre des informations rcupres dans la base de donnes La classe doit tre dsigne par son nom complet (avec le nom du paquetage) Exemple :
select new p1.p2.Classe(e.nom, e.salaire) from Employe e

R. Grin

JPA

page 195

R. Grin

JPA

page 196

Clauses where et having


Ces clauses peuvent comporter les mots-cls suivants : n [NOT] LIKE, [NOT] BETWEEN, [NOT] IN n AND, OR, NOT n [NOT] EXISTS n ALL, SOME/ANY n IS [NOT] EMPTY, [NOT] MEMBER OF

Exemple
select d.nom, avg(e.salaire) from Departement d join d.employes e group by d.nom having count(d.nom) > 3

R. Grin

JPA

page 197

R. Grin

JPA

page 198

33

having
Restriction : la condition doit porter sur lexpression de regroupement ou sur une fonction de regroupement portant sur lexpression de regroupement Par exemple, la requte suivante provoque une exception :
select d.nom, avg(e.salaire) from Departement d join d.employes e group by d.nom having avg(e.salaire) > 1000
R. Grin JPA page 199

Sous-requte (1)
Les clauses where et having peuvent contenir des sous-requtes Exemple :
select e from Employe e where e.salaire >= ( select e2.salaire from Employe e2 where e2.departement = 10)

R. Grin

JPA

page 200

Sous-requte (2)
{ALL | ANY | SOME} (sous-requte) fonctionne comme dans SQL Exemple :
select e from Employe e where e.salaire >= ALL ( select e2.salaire from Employe e2 where e2.departement = e.departement)

Sous-requte synchronise
Une sous-requte peut tre synchronise avec une requte englobante Exemple :
select e from Employe e where e.salaire >= ALL ( select e2.salaire from Employe e2 where e2.departement = e.departement)

R. Grin

JPA

page 201

R. Grin

JPA

page 202

Sous-requte - exists
[not]exists fonctionne comme avec SQL Exemple :
select emp from Employe e where exists ( select ee from Employe ee where ee = e.epouse)

Rgle pour les expressions de chemin


Une navigation peut tre chane une navigation prcdente la condition que la navigation prcdente ne donne quune seule entit (OneToOne ou ManyToOne)

R. Grin

JPA

page 203

R. Grin

JPA

page 204

34

Exemple
select e.nom, e.departement.nom, e.superieur.departement.nom from Employe e

Contre-exemple
d.employes.nom est interdit car d.employes est une collection Pour avoir les noms des employs dun dpartement, il faut utiliser une jointure

R. Grin

JPA

page 205

R. Grin

JPA

page 206

Jointure
Une jointure permet de combiner plusieurs entits dans un select Rappel : il est possible dutiliser plusieurs entits dans une requte grce la navigation Une jointure est le plus souvent utilise pour rsoudre les cas (interdit par JPA) o n lexpression du select serait une collection n la navigation partirait dune collection
R. Grin JPA page 207

Types de jointures
Il existe plusieurs types de jointures : n jointure interne (jointure standard join) n jointure externe (outer join) n jointure avec rcupration de donnes en mmoire (join fetch)

R. Grin

JPA

page 208

Exemple
Si on veut tous les employs dun dpartement, la requte suivante nest pas permise par la spcification JPA (bien que TopLink lautorise) :
select d.employes from Departement d where d.nom = 'Direction'

Autres exemples
select e.nom from Departement d join d.employes e where d.nom = 'Direction' select e.nom, parts.projet.nom from Employe e join e.participations parts select e.nom, d.nom from Employe e, Departement d where d = e.departement select e, p from Employe e join e.participations parts join parts.projet p
R. Grin JPA page 210

Une jointure est ncessaire :


select e from Departement d join d.employes e where d.nom = 'Direction'
R. Grin JPA page 209

35

Jointure externe
select e, d from Employe e left join e.departement d

join fetch
Permet dviter le problme des N + 1 selects Lentit plac droite de fetch join sera cre en mmoire en mme temps que lentit de la clause select Le select SQL gnr sera une jointure externe qui rcuprera les donnes de toutes les entits associes en mme temps que les donnes des entits principales de la requte
R. Grin JPA page 212

affichera aussi les employs qui ne sont pas associs un dpartement

R. Grin

JPA

page 211

Exemple
select e from Employe e join fetch e.departement

Exemple
String texteQuery = "select e " + " from Employe as e " + " join fetch e.participations"; Query query = em.createQuery(texteQuery); listeEmployes = (List<Employe>)query.getResultList();

Cette requte rcuprera tous les employs mais, en plus, lappel de la mthode getDepartement() ne provoquera aucune interrogation de la base de donnes puisque le join fetch aura dj charg tous les dpartements des employs Lexemple suivant prcharge les collections de participations aux projets
R. Grin JPA page 213

R. Grin

JPA

page 214

Doublons possibles avec join fetch


La requte SQL lance par un join fetch fait une jointure pour rcuprer les entits prcharges Ensuite, les entits prcharges sont enleves des lignes du rsultat pour quelles napparaissent pas dans le rsultat du query Ce traitement, impos par la spcification de JPA, peut occasionner des doublons dans le rsultat Pour les viter, il faut ajouter loprateur DISTINCT dans le texte de la requte ou placer le rsultat dans une collection de type Set
R. Grin JPA page 215

Fonctions
Fonctions de chanes de caractres : concat, substring, trim, lower, upper, length, locate (localiser une sous-chane dans une autre) Fonctions arithmtiques : abs, sqrt, mod, size (dune collection) Fonctions de date : current_date, current_time, current_timestamp Fonctions de regroupement : count, max, min, avg Pour plus dinformations, consultez la spcification JPA
R. Grin JPA page 216

36

Travail avec les collections


Une expression chemin dun select peut dsigner une collection Exemples : departement.employes facture.lignes La fonction size donne la taille de la collection La condition is [not] empty est vraie si la collection est [nest pas] vide La condition [not] member of indique si une entit appartient une collection
R. Grin JPA page 217

Exemples
select d from Departement where e.employes is empty select e from Employe e where :projet member of e.participations.projet

R. Grin

JPA

page 218

Parcours dune collection


La requte suivante ne donnera pas tous les produits lis une facture ; elle provoquera une exception lexcution
select distinct f.lignes.produit from Facture as f

Parcours dune collection


Le plus simple est dutiliser un join dans le from avec un alias ( l dans lexemple cidessous) pour dsigner un lment qui parcourt la collection :
select distinct l.produit from Facture as f join f.lignes as l

En effet, il est interdit de composer une expression de chemin en partant dune expression qui dsigne une collection (f.lignes)

Lautre solution, in , une ancienne syntaxe hrite dEJB 2, nest pas recommande

R. Grin

JPA

page 219

R. Grin

JPA

page 220

Enchanement des mthodes


Les mthodes setParameter, setMaxResults renvoient le Query modifi On peut donc les enchaner Exemple :
em.createQuery(texteQuery) .setParameter(nomParam, valeurParam) .setMaxResults(30) .getResultList();

Pagination du rsultat
Query setMaxResults(int n) : indique le nombre maximum de rsultats retrouver Query setFirstResult(int n) : indique la position du 1er rsultat retrouver (numrot partir de 0)

R. Grin

JPA

page 221

R. Grin

JPA

page 222

37

Utilit
Pour les performances il est parfois mauvais de charger toutes les donnes modifier dans des instances dentits En ce cas, EJBQL permet de modifier les donnes de la base directement, sans crer les entits correspondantes

Opration de modification en volume

R. Grin

JPA

page 223

R. Grin

JPA

page 224

Cas dutilisation
Si on veut augmenter de 5% les 1000 employs de lentreprise il serait mauvais de rcuprer dans 1000 instances les donnes de chaque employs, de modifier le salaire de chacun, puis de sauvegarder les donnes Un simple ordre SQL
update employe set salaire = salaire * 1.05

Exemple
em.getTransaction().begin(); String ordre = "update Employe e " + " set e.salaire = e.salaire * 1.05"; Query q = em.createQuery(ordre); int nbEntiteModifiees = q.executeUpdate(); em.getTransaction().commit();

sera normment plus performant

R. Grin

JPA

page 225

R. Grin

JPA

page 226

Syntaxe
Les ordres de modification en volume rfrencent les classes et les proprits des classes mais ils ne crent aucune entit en mmoire et ils ne mettent pas jour les entits dj prsentes en mmoire update Entite as alias set alias.prop1 = val1, alias.prop2 = val2, where condition La condition peut tre aussi complexe que la condition dun select
R. Grin JPA page 227

Remarques
Les modifications doivent tre faites dans une transaction Le plus souvent il faut isoler le lancement de ces oprations dans une transaction part, ou au moins excuter ces oprations au dbut dune transaction avant la rcupration dans la base dentits touches par lopration En effet, les entits en mmoire ne sont pas modifies par lopration et elles ne correspondront alors donc plus aux nouvelles valeurs modifies dans la base de donnes
R. Grin JPA page 228

38

Exceptions non contrles


JPA nutilise que des exceptions non contrles (descendantes de RuntimeException) JPA utilise les 2 exceptions IllegalArgumentException et IllegalStateException du paquetage java.lang Sinon, toutes les autres exceptions sont dans le paquetage javax.persistence et hritent de PersistenceException
R. Grin JPA page 229 R. Grin JPA page 230

Exceptions

Types dexception
EntityNotFoundException EntityExistsException NonUniqueResultException NoResultException TransactionRequiredException RollbackException OptimisticLockException

Transaction

R. Grin

JPA

page 231

R. Grin

JPA

page 232

2 types de transactions
Les transactions locales une ressource, fournies par JDBC sont attaches une seule base de donnes Les transactions JTA, avec plus de fonctionnalits que les transactions JDBC, en particulier elles peuvent travailler avec plusieurs bases de donnes

Transactions dans Java EE


Elles sont tudies dans la dernire section de ce support de cours

R. Grin

JPA

page 233

R. Grin

JPA

page 234

39

Transactions dans Java SE (sans serveur dapplications)


Daprs la spcification JPA, dans Java SE, les fournisseurs de persistance doivent supporter les transactions locales une ressource, mais ne sont pas obligs de supporter les transactions JTA La dmarcation des transactions est choisie par le dveloppeur Les contextes de persistance peuvent couvrir plusieurs transactions
R. Grin JPA page 235

EntityTransaction
En dehors dun serveur dapplications, une application doit utiliser linterface javax.persitence.EntityTransaction pour travailler avec des transactions locales une ressource Une instance de EntityTransaction peut sobtenir par la mthode getTransaction() de EntityManager

R. Grin

JPA

page 236

EntityTransaction
public interface EntityTransaction { public void begin(); public void commit(); public void rollback(); public void setRollbackOnly(); public boolean getRollbackOnly(); public void isActive(); }

Exemple
EntityManager em; ... try { em.getTransaction().begin() ... em.getTransaction().commit(); } finally { em.close(); }
page 237 R. Grin JPA page 238

R. Grin

JPA

Rollback (1)
En cas de rollback, n rollback dans la base de donnes n le contexte de persistance est vid ; toutes les entits deviennent dtaches

Rollback (2)
Les instances dentits Java gardent les valeurs quelles avaient au moment du rollback Mais ces valeurs sont le plus souvent fausses Il est donc rare dutiliser ces entits en les rattachant par un merge un GE Le plus souvent il faut relancer des requtes pour rcuprer des entits avec des valeurs correctes

R. Grin

JPA

page 239

R. Grin

JPA

page 240

40

Transaction et contexte de persistance


Quand un GE nest pas gr par un container le contexte de persistance nest pas ferm la fin dune transaction Quand un GE est gr par un container et que le contexte de persistance nest pas de type tendu , le contexte est ferm la fin dune transaction (voir la fin de ce support)

Modifications et commit
Les modifications effectues sur les entits gres sont enregistres dans la base de donnes au moment dun commit Les modifications sont enregistres dans la base, mme si elles ont t effectues avant le dbut de la transaction (avant le tx.begin())

R. Grin

JPA

page 241

R. Grin

JPA

page 242

Synchronisation dun GE avec une transaction


Synchronisation dun GE avec une transaction : le GE est enregistr auprs de la transaction ; un commit de la transaction provoquera alors automatiquement un flush du GE (le GE est averti lors du commit) ; voir la dernire section de ce cours sur les diffrents types de transaction

Concurrence

R. Grin

JPA

page 243

R. Grin

JPA

page 244

GE et threads
Une fabrique de GE peut tre utilise sans problme par plusieurs threads Mais un GE ne doit tre utilis concurremment que par un seul thread

Entits et threads
Les entits ne sont pas prvues pour tre utilises par plusieurs threads en mme temps Si a doit tre le cas, lapplication doit prendre toutes ses prcautions pour viter les problmes Cest aussi le rle de lapplication dempcher quune entit ne soit gre par plusieurs GE en mme temps Le rle du fournisseur de persistance nintervient pas pour ces cas
R. Grin JPA page 246

R. Grin

JPA

page 245

41

Concurrence BD
Le fournisseur de persistance peut apporter automatiquement une aide pour viter les problmes daccs concurrents aux donnes de la BD, pour les entits gres par un GE

Exemple de problme de concurrence BD


Une entit est rcupre depuis la BD (par un find par exemple) Lentit est ensuite modifie par lapplication puis la transaction est valide Si une autre transaction a modifi entretemps les donnes de la BD correspondant lentit, la transaction doit tre invalide

R. Grin

JPA

page 247

R. Grin

JPA

page 248

Gestion de la concurrence
Par dfaut, le fournisseur de persistance gre les problmes daccs concurrents aux entits gres par un GE avec une stratgie optimiste

@version
Annote un attribut dont la valeur reprsentera un numro de version (incrment chaque modification) pour lentit et sera utilise pour savoir si ltat dune entit a t modifie entre 2 moments diffrents (stratgie optimiste) Lattribut doit tre de type int, Integer, short, Short, long, Long ou java.sql.TimeStamp (si possible, viter ce dernier type) Lapplication ne doit jamais modifier un tel attribut (modifi par JPA)
R. Grin JPA page 250

R. Grin

JPA

page 249

Exemple
@Version private int version;

Entit versionne
Cest une entit qui possde un attribut qui possde lannotation @version (ou le tag correspondant dans les fichiers XML)

R. Grin

JPA

page 251

R. Grin

JPA

page 252

42

lock(A, mode)
Sert protger une entit contre les accs concurrents pour les cas o la protection offerte par dfaut par le fournisseur ne suffit pas Cette entit doit tre versionne (sinon, le traitement nest pas portable)

Modes de blocage
Lnumration LockModeType (paquetage javax.persistence) dfinit 2 modes READ : les autres transactions peuvent lire lentit mais ne peuvent pas la modifier WRITE : comme READ, mais en plus lattribut de version est incrment, mme si lentit na pas t modifie (utilit explique dans les transparents suivants)

R. Grin

JPA

page 253

R. Grin

JPA

page 254

READ
Empche les lectures non rptables sur les donnes de la BD associes lentit Le fournisseur de persistance peut choisir une stratgie pessimiste (du type select for update ) ou optimiste

READ
Le blocage rel peut ntre effectu quau moment du flush ou du commit, quelle que soit lemplacement du read dans le code Java Sil y a un problme, une exception OptimisticLockException peut tre lance

R. Grin

JPA

page 255

R. Grin

JPA

page 256

Utilit des blocages READ


Un bilan qui calcule le total des salaires des employs pour chaque dpartement doit interdire quun employ ne change de dpartement pendant le traitement Tous les employs peuvent tre bloqus en mode READ pour viter ce problme

WRITE
vite en quelque sorte les problmes de lignes fantmes avec les associations qui concernent une entit En effet, le fournisseur de persistance incrmente automatiquement le numro de version si une entit est modifie mais pas si les liens des associations qui partent de lentit sont modifies

R. Grin

JPA

page 257

R. Grin

JPA

page 258

43

Utilit des blocages WRITE (1)


Une entte de facture contient un champ dans lequel est stock le total de la facture Supposons que le calcul de ce total est effectu par un processus part du processus de lajout des lignes de la facture Lorsquune ligne de facture est ajoute une facture, len-tte de la facture nest pas modifie donc le fournisseur de persistance nincrmente pas le numro de version de len-tte
R. Grin JPA page 259

Utilit des blocages WRITE (2)


Une ligne peut tre ajoute une facture sans que le traitement qui calcule le total ne sen rende compte ; il y aura inconsistance entre ce total et les lignes de la facture Si len-tte est bloque en criture pendant lajout dune ligne de facture, le traitement qui effectue le calcul du total sapercevra que la facture a chang pendant le calcul puisque le numro de version aura t incrment et il ny aura pas inconsistance
R. Grin JPA page 260

Niveau disolation
Le fournisseur suppose que le SGBD gre la base de donnes avec un niveau disolation READ COMMITED (voir cours sur les BD)

Entit dtache

R. Grin

JPA

page 261

R. Grin

JPA

page 262

Cas dutilisation
Le serveur dapplication rcupre des donnes dans la BD Ces donnes sont montres lutilisateur et celui-ci peut les modifier Les modification sont repasses au serveur et enregistres dans la BD Les entits dtaches facilitent limplmentation dun tel cas dutilisation

EJB 2.0
Dans la norme EJB 2.0, les donnes de la BD taient enregistres dans un objet EJB entit Le problme tait quun objet entit ne pouvait exister que dans lenvironnement du serveur dapplication Les donnes tait donc souvent passes au client sous forme de DTO (pour viter de nombreux appels distants aux EJB entits, qui sont coteux)
R. Grin JPA page 264

R. Grin

JPA

page 263

44

EJB 3.0
Plus ce problme dans la norme EJB 3.0 Les entits peuvent tre dtaches de leur contexte de persistance dorigine et rattaches par la suite

EJB 3.0
Une fois dtaches les entits peuvent tre passes sans problme la couche cliente Les modifications effectues par lutilisateur peuvent tre enregistres dans lentit dtache Lentit peut ensuite tre rattache un GE et les modifications sont alors enregistres dans la base de donnes

R. Grin

JPA

page 265

R. Grin

JPA

page 266

Rattachement
La mthode merge de EntityManager permet dobtenir une entit gre partir dune entit dtache Sa signature : <T> T merge(T entit) Attention, lentit passe en paramtre nest pas rattache ; cest lentit renvoye par la mthode merge qui est rattache ; cette entit a le mme tat et la mme cl primaire que lentit passe en paramtre
R. Grin JPA page 267

Exemples de dtachement
Un servlet peut dcider denregistrer des entits dans une session dutilisateur ; cette session peut tre srialise par un conteneur de servlet (et les entits sont alors dtaches) Une application peut viter lutilisation de DTO en transfrant les donnes entre les clients et le serveur dans des objets dtachs, vitant ainsi des recopies inutiles
R. Grin JPA page 268

tat dune entit dtache


Une entit dtache continue exister mais la synchronisation avec la BD nest pas garantie Ltat dune entit dtache peut ne pas tre entirement disponible

tat dune entit


En effet, pour des raisons de performances, une entit gre par un GE (attache) peut ne rcuprer dans la BD quune partie de son tat Le reste de ltat ne sera rcupr que lorsque lentit en aura vraiment besoin, avec laide du GE Si lentit est dtache alors quune partie de son tat na pas encore t rcupre, la partie manquante de lentit dtache ne sera pas disponible
R. Grin JPA page 270

R. Grin

JPA

page 269

45

tat dune entit


Un attribut persistant dune entit est immdiatement disponible dans les 2 cas suivants : n lattribut a dj t utilis n lattribut na pas t marqu par fetch=LAZY

tat dune entit dtache


Une entit peut donc ne pas tre totalement initialise au moment de son dtachement Par exemple, si une association dune entit dtache a lattribut fetch=LAZY, il est possible que lassociation ne puisse tre rcupre (dpend des circonstances et des fournisseurs de JPA) En ce cas, une fois dtache et loin du GE, la norme nassure pas que lentit puisse rcuprer ltat manquant
page 271 R. Grin JPA page 272

R. Grin

JPA

Mode de rcupration des associations


Si une association dun objet dtach a le mode de rcupration LAZY, il nest possible de naviguer travers cette association que si n lapplication a dj effectu cette navigation n ou si lassociation a t charge par un join fetch lors dune requte

Rendre accessible ltat dune entit dtache


2 solutions pour accder tout ltat dune entit dtache Lapplication rcupre tout ltat de lentit gre avant le dtachement Lapplication rattache lentit par la mthode merge pour rcuprer ltat manquant

R. Grin

JPA

page 273

R. Grin

JPA

page 274

Rcuprer une association avant le dtachement


Si le but est une entit (OneToOne ou ManyToOne), il suffit de lire une des proprits de lentit Si le but est une collection (OneToMany ou ManyToMany), lappel de la mthode size() de la collection suffit le plus souvent

Entit dtache et concurrence


Avant que les modifications sur lentit dtache ne soient enregistres dans la BD, lentit doit tre rattache un contexte de persistance (celui dorigine ou un autre) A ce moment, ou au moment du commit qui enregistre vraiment les modifications, le contexte de persistance vrifie quil ny a pas de conflit de concurrence

R. Grin

JPA

page 275

R. Grin

JPA

page 276

46

Conflit de concurrence
Si les donnes de la BD associe un objet dtach ont t modifies depuis le dtachement de lobjet, merge lance une exception, ou le commit chouera Tout se passe donc comme si un conflit de concurrence avait t dtect (avec une stratgie optimiste)

Dtachement automatique
Quelques situations provoquent un dtachement automatique des entits gres : n Aprs un commit si le contexte de persistance est limit la transaction (avec un serveur dapplications) n Aprs un rollback n Aprs un clear du GE n Aprs la fermeture du GE n Aprs le passage par valeur de lentit avec une mthode remote
R. Grin JPA page 278

R. Grin

JPA

page 277

Associations
X entit dtache ; association entre X et Y Ltat de Y peut tre disponible dans ces cas : n Y a t retrouv par find Y a t retrouve par une requte avec une clause join fetch n une proprit de Y non cl primaire a dj t accde par lapplication n Y est navigable depuis une entit disponible avec lassociation marque fetch=EAGER
n
R. Grin JPA page 279 R. Grin

Optimisations

JPA

page 280

Les performances dune application peuvent tre grandement amliores par n un choix adapt du mode de rcupration des entits associes n lutilisation doprations de modifications de grandes quantits de donnes sans cration dentits

Callback

R. Grin

JPA

page 281

R. Grin

JPA

page 282

47

Mthodes callback
Des mthodes peuvent tre annotes pour indiquer quelles seront appeles par le fournisseur de persistance quand une entit passera dans une nouvelle tape de son cycle de vie Ces mthodes peuvent appartenir une classe entit (entity ou classe mre mapped ) ou une classe couteur

Types de mthode
@PrePersist : quand persist (ou merge) sest termin avec succs @PostPersist : aprs linsertion dans la BD @PreRemove : quand remove est appel @PostRemove : aprs suppression dans la BD @PreUpdate : avant modification dans la BD @PostUpdate : aprs modification dans la BD @PostLoad : aprs la lecture des donnes de la BD pour construire une entit
R. Grin JPA page 284

R. Grin

JPA

page 283

Fichier XML
Les mthodes callback peuvent aussi tre indiques dans un fichier XML Un fichier XML peut indiquer des mthodes callback par dfaut qui seront appeles pour toutes les entits

Configuration dune unit de persistance

R. Grin

JPA

page 285

R. Grin

JPA

page 286

Configuration dune unit de persistance


Dans un environnent non gr par un serveur dapplications, il est ncessaire de donner les informations pour la connexion la base de donnes Ces informations, ainsi que dautres informations, comme les noms des classes entits, doivent tre donnes dans un fichier persistence.xml situ dans un sousrpertoire META-INF dun des rpertoires du classpath
R. Grin JPA page 287

Configuration dune unit de persistance


Les informations indiquent comment se connecter la base de donnes, ainsi que dautres informations, comme les noms des classes entits, la configuration de lenvironnement de mis au point (logging, affichage des ordres SQL lancs dans le SGBD,) ou des proprits particulires au driver du fournisseur de persistance

R. Grin

JPA

page 288

48

persistence.xml
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version= "1.0" > <persistence-unit name="Employes" transaction-type="RESOURCE_LOCAL"> <class>p1.Employe</class> <class>p1.Dept</class> <properties> . . . <! Voir transparent suivant--> </properties> </persistence-unit> </persistence>
R. Grin JPA page 289

Section properties
La section properties dpend du fournisseur des fonctionnalits dcrites dans la spcification JPA Elle contient les informations pour la connexion mais aussi dautres informations pour le logging ou la cration automatique des tables si elle nexistent pas dj ; il faut consulter la documentation du fournisseur

R. Grin

JPA

page 290

Exemple de section properties


<properties> <property name="toplink.jdbc.driver" value="oracle.jdbc.OracleDriver"/> <property name="toplink.jdbc.url" value="jdbc:oracle:thin:@...:INFO "/> <property name="toplink.jdbc.user" value="toto"/> <property name="toplink.jdbc.password" value="mdp"/> </properties>
R. Grin JPA page 291

Les ajouts de TopLink


TopLink a des extensions par rapport la norme JPA Par exemple, n logging n gnration automatique de tables n

R. Grin

JPA

page 292

Gnration automatique des tables


La proprit toplink.ddl-generation permet de crer automatiquement les tables au moment de lexcution Cette proprit peut avoir 3 valeurs : n none : aucune cration automatique n create-tables : les tables sont cres si elles nexistent pas dj n drop-and-create-tables : si une table existe dj, elle est dabord supprime avant dtre recre (utile pour les tests)
R. Grin JPA page 293

Exemple
<properties> . . . <property name="toplink.ddl-generation" value="drop-and-create-tables"/> </properties>

R. Grin

JPA

page 294

49

toplink.ddl-generation.output-mode indique ce qui sera fait avec les fichiers DDL Valeurs possibles : n sql-script gnre les fichiers mais ne les excute pas n database excute les ordres DDL mais ne gnre pas les fichiers n both gnre les fichiers et les excute (valeur par dfaut)
R. Grin JPA page 295

Proprit toplink.applicationlocation indique le nom du rpertoire qui contiendra les fichiers contenant les ordres DDL de cration et de suppression des tables (le rpertoire courant par dfaut)

R. Grin

JPA

page 296

logging (1)
toplink.create-ddl-jdbc-file-name indique le nom du fichier qui contiendra les ordres de cration des tables ; par dfaut, createDDL.jdbc toplink.drop-ddl-jdbc-file-name idem pour la suppression des tables ; par dfaut, dropDDL.jdbc La proprit toplink.logging.level peut avoir les valeurs n OFF : aucune information n SEVERE : uniquement les erreurs n WARNING : les avertissements (et les erreurs) n INFO (valeur par dfaut) : assez peu
dinformation en plus
n

CONFIG : donne des informations au moment du


dploiement sur la configuration

R. Grin

JPA

page 297

R. Grin

JPA

page 298

logging (2)
n

FINE : donne des informations sur les ordres


SQL utile pendant les tests et la mise au point

FINER : encore plus dinformations, par exemple


sur les transactions

Fichiers XML

FINEST : encore plus dinformations, par


exemple sur lutilisation des squences

R. Grin

JPA

page 299

R. Grin

JPA

page 300

50

Placement des fichiers XML


Par dfaut les fichiers XML contenant les mta donnes sont places dans le fichier META-INF/orm.xml, sous un rpertoire du classpath Il est possible dindiquer dautres emplacements avec le tag <mapping-file> dans le fichier persistence.xml qui dfinit lunit de persistance

Exemple
<persistence-unit name="xxxx"> ... <mapping-file>META-INF/queries.xml </mapping-file> <mapping-file>META-INF/entities.xml </mapping-file> </persistence-unit>

R. Grin

JPA

page 301

R. Grin

JPA

page 302

Fichiers XML annotations


Avantages des annotations : n mta donnes proches du code n pas besoin de donner le contexte comme dans les fichiers XML n plus simple Inconvnients : n changement des mta donnes ncessite une recompilation Les informations donnes dans les fichiers XML lemportent sur les annotations
R. Grin JPA page 303

Fichiers XML annotations


Les annotations sont le plus souvent utilises Les fichiers de configuration XML peuvent tre prfrs lorsque linformation n est dpendante de lenvironnement dexcution ; par exemple pour les noms de tables ou de colonnes n concerne plusieurs classes ; par exemple @TableGenerator qui donne le nom de la table qui gnre automatiquement les cls didentification des entits
R. Grin JPA page 304

La fin de ce support concerne les serveurs dapplication et nest donne qu titre de rfrence pour ceux qui utiliseront un tel serveur Le contenu ne fait pas partie du programme demand lexamen

JPA dans les serveurs dapplications

R. Grin

JPA

page 305

R. Grin

JPA

page 306

51

Types de GE (1)
GE gr par le container (uniquement disponible dans un serveur dapplications) GE gr par lapplication (seul type disponible en dehors dun serveur dapplications) ; pas dlimit par les transactions

Types de gestionnaires dentits

R. Grin

JPA

page 307

R. Grin

JPA

page 308

Types de GE (2)
Un GE gr par le container peut tre d'un des 2 types suivants : n dlimit par les transactions (TRANSACTION ; c'est le type par dfaut) n peut survivre une fin de transaction (EXTENDED) ; ncessite un bean session avec tat (stateful)

GE gr par le container
Le contexte de persistance est inject par le serveur dapplication :
@PersistenceContext(unitName="Xxxxx")

Avec un serveur dapplications, par dfaut la dure de vie dun contexte de persistance est la transaction : il est ferm quand la transaction se termine

R. Grin

JPA

page 309

R. Grin

JPA

page 310

GE gr par le container (2)


Il est possible de faire durer un contexte de persistance pendant plusieurs transactions Pour cela il faut crer un contexte de persistance tendu :
@PersistenceContext(unitName="Xxxxx" type=PersistenceContextType=EXTENDED)

GE gr par le container (3)


Lapplication peut grer elle-mme la cration dun GE en utilisant une fabrique de GE (mthode createEntityManager()) La fabrique de gestionnaires dentits sobtient par injection de ressource (fournie par le serveur dapplications) : @PersistenceUnit EntityManagerFactory emf;

Ce type de GE nest disponible que dans un bean session avec tat (stateful) ; il nest pas disponible dans un bean session sans tat (stateless)
R. Grin JPA page 311

R. Grin

JPA

page 312

52

Contexte de persistance de porte limite une transaction


Dans le cas dun contexte de persistance de porte limite une transaction (pas le cas si application en dehors dun container), n persist, merge, remove et refresh doivent tre invoques dans le contexte dune transaction n find et getReference (comme les rsultats de lexcution dun Query) peuvent tre invoqus en dehors du contexte dune transaction mais dans ce cas les entits renvoyes sont dtaches
R. Grin JPA page 313

Transactions
Une requte peut tre lance en dehors de toute transaction Dans le cas o le contexte de persistance est limit une transaction, les entits seront dtaches (non gres par un GE)

R. Grin

JPA

page 314

Transactions disponibles dans Java EE


Les serveurs dapplications utilisent par dfaut les transactions JTA, mais les transactions locales une ressource (celles qui utilisent l'API de JDBC pour les transactions) sont aussi disponibles Les transactions sont gres par le container du serveur dapplication ou par lapplication Seules les transactions JTA peuvent tre gres par le container
page 315 R. Grin JPA page 316

Types de transactions

R. Grin

JPA

Dmarcation des transactions dans Java EE


Transactions JTA gres par le serveur dapplication : les transactions sont dmarres (ou non) au dbut dune mthode et termines (ou non) la fin dune mthode, suivant les indications donnes par le dveloppeur par annotation ou dans un fichier XML Transactions gres par lapplication : lapplication dcide de dmarrer et de terminer une transaction nimporte o dans le code
R. Grin JPA page 317

Transactions gres par lapplication disponibles dans Java EE


Le code utilise linterface javax.transaction.UserTransaction qui possde des mthodes pour dmarrer, terminer ou marquer pour invalidation une transaction JTA Une instance de UserTransaction peut tre injecte par une annotation @Resource

R. Grin

JPA

page 318

53

Environnement par dfaut dans un serveur dapplications


Contexte de persistance gr par le container (inject par annotation ou par lookup JNDI) Contexte de persistance limit une seule transaction Transaction JTA dont les dmarcations sont fixes dclarativement (par annotation ou dans un fichier XML)

Un principe
Pour que tout se passe bien, tous les appels de mthodes des GE durant une mme transaction doivent utiliser le mme contexte de persistance Sinon, des modifications effectues sur des entits durant la transaction risquent dtre perdues par la suite dans la transaction JPA facilite l'application de ce principe (voir transparent suivant)
R. Grin JPA page 320

R. Grin

JPA

page 319

Modle de conception dans Java EE


La configuration par dfaut correspond au modle de conception une transaction par requte de lutilisateur : n la transaction dmarre au dbut du traitement dune requte n et elle se termine la fin du traitement Pour faciliter lutilisation de ce modle, le contexte de persistance peut se propager aux mthodes appeles durant toute la dure dune transaction (dtaill plus loin)
R. Grin JPA page 321

Autre modle de conception


Avec un bean session avec tat (stateful) il est possible dutiliser un mme contexte de persistance tendue pour plusieurs transactions JTA Le modle de conception correspond des traitements conversationnels qui peuvent couvrir plusieurs requtes de lutilisateur

R. Grin

JPA

page 322

Propagation de contexte
Pour faciliter la tche du dveloppeur, les transactions JTA permettent la propagation de contexte pour les GE grs par le container Cette propagation de contexte peut occasionner des collisions de contexte dans certaines situations dans lesquelles des beans sessions avec tat sont impliqus Lhritage de contexte limite les possibilits de conflit
R. Grin JPA page 323

Dfinition
Association dun contexte de persistance avec une transaction JTA : le contexte de persistance est li la transaction ; le contexte devient le contexte actif li la transaction Cette association va permettre au container de retrouver un contexte de persistance en interrogeant la transaction, et donc de permettre la propagation de contexte
R. Grin JPA page 324

54

Dfinition
Un contexte de persistance peut tre propag durant une transaction JTA sil est utilis par des GEs grs par le container Ce contexte est alors utilis tour de rle durant la transaction par les GEs Cette propagation sappelle une propagation de contexte Quand un GE reoit un message, il vrifie sil existe un contexte propag ; si cest le cas, il utilise celui-ci, sinon il en cre un nouveau
R. Grin JPA page 325

Avantage de la propagation
Les modifications non encore enregistres dans la base (elles le seront seulement au commit de la transaction), mais enregistres dans le contexte de persistance, sont disponibles durant toute la transaction, quel que soit lemplacement du code plac dans la transaction

R. Grin

JPA

page 326

Conflit de contextes
La propagation de contexte ne fonctionne pas lors de lappel dune mthode dun bean session avec tat (stateful) depuis un autre bean En effet, une bean session avec tat ne peut travailler quavec un seul contexte et ne peut accepter de travailler avec un autre contexte propag Une exception est leve Voir la spcification JPA pour plus de dtails
R. Grin JPA page 327

Hritage de contexte
Une exception pour la collision de contexte : un bean avec tat cr par un autre bean avec tat hrite du contexte de ce bean si les 2 beans utilisent un contexte de persistance tendu Ainsi des appels de mthodes pourront se faire entre les 2 beans sans collision de contexte

R. Grin

JPA

page 328

Synchronisation
Il est possible de synchroniser plusieurs contextes de persistance grs par lapplication avec une mme transaction JTA Mais un seul contexte gr par le container peut tre synchronis avec une transaction JTA

Conversation longue (1)


L'utilisation d'un contexte tendu permet d'implmenter des conversations longues entre un client et un bean session avec tat Il n'est pas indispensable, et souvent nfaste, qu'une seule transaction longue couvre toute la conversation

R. Grin

JPA

page 329

R. Grin

JPA

page 330

55

Conversation longue (2)


On peut commencer par une transaction, valider la transaction, passer des donnes au client qui les modifie et ensuite reprendre une autre transaction pour terminer la conversation Ds que la 2me transaction dmarre, toutes les modifications faites entre les 2 transactions sont prises en compte par cette 2me transaction

joinTransaction
Lorsquun GE est cr explicitement par lapplication (il nest pas gr par le container), 2 cas : n si une transaction JTA est dj active, le contexte du GE est synchronis avec la transaction n sinon le contexte peut manuellement tre synchronis avec la transaction par la mthode joinTransaction() de EntityManager
R. Grin JPA page 332

R. Grin

JPA

page 331

Sites Web (1)


Spcification officielle de JPA :
http://jcp.org/aboutJava/communityprocess/final /jsr220/index.html (cliquer sur le 1er bouton download the Specification for evaluation or to build an application that uses the Specification

Bibliographie

Toplink :
http://www.oracle.com/technology/products/ias/t oplink/jpa/index.html

R. Grin

JPA

page 333

R. Grin

JPA

page 334

Sites Web (2)


Hibernate :
http://www.hibernate.org/hib_docs/entitymanag er/reference/en/html/

Livre
Pro EJB 3 JPA de Mike Keith et Merrick Schincariol Edition Apress (en anglais)

Kodo :
http://edocs.bea.com/kodo/docs40/full/html/ejb3_overvi ew.html

R. Grin

JPA

page 335

R. Grin

JPA

page 336

56

Вам также может понравиться