Title: Chapitre 2 Persistance de donn
1Chapitre 2Persistance de données De
Hibernate au standard JPA 1.0
2Sommaire
- Stratégies d'accès aux données
- Principes du mappage Objet/Relationnel
- Le Framework Hibernate 3
- La JPA 1.0 (Java Persistance API)
- Synthèse comparative
3Critères de choix de la stratégie de persistance
- Les critères de choix sont
- La performance
- La portabilité
- L'indépendance vis à vis des bases de données
- Prise en compte des relations
- Facilités de développement
- Technique de Caching
- Le modèle de persistance (O/R mapping)
- Migration
4Stratégies de persistance
- JDBC plat avec objets ADO
- Framework de persistance du type
Hibernate/JDO/Castor - EJB Entity
- Avec persistance CMP
- Avec persistance BMP
- EJB Session avec JDBC
5La persistance des objet
- La persistance dobjets désigne le fait que des
objets individuels peuvent survivre au processus
de lapplication. - Ils peuvent être enregistrés dans un entrepôt de
données et récupérés par la suite. - Le mappage Objet/Relationnel (ORM) désigne la
persistance automatisée et transparente dobjets
dans une application Java vers les tables dune
base de données relationnelle à laide des méta
données décrivant le mapping entre les objets et
la base de données.
6Gestion de la correspondance objet/relationnel
- 30 du code java est consacré à gérer la mise en
rapport SQL/JDBC et la non correspondance entre
le modèle objet et le modèle relationnel - Gestion des associations
- Correspondances de types
- Granularité
- Les outils et frameworks ORM réduisent
grandement le code qui permet cette
correspondance et facilitent donc les adaptations
mutuelles des deux modèles.
7ORM( Object Relationnel Mapping)
- Cest une technique de mapping dune
représentation des données dun modèle objet vers
un modèle relationnel de base de données et
inversement. - Quatre éléments constituant une solution ORM
- Une API pour effectuer les opérations CRUD
(Create, Read, Update, delete) de base sur les
objets des classes persistantes. - Un langage ou une API pour spécifier des requêtes
qui se réfèrent aux classes et aux propriétés des
classes. - Un système pour spécifier des métadonnées de
mapping. - Une technique pour limplémentation du mapping
objet/relationnel permettant dinteragir avec des
objets transactionnels pour effectuer des
vérifications brutes, rechercher des associations
lâches et implémenter dautres fonctions
doptimisation.
8ORM( Object Relationnel Mapping)
- Productivité
- Réduction sensiblement le temps de développement.
- Maintenabilité
- Utilisation dun tampon entre les deux modèles
pour isoler les modifications mineurs de chaque
modèle. - Performance
- Utilisation dun grand nombre doptimisation.
9Solution ORM Hibernate
- Un framework Java de persistance
- Permet de faire la correspondence des tables de
base de données relationnelle avec des objets
java simples (POJO ou Plain Old Java Object). - Une fois la correspondance entre les deux mondes
définie, le programme Java peut manipuler toutes
les données en utilisant que des JavaBean,
masquant totalement la base de données
sous-jacente et ses spécificités. - Le framework assure le remplissage de ces objets
et la mise à jour de la base en se basant sur
leur contenu. - XML constitue le format de description de la
correspondance entre les tables relationnelles et
les classes Java.
10Historique de Hibernate
- Novembre 2001 fondé par Gavin King.
- Juin 2003 hibernate 2.0 solution complète
dORM. - Août 2003 Intérêt du monde de lentreprise
grandissant. - Octobre 2003 Hibernate rejoint JBoss.
- Juin 2004 Premier brouillon de la spec EJB3
inspiré fortement dHibernate. - Octobre 2005 NHibernate rejoint JBoss.
- Décembre 2005 Hibernate 3.1.
11Hibernate Architecture
- Hibernate utilise des API Java existantes dont
JDBC, JTA (Java Transaction API) et JNDI (Java
Naming and Dictory Interface). - JDBC fournit un niveau rudimentaire dabstraction
des fonctionnalités communes aux bases de données
relationnelles, ce qui permet à pratiquement
toutes les bases de données dotées dun pilote
JDBC dêtre supportées par Hibernate. JNDI et JTA
permettent à Hibernate dêtre intégré avec des
serveurs dapplications J2EE.
Architecture multicouches dHibernate
extrait du livre
Hibernate de
Gavin King et Christian Bauer.
12Hibernate Interfaces centrales
- Grâce à ces interfaces, on peut stocker et
récupérer des objets persistants et contrôler des
transactions. - Interface Session
- Linterface Session est linterface principale
utilisée pour les applications Hibernate. Les
instances de session sont légères et peu
coûteuses à créer et à détruire. - Cest un objet mono-threadé, à durée de vie
courte, qui représente une conversation entre
l'application et l'entrepôt de persistance. - Linterface session est quelquefois appelée
gestionnaire de persistance car il sagit
également dune interface pour les opérations
liées à la persistance comme le stockage et la
récupération des objets. - SessionFactory
- Lapplication obtient des instances Session à
partir dune SessionFactory. - La sessionFactory est loin dêtre légère. Elle
est destinée à être partagée par de nombreux
thread dapplication. Il y a en général une
unique SessionFactory pour lapplication entière.
13Hibernate Interfaces centrales
- Interface configuration
- Lobjet Configuration est utilisé pour configurer
et amorcer Hibernate. Lapplication utilise une
instance configuration pour spécifier
lemplacement de mapping et de propriétés
spécifiques à Hibernate, puis pour créer la
SessionFactory. - Interfaces Query et Criteria
- Linterface Query permet de faire porter des
requêtes sur la base de données et de contrôler
la manière dont la requête est exécutée . - Une instance Query est utilisée pour lier les
paramètres de requête, limiter le nombre de
résultats retournés et enfin exécuter la requête.
- Les instances Query sont légères et ne peuvent
pas être utilisées en dehors de la Session qui
les a crées. - Linterface Creteria est très similaire, elle
permet de créer et dexécuter des requêtes par
critères orientés objet.
14Hibernate Interfaces centrales
- Interface Transaction
- Linterface Transaction est une API optionnelle.
- Cest un objet mono-threadé à vie courte utilisé
par l'application pour définir une unité de
travail. - Elle abstrait le code de l'application de
limplémentation sous-jacentes gérant les
transactions qu'elles soient JDBC, JTA ou CORBA. - Une Session peut fournir plusieurs Transactions
dans certains cas.
15Configuration de Hibernate
- La configuration dHibernate consiste à ajuster
un certains nombre de paramètres qui permettent
doptimiser le comportement à lexécution
dHibernate. - Il y a trois méthodes qui permettent de
configurer Hibernate - En utilisant un fichier hibernate.properties.
- En utilisant une instance java.util.properties de
manière programmatique. - En utilisant un fichier de configuration XML.
16Hibernate hibernate.properties
- Exemple de fichier hibernate.properties pour une
source de données fournie par conteneur
le nom JNDI de la source de données.
Hibernate.connection.datasource
java/comp/env/jdbc/actionDB Hibernate.transacti
on.factory-class\net.sf.hibernate.transaction. JT
ATransactionFactory Hibernate.transaction.manage
r_lookup_class \net.sf.hibernate. transaction.JBO
SSTransactionManagerLookup Hibernate.dialect
net.sf.hibernate.dialect.PostgreSQLDialect
Activation de lintégration avec JTA
Localisation duTransactionManager
Utilisation du dialect SQL
17Hibernate hibernate.cfg.xml
- Un fichier de configuration XML peut être utilisé
pour configurer entièrement une SessionFactory. - A la différence de hibernate.properties qui ne
contient que des paramètres de configuration, le
fichier hibernate.cfg.xml peut également
spécifier lemplacement des documents de mapping.
Configuration cfgnew configuration() Cfg.addRess
ouce( essai/exple.hbm.xml ) Cfg.setProperties(S
ystem.getProperties()) SessionFactory
sessionscfg.buildSessionFactory()
18Hibernate hibernate.cfg.xml
lt?xml version1.0 encodingutf-8?gt lt!DOCTYPE
hibernate-configuration PUBLIC "-Hibernate/Hiberna
te Configuration DTD//EN " " http//hibernate.sour
ceforge.net/hibernate-configuration-2.0.dtdgt lthibe
rnate-configurationgt ltSession-factory name"
java/hibernate/HibernateFactory "gt ltproperty
name" show_sql "gttruelt/propertygt ltproperty
name"connection.datasource "gt Java/comp/env/jd
bc/ActionDB lt/propertygt ltproperty name"
dialect "gt Net.sf.hibernate.dialect.PostgreSQLDi
alect lt/propertygt ltproperty name"
transaction.manager_look_class"gt Net.sf.hibernate
.transaction.JBossTransactionManagerLookup
lt/propertygt ltmapping ressource"
auction/Item.hbm.xml"/gt ltmapping ressource"
auction/Category.hbm.xml"/gt ltmapping ressource"
auction/Bid.hbm.xml"/gt lt/session-factorygt lt/hibern
ate-configurationgt
Type de document
Lattribut name
Les propriétés Hibernate
Documents de mapping
19Hibernate hibernate.cfg.xml
- La déclaration du type de document est utilisée
par le parseur XML pour valider ce document
daprès la DTD de configuration dHibernate. - Lattribut facultatif name équivaut à la
propriété hibernate.session_factory_name. Il est
utilisé pour la liaison JNDI de la
SessionFactory. - Les propriétés Hibernate peuvent être spécifiées
sans le préfixe hibernate. Les noms et les
valeurs de propriétés sont identiques aux
propriétés de la configuration programmatique. - Les documents de mapping peuvent être spécifiés
en tant que ressources dapplication
20Hibernate hibernate.cfg.xml
- A présent Hibernate est prêt à être initialiser
en utilisant - Mais, comment Hibernate savait-il où le fichier
de configuration se trouvait? - Lorsque configure( ) est appelé, Hibernate
cherche un fichier nommé Hibernate.cfg.xml dans
le CLASSPATH. Si on souhaite utiliser un nom de
fichier différent ou placer ce fichier de
configuration dans un sous-repertoire, on na
quajouter un chemin à la méthode configure( )
SessionFactory sessionsnew configuration( )
.configure( ).buildSessionFactory( )
SessionFactory sessionsnew configuration( )
.configure( /hibernate-config/auctio
n.cfg.xml) .buildSessionFactory( )
21Langage de requête dHibernate HQL
- Fonctionnalités
- La capacité à appliquer des restrictions aux
propriétés dobjets associés liés par référence. - La capacité à trier les résultats de la requête
- La capacité à paginer les résultats
- Lagrégation avec group by, having et des
fonctions dagrégation comme sum, min et max. - Les jointures externes lors de la récupération de
plusieurs objets par ligne
22Langage de requête dHibernate HQL
- La capacité à appeler des fonctions SQL définies
par lutilisateur. - Les sous requêtes (requêtes imbriqués).
- HQL est moins verbeux et plus lisible que la
requête avec SQL. - Exemple de requête avec SQL
- Le même en HQL
23Hibernate SQL natif
- L'un des objectifs d'Hibernate est de s'éloigner
de la base de données. Or, l'utilisation du SQL
natif va à l'encontre de cet objectif. De ce
point de vue, le SQL natif est à éviter. - Néanmoins, l'équipe du projet le conseille
seulement de façon exceptionnelle pour des points
qui ont besoin d'utiliser une optimisation
spécifique à la base de données. - Cette fonctionnalité offre un moyen de migration
plus propre d'une application basée sur SQL/JDBC
vers une application Hibernate.
24 25Un peu dhistoire
- Entity Beans EJB 1.0 -gt 2.1
- Complexité
- La courbe dapprentissage trop prononcée
- Modèle de programmation non-intuitif
- Performance
- Le coût pour effectuer certaines requêtes était
hors de proportions, le cycle de vie du container
devenait un boulet
26Un peu dhistoire
- Les équipes IT se sont de plus en plus tourné
vers dautres produits sur le marché - Hibernate
- Le plus répandu dans la communauté présentement.
Toutefois, la responsabilité de compatibilité
avec différents serveurs dapplication revient à
la communauté. - JDO
- Bien que JDO soit un standard, appuyé par la JSR
243 (JDO 2.0), cette technologie a reçu bien peu
dappui. - Produits commerciaux (ex. TopLink)
- API propriétaires, onéreux, non-standard
- Ces trois solutions fonctionnent globalement
suivant les mêmes principes - Des fichiers de mapping pour faire correspondre
les tables aux classes java - Des beans Java simples correspondant aux objets
métiers ceux sont ces beans que manipule le
développeur - Une API de persistance qui permet de rendre
persistant en base les beans métiers. On retrouve
généralement les mêmes verbes (insert, update,
delete, get) - Un langage de requêtes proche du SQL mais
manipulant les propriétés des beans.
27Les besoins
- Clairement, 2 grands besoins se dégagèrent,
répondant à lindustrie et aux développeurs - Avoir une API simple dutilisation, attrayante
pour les développeurs, appliquant les techniques
apprises des cadres dapplications de la
communauté open source. - Avoir un standard respecté par les fournisseurs
de serveurs dapplications.
28L'orientation EJB 3.0
- Les spécifications des EJB 3.0 Entité et de Java
Persistence API (JPA) reprennent les grands
mécanismes des solutions de mapping
relationnel/objet. - Les différents fournisseurs ont décliné leur
offre afin dintégrer les spécifications des EJB
3.0 Entité et JPA - Hibernate supporte les annotations EJB 3.0 et JPA
Hibernate 3.2 peut être utilisé comme avant, ou
bien servir dimplémentation aux EJB 3.0. - Toplink est limplémentation des EJB 3.0 Entité
pour la solution Oracle - On assiste donc semble-t-il à la fin du
casse-tête du choix darchitecture de la couche
de persistance dans le monde Java nous avons
une interface normée qui est supporté par les
acteurs principaux et qui repose sur des
solutions et concepts déjà éprouvés.
29Présentation de JPA
- JPA est un standard pour la persistance des
objets Java - L'API JPA est récente. Elle n'a été disponible
qu'à partir du JDK 1.6. - L'API de persistance est accessible en utilisant
le paquetage Java javax.persistence. - La spécification JPA a été implémentée par les
deux produits Toplink et Hibernate.
30Mapping Objet Relationnel
- La communication entre les mondes objet et
relationnel suppose une transformation pour
adapter la structure des données relationnelles
au modèle objet.
31Fichier de configuration
Fichier de configuration
- Un seul fichier de configuration XML
- Il est nécessaire dindiquer au fournisseur de
persistance comment il peut se connecter à la
base de données - Ce fichier peut aussi comporter dautres
informations
32Fichier de configuration
Déclaration du lunité persistante
ltpersistence ltpersistence-unit name"ExpoJPA"gt
ltprovidergt oracle.toplink.essentia
ls.PersistenceProvider lt/providergt
ltmapping-filegt META-INF/orm.xml
lt/mapping-filegt ltclassgt com.expose.jpa.Pers
onne lt/classgt ltpropertiesgt
ltproperty name"toplink.jdbc.drive
r value"com.mysql.jdbc.Driver" gt
lt/propertygt ltproperty
name"toplink.jdbc.url value"jdbcmysql//local
host3306/expojpa"gt lt/propertygt
ltproperty name"toplink.jdbc.user"
value"root"gt lt/propertygt
lt/propertiesgt lt/persistence-unitgt lt/persistencegt
configurent la liaison JDBC avec la base de
données
33Les Entités
- Les classes dont les instances peuvent être
persistantes sont appelées des entités dans la
spécification de JPA - Le développeur indique quune classe est une
entité en lui associant lannotation _at_Entity - Il faut importer javax.Persistence.Entity dans
les classes entités.
34Cycle de vie dune entité
35Classes entités Entity Class
- Une classe entité doit posséder un attribut qui
représente la clé primaire dans la BD (_at_Id) - Elle doit avoir un constructeur sans paramètre
protected ou public - Elle ne doit pas être final
- Aucune méthode ou champ persistant ne doit être
final - Une entité peut être une classe abstraite mais
elle ne peut pas être une interface
36Classes entités Embedded Class
- Il existe des classes incorporées (embedded) dont
les données nont pas didentité dans la BD mais
sont insérées dans une des tables associées à une
entité persistante - Par exemple, une classe Adresse dont les valeurs
sont insérées dans la table Employe
37EntityManager
- Classe javax.persistence.EntityManager
- Le gestionnaire dentités est linterlocuteur
principal pour le développeur. - Il fournit les méthodes pour gérer les entités
- les rendre persistantes,
- les supprimer de la base de données,
- retrouver leurs valeurs dans la base,
- etc.
38Cycle de vie dun EntityManager
- La méthode createEntityManager() de la classe
EntityManagerFactory créé un Entity Manager - LEntity Manager est supprimé avec la méthode
close() de la classe EntityManager, il ne sera
plus possible de lutiliser ensuite.
39Fabrique de lEntityManager
- La classe Persistence permet dobtenir une
fabrique de gestionnaire dentités par la méthode
createEntityManagerFactory - 2 variantes surchargées de cette méthode
- 1 seul paramètre qui donne le nom de lunité de
persistance (définie dans le fichier
persistence.xml) - Un 2ème paramètre de type Map qui contient des
valeurs qui vont écraser les propriétés par
défaut contenues dans persistence.xml
40Méthodes de EntityManager
- void flush()
- Toutes les modifications effectuées sur les
entités du contexte de persistance gérées par
lEntityManager sont enregistrées dans la BD lors
dun flush du GE - Au moment du flush, lEntityMnager étudie ce
quil doit faire pour chacune des entités quil
gère et il lance les commandes SQL adaptées pour
modifier la base de données (INSERT, UPDATE ou
DELETE) - void persist(Object entité)
- Une entité nouvelle devient une entité gérée,
létat de lentité sera sauvegardé dans la BD au
prochain flush ou commit - void remove(Object entité)
- Une entité gérée devient supprimée, les données
correspondantes seront supprimées de la BD
41Méthodes de EntityManager
- void lock(Object entité, LockModeType lockMode)
- Le fournisseur de persistance gère les accès
concurrents aux données de la BD représentées par
les entités avec une stratégie optimiste, lock
permet de modifier la manière de gérer les accès
concurrents à une entité - void refresh(Object entité)
- LEntityManager peut synchroniser avec la BD une
entité quil gère en rafraichissant son état en
mémoire avec les données actuellement dans la BD.
- Utiliser cette méthode pour sassurer que
lentité a les mêmes données que la BD - ltTgt T find(ClassltTgt classeEntité,Object
cléPrimaire) - La recherche est polymorphe l'entité récupérée
peut être de la classe passée en paramètre ou
d'une sous-classe (renvoie null si aucune entité
na lidentificateur passé en paramètre)
42Relations
- 4 types de relations à définir entre les entités
de la JPA - One to One
- Many to One
- One to Many
- Many to Many
43Relationship Many to One
_at_Entity
_at_Entity
_at_Table(name"EMP")
public class Department private int id
private String dname // getters setters
...
public class Employee private int id
private Department d // getters
setters ...
_at_Id
_at_Id
_at_ManyToOne
_at_JoinColumn(name"DEPT_ID")
EMP
DEPARTMENT
DEPT_ID
ID
DNAME
ID
FK
PK
PK
44Relationship One to Many
_at_Entity
_at_Entity
_at_Table(name"EMP")
public class Department private int id
private String dname private
CollectionltEmployeegt emps // getters
setters ...
public class Employee private int id
private Department d // getters
setters ...
_at_Id
_at_Id
_at_ManyToOne
_at_OneToMany(mappedBy"d")
_at_JoinColumn(name"DEPT_ID")
EMP
DEPARTMENT
DEPT_ID
ID
DNAME
ID
FK
PK
PK
45Relationships One to One
_at_Entity
_at_Entity
_at_Table(name"EMP")
public class ParkingSpace private int id
private int lot private String location
private Employee emp // getters setters
...
public class Employee private int id
private ParkingSpace space // getters
setters ...
_at_Id
_at_Id
_at_OneToOne
_at_JoinColumn(name"P_SPACE")
_at_OneToOne(mappedBy"space")
EMP
PARKINGSPACE
P_SPACE
ID
LOCATION
LOT
ID
FK
PK
PK
46Relationships Many to Many
_at_Entity
_at_Entity
_at_Table(name"EMP")
public class Project private int id
private String name private
CollectionltEmployeegt e // getters setters
...
public class Employee private int id
private CollectionltProjectgt p
_at_Id
_at_Id
_at_ManyToMany(mappedBy"p")
_at_JoinTable(name"EMP_PROJ", joinColumns
_at_JoinColumn(name"EMP_ID"),
inverseJoinColumns _at_JoinColumn(name"PROJ_ID"
))
_at_ManyToMany
PROJECT
EMP_PROJ
EMP
SALARY
NAME
NAME
ID
PROJ_ID
EMP_ID
ID
PK
PK
PK,FK1
PK,FK2
47Étapes pour récupérer des données
Queries
- Il est possible de rechercher des données sur des
critères plus complexes que la simple identité - Les étapes sont alors les suivantes
- Décrire ce qui est recherché (langage JPQL)
- Créer une instance de type Query
- Initialiser la requête (paramètres, pagination)
- Lancer lexécution de la requête
- La JPA introduit le JPQL (Java Persistence Query
Language), qui est, tout comme le EJBQL ou encore
le HQL, un langage de requête du modèle objet,
basé sur SQL.
48Interface Query
- Représente une requête
- Une instance de Query (dune classe implémentant
Query) est obtenue par les méthodes - createQuery,
- createNativeQuery ou
- createNamedQuery de linterface EntityManager
49Queries NamedQueries
- Peut être mise dans nimporte quelle entité, mais
on choisira le plus souvent lentité qui
correspond à ce qui est renvoyé par la requête - On peut sauvegarder des gabarits de requête dans
nos entités. - Ceci permet
- La réutilisation de la requête
- Dexternaliser les requête du code.
_at_Entity _at_NamedQuery(name"myQuery", query"Select
o from MyPojo o") public class MyPojo
public class MyService public void
myMethod() List results em.createNamedQuery(
"myQuery").getResultList()
50Queries NativeQueries
- Une façon de faire des requête en SQL natif.
- Sert principalement à avoir plus de contrôle sur
les requêtes à la base de donnée.
public class MyService public void
myMethod() List results
em.createNativeQuery(SELECT FROM MyPojo,
MyPojo.class) .getResultList()
51Transactions
- 2 façons de mettre en place les transactions
- JTA
- En utilisant la Java Transaction API
- Resource-local
- En utilisant le modèle de transaction du
persistence manager - Les fournisseurs de persistance doivent supporter
les transactions locales à une ressource, mais ne
sont pas obligés de supporter les transactions
JTA - La démarcation des transactions est choisie par
le développeur - Les contextes de persistance peuvent couvrir
plusieurs transactions
52Transactions Resource-local
- Tient compte uniquement de la transaction
actuelle, indépendamment du serveur
dapplication. - 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 méthode getTransaction() de EntityManager
public class MyServlet extends HttpServlet
public void doGet() EntityManager em
emf.createEntityManager() em.getTransaction().
begin() // persistence operations
em.getTransaction().commit() em.close()
53Application server / persistence engine
- Les serveurs dapplication ont tous placé leurs
pions en vue de lavènement de la JPA. - Chacun a intégré un persistence manager de leur
choix - JBoss AS -gt Hibernate EntityManager
- BEA Weblogic 9.2 -gt SolarMetric Kodo
(OpenJPA!) - Sun GlassFish -gt Oracle TopLink Essentials
- Oracle 10g AS -gt Oracle TopLink Essentials
54Outils JPA
- Open source
- Eclipse 3.2.x et plus w/ DALI
- NetBeans 5.5 et plus
- Oracle JDeveloper
- Commerciaux
- BEA Workshop Studio (Eclipse)
- JBoss IDE (Eclipse) gratuit
55Comparaison Hibernate/JPA
- Points Communs
- Offrir des services de persistance
- Mappage Objet/Relationnel déclaratif
- Adopter un langage de requêtes
- Points de divergence
- JPA est une brique de base du standard Java EE 5
- Hibernate est un Framework alors que JPA est une
spécification (API) - Hibernate peut être utilisé comme fournisseur de
persistance - JPA utilise les annotations Java 5 pour assurer
le mappage - JPA est plus simple à mettre en œuvre que
Hibernate (Entity Manager, pas de fichiers de
mappage, )