Prsentation gnrale Architecture du noyau Hibernate Environnement de travail Classes persistantes dans Hibernate Oprations du gestionnaire de persistance Mta-donnes : fichiers de mapping/annotations des classes mtier Rcupration dinstances persistantes Requtes Transactions
86
Version 4 (2010: 3.6) : implmentation du standard de persistance EJB 3.0 Java Persistence API (JPA) Possibilit dtre utilis aussi bien dans un dveloppement client lourd, que dans un environnement web lger de type Apache Tomcat ou dans un environnement J2EE complet [Wikipdia] Code SQL gnr lexcution via des informations fournies dans un document de correspondance (mapping) XML ou des annotations
87
88
Hibernate Core : API native implmentant les services de base pour la persistance
Mta-donnes au format XML (+ annotations depuis la version 3.6) Langage HQL et interface pour crire des requtes
Hibernate Annotations (inclus dans Hibernate Core 3.6) : Remplacement des fichiers XML par des annotations JDK 5.0 implmentant les annotations du standard JPA + annotations spcifiques Hibernate Hibernate Entity Manager : Implmentation de la partie des spcifications JPA concernant
Les interfaces de programmation, Les rgles de cycle de vie des objets persistants Les fonctionnalits dinterrogation
Hibernate Entity Manager = wrapper au dessus du noyau Hibernate implmentant une solution complte de persistance JPA (cf. documentation Hibernate)
89
90
Session ou EntityManager : Objet mono-thread, dure de vie courte, reprsentant une conversation entre l'application et l'entrept de persistance Encapsule une connexion JDBC Contient un cache (de premier niveau et obligatoire) des objets persistants 92 Maude Manouvrier - Univ. Paris Dauphine repris de http://www.hibernate.org/hib_docs/reference/fr/html/architecture.html
93
94
95
Activation de la gnration automatique des schmas de base de donnes - directement dans la base de donnes :
<!-- Drop and re-create the database schema on startup --> <property name="hbm2ddl.auto">create</property>
96
97
Modle objet :
public class Person { private private private private private private }
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de http://docs.jboss.org/hibernate/core/3.6/reference/fr-FR/html_single/
public class Event { private private private private } Long id; String title; Date date; Set participants;
Long id; int age; String firstname; String lastname; Set events ; Set emailAddresses ;
98
Dclaration de la DTD
<class name="events.Person" table="PERSON"> mappe en <id name="id" column="PERSON_ID"> <generator class="native"/> Mapping de lidentifiant </id> <property name="age"/> <property name="firstname"/>
<property name="lastname"/> Mapping de collection <set name="events" table="PERSON_EVENT"> Attribut de jointure entre PERSON et PERSON_EVENT <key column="PERSON_ID"/> <many-to-many column="EVENT_ID" class="events.Event"/> </set> Pour prciser quil y a une table association <set name="emailAddresses" table="PERSON_EMAIL_ADDR"> <key column="PERSON_ID"/> <element type="string" column="EMAIL_ADDR"/> </set> Pour dfinir une collection de valeurs </class> </hibernate-mapping>
Maude Manouvrier - Univ. Paris Dauphine repris et adapt du tutorial dHibernate 3
99
// Accessor methods @Id@GeneratedValue(strategy=GenerationType.AUTO) @Column(name="PERSON_ID") public Long getId() { return this.id; } private Set events = new HashSet();
@ManyToMany Mapping de collection dobjets @JoinTable( name="PERSON_EVENT", joinColumns=@JoinColumn(name="PERSON_ID"), inverseJoinColumns=@JoinColumn(name="EVENT_ID") ) protected Set getEvents() { return events;} private Set emailAddresses = new HashSet(); @CollectionOfElements Mapping de collection de valeurs @JoinTable( table=@Table(name="PERSON_EMAIL_ADDR"), joinColumns = @JoinColumn(name="PERSON_ID") ) public Set getEmailAddresses() { return emailAddresses; } }
Maude Manouvrier - Univ. Paris Dauphine
10 0
Diagramme dtats dun objet manipul avec Hibernate tats dfinis par rapport un contexte de persistance (objet Session)
Etat Managed dans JPA
10 1
102
103
104
ou
sessionFactory = new AnnotationConfiguration() .addPackage("domain") // le nom complet du package .addAnnotatedClass(Person.class)
Maude Manouvrier - Univ. Paris Dauphine
105
10
106
Maude Manouvrier - Univ. Paris Dauphine repris et adapt du doc. de ref. dHibernate EntityManager
107
11
Utilisation de Ejb3Configuration, EntityManagerFactory et EntityManager ( la place de Configuration , SessionFactory et Session) et possibilit de configurer la fabrique lexcution :
Ejb3Configuration cfg = new Ejb3Configuration(); EntityManagerFactory emf = cfg.addProperties( properties ) .addAnnotatedClass( MyAnnotatedClass.class ) .addClass( NonAnnotatedClass.class ) .addResource( "mypath/MyOtherCLass.hbm.xml ) .configure("/mypath/hibernate.cfg.xml") .buildEntityManagerFactory();
Maude Manouvrier - Univ. Paris Dauphine repris et adapt du doc. de ref. dHibernate EntityManager
108
109
12
}
Maude Manouvrier - Univ. Paris Dauphine
110
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Gri09] et de la doc dHibernate 3
13
return true; }
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Gri09] et de la doc dHibernate 3
112
Annuler ( rollback() ) la transaction et fermer la Session en cas dexception souleve par les mthodes de Session
113
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de doc. De formation Valtech
14
Transient
Sauvegarde
ramasse-miette
Recherche Rcupration
get() load() Query.list() Query.uniqueResult() Query.iterate() Query.scroll() *find() *getReference() *Query.getResultList() *Query.getSingleResult()
Dtruit
Suppression
Persistant
evict() *close() *clear()
ramasse-miette
Annulation de la surveillance
Dtach
Maude Manouvrier - Univ. Paris Dauphine figure reprise et adapte de [BK07]
ramasse-miette
* Mthodes JPA - implmentes dans Hibernate EntityManager mais pas dans Hibernate Core
114
115
15
116
117
16
118
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [BK05], [Pat05] et [Gri09]
119
17
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Pat05] et [Gri09] + doc Hbernate 3
120
Aucune requte gnre et pas de leve dexception si le nuplet correspondant nexiste pas
Session session = HibernateUtil.getSessionFactory().getCurrentSession(); session.beginTransaction(); Person aPerson1 = (Person) session.get(Person.class, new Long(2)); session.getTransaction().commit(); Hibernate: select person0_.PERSON_ID as PERSON1_2_0_, person0_.age as age2_0_, person0_.firstname as firstname2_0_, person0_.lastname as lastname2_0_ from PERSON person0_ where person0_.PERSON_ID=? Session session = HibernateUtil.getSessionFactory().getCurrentSession(); session.beginTransaction(); Person aPerson1 = (Person) session.load(Person.class, new Long(2)); System.out.println(aPerson1.getFirstname()); session.getTransaction().commit(); Hibernate: select person0_.PERSON_ID as PERSON1_2_0_, person0_.age as age2_0_, person0_.firstname as firstname2_0_, person0_.lastname as lastname2_0_ from PERSON person0_ where person0_.PERSON_ID=?
121
18
Session session =HibernateUtil.getSessionFactory().getCurrentSession(); session.beginTransaction(); Person aPerson1 = (Person) session.get(Person.class, new Long(1)); if (aPerson1!=null) System.out.println(aPerson1.getFirstname()); session.getTransaction().commit(); Hibernate: select person0_.PERSON_ID as PERSON1_2_0_, person0_.age as age2_0_, person0_.firstname as firstname2_0_, person0_.lastname as lastname2_0_ from PERSON person0_ where person0_.PERSON_ID=? Mais pas dexception!! (sauf si on noublie de tester aPerson1)
122
Session session = HibernateUtil.getSessionFactory().getCurrentSession(); session.beginTransaction(); Person aPerson1 = (Person) session.load(Person.class, new Long(2)); Event anEvent1 = (Event) session.load(Event.class, new Long(8)); aPerson1.addToEvent(anEvent1); // Mthode mtier au-dessus session.getTransaction().commit(); select from PERSON person0_ where person0_.PERSON_ID=? select ... from PERSON_EVENT events0_ inner join EVENTS event1_ on events0_.EVENT_ID=event1_.EVENT_ID where events0_.PERSON_ID=? select from EVENTS event0_ where event0_.EVENT_ID=? (sauf si association dj existante ou si get et aprs la 1re requte) select from PERSON_EVENT participan0_ inner join PERSON person1_ on participan0_.PERSON_ID=person1_.PERSON_ID where participan0_.EVENT_ID=? insert into PERSON_EVENT (PERSON_ID, EVENT_ID) values (?, ?)
123
19
124
125
20
entitymanager.getReference(Class clazz, serializable id) Utilisation dun proxy pour rcuprer une rfrence sur lobjet sans rellement le charger (utile en particulier pour attacher un enfant un parent sans charger le parent) session.load()
Person aPerson1 = (Person) em.getRefrence(Person.class, Long(2)); Aucune requte gnre sauf si accs aux attributs de lobjet new
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de la documentation de Hibernate EntityManager
126
127
21
save/persist
Session session = HibernateUtil.getSessionFactory().getCurrentSession(); session.beginTransaction(); Event theEvent = new Event(); theEvent.setTitle(title); theEvent.setDate(theDate); session.save(theEvent); // Mme chose avec session.persist(theEvent); // ou avec entityManager.persist(theEvent); session.getTransaction().commit(); select nextval ('hibernate_sequence') car dans les mta-donnes XML :
On y reviendra!!
128
merge
// Aprs le code du transparent prcdent theEvent.setTitle("Test2"); // Mise jour dune instance dtache Session session2 = HibernateUtil.getSessionFactory().getCurrentSession(); session2.beginTransaction(); Event theEvent2 = (Event)session2.merge(theEvent); // TheEvent est toujours dtach, theEvent2 est persistant session2.getTransaction().commit();
Suite au merge : select from EVENTS event0_ where event0_.EVENT_ID=? update EVENTS set EVENT_DATE=?, title=? where EVENT_ID=? ou insert into EVENTS (EVENT_DATE, title, EVENT_ID) values (?, ?, ?) si pas dutilisation de la session dans le transparent prcdent
129
22
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Pat05] et [Gri09] + doc Hbernate 3
select PERSON person0_ where person0_.PERSON_ID=? update PERSON set age=?, firstname=?, lastname=? where PERSON_ID=?
Il faut appeler save ou persist pour rendre un objet transient persistant (pas de persistance automatique)
Session session = HibernateUtil.getSessionFactory().getCurrentSession(); session.beginTransaction(); Event theEvent = new Event(); theEvent.setTitle("Test3"); theEvent.setDate(new Date()); session.getTransaction().commit(); aucune requte gnre
131
23
flush
Event theEvent = new Event(); theEvent.setTitle("Test10"); theEvent.setDate(new Date()); Session session = HibernateUtil.getSessionFactory().getCurrentSession(); session.beginTransaction(); session.save(theEvent); theEvent.setTitle("Test11");
session.flush(); List result = session.createQuery("from Person").list(); session.getTransaction().commit(); // cre un flush automatique Sans le flush() : select select insert update select insert update select nextval ('hibernate_sequence') from PERSON into EVENTS (EVENT_DATE, title, EVENT_ID) values (?, ?, ?) EVENTS set EVENT_DATE=?, title=? where EVENT_ID=? nextval ('hibernate_sequence') into EVENTS (EVENT_DATE, title, EVENT_ID) values (?, ?, ?) EVENTS set EVENT_DATE=?, title=? where EVENT_ID=? from PERSON ou select from EVENTS
132
Retourne linstance persistante correspondante En accord avec les spcifications EJB 3.0 mais plusieurs variantes Ne se proccupe pas de ltat du contexte de persistance session.update(objet) Force la mise jour (UPDATE) de lobjet dans la base Lve une exception si une instance de mme identificateur existe dans le contexte de persistance
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Pat05] et [Gri09] + doc Hbernate 3
133
24
insert into EVENTS (EVENT_DATE, title, EVENT_ID) values (?, ?, ?) update EVENTS set EVENT_DATE=?, title=? where EVENT_ID=? contrairement au merge, pas de select avant le update et objet theEvent r-attach
134
insert into EVENTS (EVENT_DATE, title, EVENT_ID) values (?, ?, ?) select from EVENTS this_ where this_.EVENT_ID=? Exception in thread "main" org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session
135
25
En gnral : utilisation des mthodes update(), saveOrUpdate() ou merge() dans le cas dutilisation dinstance dune session une autre
136
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Pat05] et [Gri09] + doc Hbernate 3
saveOrUpdate
Event theEvent = new Event(); theEvent.setTitle("Event34"); theEvent.setDate(new Date()); Session session2 = HibernateUtil.getSessionFactory().getCurrentSession(); session2.beginTransaction(); Event anEvent1 = (Event) session2.load(Event.class, new Long(6)); anEvent1.setTitle("Test"); session2.saveOrUpdate(theEvent); session2.saveOrUpdate(anEvent1); session2.getTransaction().commit();
from EVENTS event0_ where event0_.EVENT_ID=? nextval ('hibernate_sequence') into EVENTS (EVENT_DATE, title, EVENT_ID) values (?, ?, ?) EVENTS set EVENT_DATE=?, title=? where EVENT_ID=?
Exception car une instance existe dj du mme id dans le contexte de persistance (mais attention pas si on utilise uniquement un proxy c--d pas avec load sans accder aux proprits de lobjet ex. sans anEvent1.setTitle("Test"))
137
26
1. Chargement dun objet dans une premire session 2. Objet pass la couche utilisateur
138
27
Si instance persistante avec le mme identifiant couramment associe la session copie de l'tat de l'objet donn dans l'instance persistante
Si pas d'instance persistante associe cette session chargement partir de la base de donnes ou cration dune nouvelle instance persistante Instance persistante correspondante retourne ! Mais instance passe en paramtre toujours dtache et donc non associe la session
140
!
Si support par le SGBD
UPGRADE : SELECT FOR UPDATE gestion dune file dattente en cas daccs concurrent avant la fin de la transaction UPGRADE_NOWAIT : SELECT FOR UPDATE NOWAIT Exception souleve en en cas daccs concurrent avant la fin de la transaction
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Pat05] et [Gri09] + doc Hbernate 3
141
28
lock (1/2)
Session session = HibernateUtil.getSessionFactory().getCurrentSession(); session.beginTransaction(); Event theEvent = new Event(); theEvent.setTitle("Event1"); theEvent.setDate(new Date()); session.persist(theEvent); // ou session.save(theEvent); session.getTransaction().commit(); theEvent.setTitle("Test3"); // theEvent est dtach Session session2 = HibernateUtil.getSessionFactory().getCurrentSession(); session2.beginTransaction(); session2.buildLockRequest(new LockOptions(LockMode.READ)).lock(theEvent); //session2.lock(theEvent, LockMode.READ); // Deprecated API session2.getTransaction().commit();
select nextval ('hibernate_sequence') insert into EVENTS (EVENT_DATE, title, EVENT_ID) values (?, ?, ?) select EVENT_ID from EVENTS where EVENT_ID =? sauf si LockMode.NONE
142
lock (2/2)
entityManager.lock() modifie uniquement le mode de verrouillage de lentit mais ne la r-attache pas exception en cas dentit dtache
EntityManager em = HibernateUtil.getEntityManagerFactory().createEntityManager(); em.getTransaction().begin(); Event theEvent = new Event(); theEvent.setTitle("Event1"); theEvent.setDate(new Date()); em.persist(theEvent); em.getTransaction().commit(); theEvent.setTitle("Test3"); // theEvent est dtach EntityManager em2 = HibernateUtil.getEntityManagerFactory().createEntityManager(); em2.getTransaction().begin(); LockModeType l = LockModeType.valueOf("OPTIMISTIC"); // ~ READ em2.lock(theEvent,l); em2.getTransaction().commit();
select nextval ('hibernate_sequence') insert into EVENTS (EVENT_DATE, title, EVENT_ID) values (?, ?, ?) Exception in thread "main" java.lang.IllegalArgumentException: entity not in the persistence context
143
29
144
close (1/4)
Session session = HibernateUtil.getSessionFactory().getCurrentSession(); session.beginTransaction(); Event theEvent = new Event(); theEvent.setTitle("Event1"); theEvent.setDate(new Date()); session.persist(theEvent); // session.save(theEvent); session.close(); session.getTransaction().commit();
145
30
close (2/4)
EntityManager em = HibernateUtil.getEntityManagerFactory().createEntityManager(); em.getTransaction().begin(); Event theEvent = new Event(); theEvent.setTitle("Event1"); theEvent.setDate(new Date()); em.persist(theEvent); em.close(); // Aprs le persist() em.getTransaction().commit();
select nextval ('hibernate_sequence') insert into EVENT (EVENT_DATE, title, EVENT_ID) values (?, ?, ?) Exception in thread "main" java.lang.IllegalStateException: EntityManager is closed
146
close (3/4)
EntityManager em = HibernateUtil.getEntityManagerFactory().createEntityManager(); em.getTransaction().begin(); Event theEvent = new Event(); theEvent.setTitle("Event1"); theEvent.setDate(new Date()); em.close(); // Avant le persist() em.persist(theEvent); em.getTransaction().commit();
147
31
close (4/4)
EntityManager em = HibernateUtil.getEntityManagerFactory().createEntityManager(); try { em.getTransaction().begin(); // do some work // ... em.commit(); } catch (RuntimeException e) { if (em.getTransaction() != null) em.getTransaction().rollback(); throw e; // or display error message } finally { em.close(); }
148
clear
EntityManager em = HibernateUtil.getEntityManagerFactory().createEntityManager(); em.getTransaction().begin(); Event theEvent = new Event(); theEvent.setTitle("Event1"); theEvent.setDate(new Date()); em.persist(theEvent); em.clear(); em.getTransaction().commit();
32
session.evict()/entityManager.detach()
EntityManager em = HibernateUtil.getEntityManagerFactory().createEntityManager(); em.getTransaction().begin(); Event theEvent = new Event(); theEvent.setTitle("Event1"); theEvent.setDate(new Date()); em.persist(theEvent); em.detach(theEvent); em.getTransaction().commit();
Instance toujours prsente dans la JVM tant que lobjet est rfrenc instance transiente Objet ramass par la ramasse miette ds quil nest plus rfrenc
On reviendra sur cette mthode en cas de graphe dobjets
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Pat05] et [Gri09] + doc Hbernate 3
151
33
session.delete()/ entityManager.remove()
EntityManager em = HibernateUtil.getEntityManagerFactory().createEntityManager(); em.getTransaction().begin(); Event theEvent = (Event) em.getReference(Event.class, new Long (90)); em.remove(theEvent); em.getTransaction().commit();
select from EVENT event0_ left outer join PERSON_EVENT participan1_ on event0_.EVENT_ID=participan1_.EVENT_ID left outer join PERSON person2_ on participan1_.PERSON_ID=person2_.PERSON_ID where event0_.EVENT_ID=? car chargement agressif par dfaut en JPA!! un select uniquement sur EVENT si fetch=FetchType.LAZY on y renviendra!! delete from EVENT where EVENT_ID=?
152
public void persist(Departement transientInstance) { log.debug("persisting Departement instance"); try { sessionFactory.getCurrentSession().persist(transientInstance); log.debug("persist successful"); } catch (RuntimeException re) { log.error("persist failed", re); throw re; } } public void delete(Departement persistentInstance) { log.debug("deleting Departement instance"); try { sessionFactory.getCurrentSession().delete(persistentInstance); log.debug("delete successful"); } catch (RuntimeException re) { log.error("delete failed", re); throw re; } }
}
Maude Manouvrier - Univ. Paris Dauphine
153
34
Persistance dune instance initialise par HashSet (par persist() par exemple) Remplacement par Hibernate de linstance par une implmentation de Set propre Hibernate Faire exo 3 exam fv.. 2012 154
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Gri09] et de la doc dHibernate 3
155
35
<component> : pour spcifier la correspondance dune association vers un composant <one-to-many> et <many-to-many> : pour spcifier correspondance dune association vers une collection dentits
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Gri09] et de la doc dHibernate 3
la
156
Mta-donnes et annotations
Possibilit dutiliser des annotations de JPA (Java Persistence API) :
Inclusion du package javax.persistence Inclusion dannotations dans les POJO Utilisation dannotations JPA et dannotations propres a Hibernate Inclure pour les versions antrieures 3.6 : hibernate.annotation.jar + ejb3-persistence.jar sinon hibernate-jpa-2.0-api-1.0.0.Final.jar Compilation des annotations en bytecode et lecture des annotations lexcution par Hibernate en utilisant la rflexion Java Possibilit de mlanger annotations et fichiers de correspondance XML
NB : Possibilit de dcrire les annotations JPA en XML par le langage JPA-XML (pour faciliter le dploiement en cas de changement de configuration)
Maude Manouvrier - Univ. Paris Dauphine
36
name : nom Java complet de la classe (ou interface) persistante table : nom de la relation en base de donnes par dfaut nom (non-qualifi) de la classe schema : Surcharge le nom de schma spcifi par l'lment racine (optionnel)
<class name="package.Departement" table="departement" schema="public">
+ dautres pour grer la gnration des requtes SQL lexcution, la stratgie de verrouillage, les cas o la classe appartient une hirarchie etc. On y reviendra cf. documentation de rfrence Hibernate : http://www.hibernate.org/docs
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Gri09] et de la doc dHibernate 3
158
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Gri09] et de la doc dHibernate 3
159
37
160
161
38
Gestion externe (+lgante) : implmenter lidentifiant par une classe compose name : proprit de type composant qui contient l'identifiant compos class : classe composant utilise comme identifiant compos La classe identifiante doit redfinir equals() et hashCode() et implmenter Serializable
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Gri09] et de la doc dHibernate 3
163
39
164
165
40
166
167
41
Instruction SQL
168
169
42
170
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Gri09] et de la doc dHibernate 3
171
43
172
Annotation @Column
@Column(name="reservation_id", unique=true, nullable=false, insertable=true, updatable=true) public int getReservationId() { return this.reservationId; } @Temporal(TemporalType.DATE) @Column(name="date_resa", unique=false, nullable=false, insertable=true, updatable=true, length=4) public Date getDateResa() { return this.dateResa; } @Temporal(TemporalType.TIME) @Column(name="heure_debut", unique=false, nullable=false, insertable=true, updatable=true, length=8) public Date getHeureDebut() { return this.heureDebut; } @Enumerated(EnumType.STRING) public Note getNote() //persistance en String dans la BD { ... }
Maude Manouvrier - Univ. Paris Dauphine
173
44
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Gri09] et de la doc dHibernate 3
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Gri09] et de la doc dHibernate 3
175
45
</class>
Enseignement *
Dpartement
/*** Enseignement generated by hbm2java*/ public class Enseignement implements java.io.Serializable { // Fields private EnseignementId id; private Departement departement; private String intitule; private String description;
}
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Gri09] et de la doc dHibernate 3
176
Dpartement
@Entity @Table(name="enseignement",schema="public" , uniqueConstraints = { } ) public class Enseignement implements java.io.Serializable { // Fields private EnseignementId id; private Departement departement; @ManyToOne(fetch=FetchType.LAZY) @JoinColumn(name="departement_id", unique=false, nullable=false, insertable=false, updatable=false) public Departement getDepartement() { return this.departement; } }
Maude Manouvrier - Univ. Paris Dauphine
177
46
Person
Employee
Dans Employee.hbm.xml : <one-to-one name="person" class="Person"/> Dans Person.hbm.xml : <one-to-one name="employee" class="Employee" constrained="true"/> La cl primaire de person fait rfrence la cl primaire de employee
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Gri09] et de la doc dHibernate 3
178
179
47
180
181
48
183
49
184
185
50
Possibilit de dfinir des proprits pour key (on delete etc.) cf. doc Hibernate
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Gri09] et de la doc dHibernate 3
186
}
@Entity @Table(name="enseignement",schema="public", uniqueConstraints = {}) public class Enseignement implements java.io.Serializable {
@ManyToOne(cascade={}, fetch=FetchType.LAZY) @JoinColumn(name="departement_id", unique=false, nullable=false, insertable=false, updatable=false) public Departement getDepartement() { return this.departement; }
}
Maude Manouvrier - Univ. Paris Dauphine
187
51
188
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Gri09] et de la doc dHibernate 3
189
52
190
191
53
192
54
Balise <many-to-one> dans la balise <natural-id> Cration par Hibernate des contraintes UNIQUE et des contraintes de cls trangres correspondantes
<class name="Bid" > <id name="id"> <generator class="native"/> </id> <natural-id> <many-to-one name="item"/> <property name="amount"/> </natural-id> </class>
POJO
public class Bid { private AuctionItem item; private float amount; }
CONSTRAINT bid_pkey PRIMARY KEY (id), CONSTRAINT fk104dd26c25fbe FOREIGN KEY (item) REFERENCES auctionitem (id) CONSTRAINT bid_item_key UNIQUE (item, amount)
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Gri09] et de la doc dHibernate 3
Instruction SQL
194
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Gri09] et de la doc dHibernate 3
55
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Gri09] et de la doc dHibernate 3
196
197
56
198
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Gri09] et de la doc dHibernate 3
199
57
200
201
58
class="Payment"/>
202
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Gri09] et de la doc dHibernate 3
203
59
204
205
60
206
207
61
Possibilit pour des raisons de lisibilit de faire un fichier par classe ( stratgie) : utilisation de extends="SuperclassName"
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Gri09] et de la doc dHibernate 3
208
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Pat05] et de la doc dHibernate 3
209
62
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Pat05] et de la doc dHibernate 3
210
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Pat05] et de la doc dHibernate 3
211
63
Chargement tardif par proxy pour les associations vers un seul objet Pas de chargement tardif possible pour les objets dtachs Activation/Dsactivation du chargement tardif par lattribut fetch
212
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Pat05] et de la doc dHibernate 3
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Pat05] et de la doc dHibernate 3
64
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Pat05] et de la doc dHibernate 3
215
65
216
Rcupration du nuplet correspondant la personne 2 Rcupration des id des vnements associs la personne 2 : 3 et 6 Rcupration des id des personnes associes aux vnements associs la personne 2 : (3,2) ; (3,4); (3,5) et (6,2) Rcupration des id des vnements associs la personne 4 : il ny a que 3 Rcupration des id des vnements associs la personne 5 : 3, 7 et 8 Rcupration des id des personnes associes aux vnements associs la personne 5 : aucun
217
66
218
Requtes
67
Requtes
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Pat05] et de la doc dHibernate 3
220
Requtes
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Pat05] et de la doc dHibernate 3
221
68
Requtes
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Pat05] et de la doc dHibernate 3
222
Requtes
Excution de la requte
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Pat05] et de la doc dHibernate 3
223
69
Requtes
pour choisir le mode de chagement Valeurs: FetchMode.JOIN (pour imposer une jointure externe), FetchMode.SELECT (pour charger lassociation par un SELECT supplmentaire) cf. mode de chargement
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Pat05] et de la doc dHibernate 3
224
Requtes
Besoin de mta-donnes pour dfinir le rsultat de la requte sauf si le rsultat correspond des donnes dont le mapping est dj dcrit
225
70
Transactions (1/10)
Pour le noyau ou Hibernate Entity Manager : Utilisation directe des connexions JDBC ainsi que des ressources JTA sans y ajouter davantage de mcanisme de blocage Pas de verrouillage des objets en mmoire ni de modification du niveau disolation dfini au niveau du SGBD En cas dutilisation dHibernate dans un environnement lger (application autonome, application web simple ou applications Swing) => dlimitation manuelle des transactions En cas dutilisation dHibernate dans un environnement J2EE => utilisation des services de gestion automatique des transactions JTA (cf. cours J2EE)
Rgles de base conseilles : pas dauto-commit et communication avec le SGBD par transaction uniquement (mme pour les lectures) 226 Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [BK07,Pat05] et de la doc dHibernate 3
Transactions (2/10)
Session sess = factory.openSession(); // Mme chose en utilisant Transaction tx = null; try { tx = sess.beginTransaction(); // do some work ... tx.commit(); } // EntityManager
catch (RuntimeException e) { if (tx != null) tx.rollback(); throw e; // or display error message } finally { sess.close(); }
Toutes exceptions souleves ne sont pas rcuprables et doivent tre considres comme fatales pour le gestionnaire de persistance en cours (il faut annuler la transaction et fermer lunit de travail)
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [BK07,Pat05] et de la doc dHibernate 3
227
71
Transactions (3/10)
3 types d'anomalies d'isolation dfini dans ANSI SQL92 :
Lectures sales ou impropres Une transaction T1 lit des modifications non valides ditems effectues par T2. En cas de annulation de T2, T1 a lu des valeurs invalides Lecture non reproductibles T1 lit un item, T2 modifie ce mme item, T1 relit ce item et obtient une valeur diffrente Lectures fantmes T1 lit un ensemble de nuplets, T2 ajoute/supprime des nuplets, T1 relit lensemble de nuplets et obtient un ensemble diffrent comme rsultat 228
Transactions (4/10)
Degrs disolation :
En SQL :
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE READ ONLY Dans le fichier de config (hibernate.hbm.xml ou persistence.xml) :
<property name="hibernate.connection.isolation" value=x"/>
avec x = 1 pour read-uncommitted, 2 pour read committed, 4 pour repeatable read et 8 pour serializabe
Maude Manouvrier - Univ. Paris Dauphine
229
72
Transactions (5/10)
Pour Hibernate et JPA : Choix par le dveloppeur et/ou ladministrateur de BD du niveau disolation utilis au niveau de la base de donnes Contrle de la concurrence de manire optimiste par versionnement en gnral associ un niveau disolation read-committed Garantie des lectures rptables par le contexte de persistance (cache) Possibilit de faire du verrouillage pessimiste pour augmenter le niveau disolation pour une unit de travail particulire
230
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [BK07,Pat05] et de la doc dHibernate 3
Transactions (6/10)
Gestion optimiste de la concurrence par versionnement : Optimiste = supposition dune excution correcte et de la raret des conflits de mise jour Par versionnement = utilisation de numros de version ou dhorodatage pour dtecter les mises jour causant des conflits avec d'autres actualisations antrieures
Association dun numro de version (nombre ou estampille temporelle) chaque entit Mise jour du numro de version chaque mise jour Comparaison automatique des numros de version Leve dune exception en cas de conflit
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [BK07,Pat05] et de la doc dHibernate 3
231
73
Transactions (7/10)
Plusieurs stratgies de gestion optimiste de la concurrence par versionnement :
En XML : optimistic-lock="none|version|dirty|all" dans la balise <class> Par annotation :
@org.hibernate.annotations.Entity(optimisticLock = OptimisticLockType.VERSION | OptimisticLockType.NONE | OptimisticLockType.DIRTY | OptimisticLockType.ALL)
NONE : dsactivation de la gestion optimiste VERSION : exploitation de la proprit <version> ou @Version DIRTY: exploitation des valeurs de proprits sales (conflit si mises jour de la mme proprits par deux transactions concurrentes sinon pas de conflit) ALL: exploitation des valeurs de toutes les proprits (comparaison sur les valeurs et non sur la proprit de version) si pas de possibilit dajouter de numro de version dans la base Attention il faut que dynamicUpdate=true et problme si gestion dobjets dtachs
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [BK07,Pat05] et de la doc dHibernate 3
232
Transactions (8/10)
Gestion optimiste de la concurrence par versionnement :
Possibilit deffectuer le contrle au niveau applicatif : vrification du numro de version par lapplication afin de maintenir l'isolation transactionnelle (approche semblable celle des EJB) Sinon gestion automatique par Hibernate Vrification de la version des objets persistants avant d'effectuer le flush() Lancement dune exception si une modification concurrente est dtecte Gestion de lexception par le dveloppeur
Vrification du numro de version et de lentit dans un seul UPDATE possibilit dexcuter des UPDATE inutiles en cas de r-attachement dentits dtaches Pour imposer un SELECT avant lUPDATE : select-before-update="true"
en XML ou selectBeforeUpdate=true en annotation Hibernate (@org.hibernate.annotations.Entity )
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [BK07,Pat05] et de la doc dHibernate 3
233
74
Transactions (9/10)
Utilisation du mcanisme de verrouillage de la base de donnes et pas de verrouillage en mmoire Niveaux de verrouillage pouvant tre obtenus par le noyau Hibernate (Hibernate Native) via LockMode :
LockMode.NONE : absence de verrouillage (pas daccs la BD sauf si lobjet nest pas en mmoire) LockMode.WRITE obtenu automatiquement quand Hibernate actualise ou insre un enregistrement LockMode.READ : vrification que le numro de version dun objet en mmoire est le mme que le numro de version en BD - obtenu automatiquement quand Hibernate lit des donnes dans un contexte d'isolation Repeatable Read ou Serializable LockMode.UPGRADE (quivalent LockModeType.READ en JPA) : vrification du numro de version (si applicable) et transformation dun verrou en lecture par un verrou en criture si autoris par le SGBD retour au mode LockMode.READ si SELECT FOR UPDATE non permis par le SGBD LockMode.UPGRADE_NOWAIT : idem que UPGADE mais utilisation de NO WAITS (lancement dune exception et pas dattente de verrou) LockMode.FORCE (quivalent LockModeType.WRITE en JPA) : incrmentation force du numro de version en BD pour indiquer la MJ par la transaction courante
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [BK07,Pat05] et de la doc dHibernate 3
234
Transactions (9bis/10)
Gestion pessimiste de la concurrence :
Niveaux de verrouillage pouvant tre obtenus par lEntityManager dHibernate via LockMode :
OPTIMISTIC (prcdemment READ) : gestion optimiste de la concurrence avec vrification du numro de version avant toute validation. OPTIMISTIC_FORCE_INCREMENT (prcdemment WRITE) : gestion optimiste de la concurrence avec vrification du numro de version avant toute validation et incrmentation force du numro de version. PESSIMISTIC_READ: application dun verrouillage en lecture lectures concurrentes autorises mais pas dautorisation dcriture. PESSIMISTIC_WRITE: application dun verrouillage en criture pas dautorisation dcriture ou de lecture concurrente. Quel que soit le mode de gestion de la concurrence : pas de lecture sale ou non reproductible. Gestion optimiste de la concurrence : pas de mise en attente des transactions et pas de verrouillage, dtection des conflits par versionnement et hypothse de la raret des conflits Gestion pessimiste : utilisation de mcanisme de verrouillage et mise en attente des transactions.
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [BK07,Pat05] et de la doc dHibernate 3
235
75
Transactions (10/10)
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [BK07,Pat05] et de la doc dHibernate 3
236
76