Vous êtes sur la page 1sur 76

Partie 4 : Hibernate / JPA

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

Maude Manouvrier - Univ. Paris Dauphine

Hibernate : gnralits (1/3)


Outil ORM ou Cadre (Framework) de persistance libre (open source) grant la persistance des objets Java/J2EE en base de donnes relationnelle [Wikipdia,
Pat05]

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

Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Pat05] et [Gri09]

Hibernate : gnralits (2/3)

Maude Manouvrier - Univ. Paris Dauphine repris de http://hibernate.org/

88

Hibernate : gnralits (3/3)


Diffrents modules :

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)

Maude Manouvrier - Univ. Paris Dauphine

89

Architecture du noyau Hibernate (1/12)


hibernate.properties : Fichier de configuration Version XML : hibernate.cfg.xml permettant un paramtrage plus fin Configuration par programmation XML mapping ou annotations : Mta-donnes (paramtres) dcrites sous la forme de fichiers de correspondance XML ou sous forme dannotation Utilises pour mettre en correspondance les classes Java et le modle relationnel

XML mapping ou annotations

Maude Manouvrier - Univ. Paris Dauphine repris et adapt de http://www.hibernate.org/hib_docs/reference/fr/html/architecture.html

90

Architecture du noyau Hibernate (2/12)


Objet temporaire Objet persistent (ayant une dure de vie longue)

SessionFactory (Hibernate) EntityManagerFactory (JPA)

Session (Hibernate) EntityManager (JPA)

Interface permettant dobtenir des instances Session ou EntityManager

Interface principale utilise par Hibernate 91

Maude Manouvrier - Univ. Paris Dauphine repris et adapt de http://www.hibernate.org/hib_docs/reference/fr/html/architecture.html

Architecture du noyau Hibernate (3/12)


SessionFactory ou EntityManagerFactory : Cache immuable (threadsafe) des correspondances (mappings) vers une (et une seule) base de donnes Coteuse construire car implique lanalyse des fichiers de configuration Pouvant contenir un cache optionnel de donnes (de second niveau) rutilisable entre les diffrentes transactions Construite partir dun objet (Ejb3)Configuration

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

Architecture du noyau Hibernate (4/12)


private static Configuration configuration; private static SessionFactory sessionFactory; private Session s; Consultation du fichier try { hibernate.cfg.xml prsent // tape 1 dans le classpath de lapplication configuration = new Configuration(); Analyse du fichier // tape 2 de mapping sessionFactory = configuration.configure().buildSessionFactory(); // tape 3 s = sessionFactory.openSession(); } catch (Throwable ex) { log.error("Building SessionFactory failed.", ex); throw new ExceptionInInitializerError(ex); }

Conseil : utiliser une classe HibernateUtil pour factoriser ces tapes


Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Pat05]

93

Architecture du noyau Hibernate (5/12)


Exemple de fichier de configuration hibernate.cfg.xml :
<?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- Database connection settings --> <property name="hibernate.connection.driver_class">org.postgresql.Driver </property> <property name="hibernate.connection.password">passwd</property> <property name="hibernate.connection.url">jdbc:postgresql:BDTest2</property> <property name="hibernate.connection.username">login</property> <!-- SQL dialect --> <property name="dialect">org.hibernate.dialect.PostgreSQLDialect</property> <!-- Enable Hibernate's automatic session context management --> <property name="current_session_context_class">thread</property> <!-- Disable the second-level cache --> <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider </property> <!-- Echo all executed SQL to stdout --> <property name="show_sql">true</property> <!-- Drop and re-create the database schema on startup --> <property name="hbm2ddl.auto">create</property> <mapping resource="events/Event.hbm.xml"/> <mapping resource="events/Person.hbm.xml"/> </session-factory> </hibernate-configuration>
Maude Manouvrier - Univ. Paris Dauphine repris et adapt du tutorial dHibernate 3

94

Architecture du noyau Hibernate (6/12)


Dclaration du type de document utilis par lanalyseur syntaxique (parseur) XML pour valider le document de configuration daprs la DTD de configuration dHibernate :
<?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration3.0.dtd">

Paramtres de configuration ncessaires pour la connexion JDBC :


<property name="hibernate.connection.driver_class">org.postgresql.Driver </property> <property name="hibernate.connection.password">passwd</property> <property name="hibernate.connection.url">jdbc:postgresql:BDTest2 </property> <property name="hibernate.connection.username">login </property>

Maude Manouvrier - Univ. Paris Dauphine

95

Architecture du noyau Hibernate (7/12)


Spcification de la variante de SQL gnre par Hibernate :
<!-- SQL dialect --> <property name="dialect">org.hibernate.dialect.PostgreSQLDialect </property>

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>

Fichier de configuration (fichier de mapping) des classes persistantes :


<mapping resource="events/Event.hbm.xml"/> <mapping resource="events/Person.hbm.xml"/>

Maude Manouvrier - Univ. Paris Dauphine

96

Architecture du noyau Hibernate (8/12)


Possibilit de transmettre les paramtres de configuration lexcution
Configuration cfg = new Configuration() .addClass(Person.class) .addClass(Event.class) .setProperty(Environment.HBM2DDL_AUTO, "create"); cfg.setProperty("hibernate.show_sql", "true"); cfg.setProperty("hibernate.connection.driver_class", "org.postgresql.Driver") .setProperty("hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect") .setProperty("hibernate.connection.url", "jdbc:postgresql:BDTest1") .setProperty("hibernate.connection.username", "login") .setProperty("hibernate.connection.password", "passwd") .setProperty("hibernate.order_updates", "true"); factory = cfg.buildSessionFactory();

Maude Manouvrier - Univ. Paris Dauphine

97

Exemple : Tutorial Hibernate


Modle relationnel :

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

Architecture du noyau Hibernate (9/12)


Exemple de fichier de correspondance pour la classe Person Person.hbm.xml :
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping> Dclaration du mapping

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"/>

Classe event.Person relation PERSON

<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

Architecture du noyau Hibernate (10/12)


Mapping par annotation exemple de la classe Person :
@Entity @Table (name="PERSON") public class Person { private Long id; private int age; private String firstname; private String lastname; public Person() {}

Classe event.Person mappe en relation PERSON

Attention avant la version 3.6 : il faut utiliser Hibernate Annotation !!


Mapping de lidentifiant

// 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

Architecture du noyau Hibernate (11/12)


Etat New dans JPA

Diagramme dtats dun objet manipul avec Hibernate tats dfinis par rapport un contexte de persistance (objet Session)
Etat Managed dans JPA

Maude Manouvrier - Univ. Paris Dauphine Figure reprise de [Pat05]

10 1

Architecture du noyau Hibernate (12/12)


Passager/Temporaire/phmre (transient) : Instance non associe (et n'ayant jamais t associe) un contexte de persistance Instance sans identit persistante (i.e. valeur de cl primaire) Persistant : Instance associe un contexte de persistance (Session) Instance possdant une identit persistante (i.e. valeur de cl primaire) et, peut-tre, un enregistrement/nuplet correspondant dans la base Pour un contexte de persistance particulier, garantie par Hibernate de lquivalence entre l'identit persistante et l'identit Java (i.e. emplacement mmoire de l'objet) Dtach Instance ayant t associe au contexte de persistance prsent ferm ou instance ayant t srialise vers un autre processus Instance possdant une identit persistante et peut-tre un enregistrement/nuplet correspondant dans la base Aucune garantie par Hibernate sur la relation entre l'identit persistante et l'identit Java
Maude Manouvrier - Univ. Paris Dauphine repris et adapt du doc. de ref. dHibernate 3

102

Environnement de travail avec Hibernate (1/6)


Bibliothques Hibernate Core (en plus de hibernate3.jar) :
Antlr-xxx.jar ANTLR (Another Tool for Language Recognition) - outil permettant de dvelopper un langage maison avec une grammaire capable de le reconnatre. Utilis pour crer langage HQL (Hibernate Query Language) - Indispensable lexcution commons-collections-xxx.jar Bibliothques du projet Apache Jakarta Commons pour manipuler les collections Indispensable lexcution Dom4j-xxx.jar API Open Source Java permettant de travailler avec XML, XPath et XSLT - Analyseur Syntaxique de configuration XML et de mapping - Indispensable lexcution javassist-xxx.GA.jar API de manipulation de bytecode (fichier .class), dans un contexte de rflexion, c--d de modification du contenu dune classe en phase dexcution - Indispensable lexcution jta.jar API JTA standard (interfaces Java standards entre un gestionnaire de transaction et les diffrentes parties impliques dans un systme de transactions distribues) Requis pour les applications sexcutant en dehors dun serveur dapplication - Indispensable lexcution slf4j-api-xxx.jar (avant log4J) (Simple Logging Facade for Java) Abstraction d'un systme de login permettant de sabstraire de limplmentation utilise - Indispensable lexcution Pour pouvoir configurer le logging : slf4j-api.jar
Maude Manouvrier - Univ. Paris Dauphine repris et adapt du doc. de ref. dHibernate 3, de [Pat05] et de http://www.objis.com/formation-java/tutoriel-hibernate-installation-analyse-hibernate-3-jar.html

103

Environnement de travail avec Hibernate (2/6)


Fichiers ncessaires avec Hibernate Core : hibernate.cfg.xml : fichier de configuration globale contenant Les paramtres de connexion la base de donnes (pilote, login, mot de passe, url, etc.) Le dialecte SQL de la base de donnes La gestion de pool de connexions Le niveau de dtails des traces etc. Pour chaque classe persistante : ClassePersistante.java : Implmentation POJO (Plain Old Java Objects) de la classe ClassePersistante.hbm.xml : Fichier XML de correspondance (mapping) ClassePersistanteHome.java ou ClassePersistanteDAO.java : Implmentation du DAO (Data Access Object) pour lisolation avec la couche de persistance Optionnel ClassePersistante.sql : Code SQL de cration de la ou les relations correspondantes Optionnel pouvant tre gnr par Hibernate
Maude Manouvrier - Univ. Paris Dauphine

104

Environnement de travail avec Hibernate (3/6)


Bibliothques Hibernate Annotation (avant la version 3.5) : hibernate-annotations.jar hibernate3.jar Annotations propres Hibernate depuis la version 3.5 lib/ejb3-persistence.jar Annotations du standard EJB3 Fichiers ncessaires pour Hibernate Annotation : hibernate.cfg.xml : fichier de configuration ClassePersistante.java : POJO avec annotations ClassePersistante.hbm.xml : optionnel possibilit de combiner annotations et mta-donnes XML Particularit pour la cration de la SessionFactory :
sessionFactory = new AnnotationConfiguration().buildSessionFactory(); Et ajout dans le fichier de hibernate.cfg.xml de <mapping class="Person"/>

ou
sessionFactory = new AnnotationConfiguration() .addPackage("domain") // le nom complet du package .addAnnotatedClass(Person.class)
Maude Manouvrier - Univ. Paris Dauphine

105

10

Environnement de travail avec Hibernate (4/6)


Bibliothques Hibernate EntityManager (avant la version 3.5) : hibernate-commons-annotations.jar hibernate-entitymanager.jar Bibliothques Hibernate EntityManager (depuis version 3.5) : hibernate-jpa-xx-api-xx.Final.jar Fichiers ncessaires pour Hibernate EntityManager : persistence.xml : fichier de configuration situ dans le rpertoire META-INF
<persistence > <persistence-unit name="manager1" transaction-type="JTA"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <jta-data-source>java:/DefaultDS</jta-data-source> <class>org.acme.Person</class> <class>org.acme.Event</class> <properties> <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/> <property name="hibernate.hbm2ddl.auto" value="create-drop"/> </properties> </persistence-unit> </persistence>

ClassePersistante.java : POJO avec annotations


Maude Manouvrier - Univ. Paris Dauphine repris et adapt du doc. de ref. dHibernate EntityManager

106

Environnement de travail avec Hibernate (5/6)


Proprit pour se connecter :
<property name="javax.persistence.jdbc.driver" value="org.postgresql.jdbcDriver"/> <property name="javax.persistence.jdbc.user" value=""/> <property name="javax.persistence.jdbc.password" value=""/> <property name="javax.persistence.jdbc.url" value="jdbc:postgresql:BDTest1"/>

Possibilit dutiliser un fichier hibernate.cfg.xml :


<property name="hibernate.ejb.cfgfile" value="/org/hibernate/ejb/test/hibernate.cfg.xml"/>

Replacement des proprits hibernate.cfg.xml par celles du fichier persistence.xml

Maude Manouvrier - Univ. Paris Dauphine repris et adapt du doc. de ref. dHibernate EntityManager

107

11

Environnement de travail avec Hibernate (6/6)


Pour crer le gestionnaire de persistance :
EntityManagerFactory emf = Persistence.createEntityManagerFactory("manager1");

Possibilit de fournir des proprits au gestionnaire de persistance lexcution :


Map<String, Object> configOverrides = new HashMap<String, Object>(); configOverrides.put("hibernate.hbm2ddl.auto", "create-drop"); EntityManagerFactory programmaticEmf = Persistence.createEntityManagerFactory("manager1", configOverrides);

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

Classes persistantes dans Hibernate (1/6)


Classes persistantes : implmentation des entits mtiers sous la forme de POJO Pas dimplmentation de certaines interfaces dhritage de classes particulires 5 rgles respecter : Implmenter un constructeur sans paramtre (pouvant tre priv mais de prfrence accessible par le paquetage) Fournir une proprit d'identifiant (optionnel mais fortement recommand) Favoriser les classes non finales (semi-optionnel) Implmenter des modificateurs (mutateurs - setter) et accesseurs (getter) pour chaque champ persistant Implmenter de Collections avec les classes du cadre dapplication (framework) Collections dHibernate (Set, List, Map etc.)
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Gri09] et de la doc dHibernate 3

109

12

Classes persistantes dans Hibernate (2/6)


/*** Departement generated by hbm2java*/ public class Departement implements java.io.Serializable { // Fields private int departementId; private String nomDepartement; private Set<Enseignement> enseignements = new HashSet<Enseignement>(0); private Set<Enseignant> enseignants = new HashSet<Enseignant>(0); // Constructors /** default constructor */ public Departement() {} // Property accessors public int getDepartementId() { return this.departementId; } public void setDepartementId(int departementId) { this.departementId = departementId; } public String getNomDepartement() { return this.nomDepartement; }

}
Maude Manouvrier - Univ. Paris Dauphine

110

Classes persistantes dans Hibernate (3/6)


Garantie par Hibernate de l'quivalence de l'identit persistante (ou de base de donnes) et de l'identit Java mais uniquement l'intrieur de la porte d'une session particulire Mthodes equals() et hashCode() surcharger en particulier si : Instances de classes persistantes gres dans un Set (manire recommande pour reprsenter des associations pluri-values) Utilisation du rattachement d'instances dtaches (on y reviendra ) Utilisation didentificateur composite (on y reviendra ) 111

Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Gri09] et de la doc dHibernate 3

13

Classes persistantes dans Hibernate (4/6)


Rgles pour surcharger equals() et hashCode(): cf . http://www-128.ibm.com/developerworks/java/library/jjtp05273.html Recommandation Hibernate : implmenter equals() et hashCode() en utilisant l'galit par cl mtier

Exemple de surcharge de equals() :


public boolean equals(Object other) { // Test dgalit de rfrence en mmoire if (this == other) return true; //Vrification de la classe dont other est instance if ( !(other instanceof MyClass) ) return false; // Test de comparaison des proprits appartenant // la cl mtier final MyClass obj = (MyClass) other; if ( !obj.getProp1().equals( getProp1() ) ) return false;

return true; }
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Gri09] et de la doc dHibernate 3

112

Classes persistantes dans Hibernate (5/6)


Pour manipuler des objets persistants : 1. Ouverture dune Session Hibernate 2. [Dbuter une transaction] fortement conseill 3. Appliquer les oprations de Session pour interagir avec lenvironnement de persistance 4. [Valider ( commit() ) la transaction en cours] 5. Synchroniser avec la base de donnes (flush) et fermer la session

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

Classes persistantes dans Hibernate (6/6)


Diagramme dtats des objets dune classe persistante
Instanciation
new

Transient
Sauvegarde

ramasse-miette

Recherche Rcupration
get() load() Query.list() Query.uniqueResult() Query.iterate() Query.scroll() *find() *getReference() *Query.getResultList() *Query.getSingleResult()

save() saveOrUpdate() *persist() delete() *merge() *remove()

Dtruit

Suppression

Persistant
evict() *close() *clear()

ramasse-miette

Remise sous surveillance


update() saveOrUpdate() *merge() lock()

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

Contexte de persistance (1/4)


Session ou EntityManager associe un contexte de persistance :
Vrification des modifications et synchronisation avec la base de donnes (automatic dirty checking) Utilisation du contexte de persistance comme cache de 1er niveau Garantie de lidentit Java Extension du contexte de persistance une conversation (unit de travail longue)

Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [BK07]

115

15

Contexte de persistance (2/4)


Automatic dirty checking :
Fermeture de lunit de travail synchronisation avec la base des entits mises jour (dirty) Possibilit de synchronisation avec la base avant lexcution dune requte Propagation des modifications dans la base aussi tard que possible et maintien des verrous de base de donnes le moins longtemps possible Possibilit de ne propager que les mises jour des proprits rellement modifies

Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [BK07]

116

Contexte de persistance (3/4)


Utilisation du cache :
Pour vrifier les mises jour Pour amliorer les performances en diminuant linteraction avec la base de donnes Pour garantir lisolation (repeatable read) Pour viter le dpassement de capacit de la pile (stack overflow) en cas de navigation dans le graphe dobjets Pour viter les conflits de reprsentation (pas deux objets correspondants au mme nuplet) Possibilit de grer le cache (dtachement dobjets et nettoyage du contexte de persistance)
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [BK07]

117

16

Contexte de persistance (4/4)


Conversation ou transaction applicative :
Ensemble doprations courtes ralises par interaction entre lutilisateur et lapplication (ex. application Web) Implmentation :
En dtachant les entits Pas de garantie de lidentit des objets (do importance de la redfinition des mthodes equals et hashCode) Gestion manuelle du r-attachement ou de la fusion des entits au contexte de persistance (attention pas de gestion du rattachement dans JPA) En tendant le contexte de persistance Pas de fermeture du contexte de persistance pendant linteraction avec lutilisateur mais dconnexion de la base Pas de possibilit de valider les changements avant la fin
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [BK07] et [Pat08]

118

Oprations du gestionnaire de persistance (1/15)


Gestionnaire de persistance ou dentits = Session ou EntityManager Oprations : Rcuprer une instance persistante Rendre une instance persistante Rendre persistantes les modifications apportes une instance persistante Rendre persistantes les modifications apportes une instance dtache R-attacher une instance dtache Dtacher une instance persistante Supprimer une instance persistante Rafrachir une instance Dtecter automatiquement un tat

Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [BK05], [Pat05] et [Gri09]

119

17

Oprations du gestionnaire de persistance (2/15)


Rcuprer une instance persistante dans Hibernate Core :
session.load(Class clazz, serializable id) Leve dune exception irrcuprable s'il n'y a pas de ligne correspondante dans la base de donnes session.get(Class clazz, serializable id) null si pas de nuplet correspondant dans la base Pour ces deux mthodes : Gnration dun ordre SQL un SELECT sur la base pour rcuprer lentit partir de son identificateur Possibilit de charger dans une instance nouvellement cre ou dans une instance existante Possibilit de transformer le SELECT en SELECT ... FOR UPDATE en utilisant LockMode.UPGRADE en 3me paramtre (on y reviendra ) Possibilit de rcuprer une instance aussi par les API Query, Criteria, SQLQuery (on y reviendra )

Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Pat05] et [Gri09] + doc Hbernate 3

120

load versus get (1/5)


Session session = HibernateUtil.getSessionFactory().getCurrentSession(); session.beginTransaction(); Person aPerson1 = (Person) session.load(Person.class, new Long(2)); session.getTransaction().commit();

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

load versus get (2/5)


Session session = HibernateUtil.getSessionFactory().getCurrentSession(); session.beginTransaction(); Person aPerson1 = (Person) session.load(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=? Exception in thread "main" org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [events.Person#1]

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

load versus get (3/5)


public class Person { public void addToEvent(Event event) { this.getEvents().add(event); event.getParticipants().add(this); } Mise jour des deux cots de lassociation

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

load versus get (4/5)


// Si on a chang la stratgie par dfaut en chargement agressif // lazy="false" - on y reviendra!! Person aPerson1 = (Person) session.get(Person.class, new Long(1)); Event anEvent1 = (Event) session.load(Event.class, new Long(6)); Person1.addToEvent(anEvent1); 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 PERSON_EVENT participan0_ inner join PERSON person1_ on participan0_.PERSON_ID=person1_.PERSON_ID where participan0_.EVENT_ID=? (si collection events non vide pour rcuprer la collection participants correspondante de chaque lment de events et autant de requtes que dlments dans events) select from EVENTS event0_ where event0_.EVENT_ID=? (sauf si association dj existante) select _ from PERSON_EVENT participan0_ inner join PERSON person1_ on participan0_.PERSON_ID=person1_.PERSON_ID where participan0_.EVENT_ID=? select from PERSON_EVENT events0_ inner join EVENTS event1_ on events0_.EVENT_ID=event1_.EVENT_ID where events0_.PERSON_ID=? (si collection participants non vide pour rcuprer la collection events correspondante de chaque lment de participants et autant de requtes que dlments dans participants) select from PERSON_EVENT participan0_ inner join PERSON person1_ on participan0_.PERSON_ID=person1_.PERSON_ID where participan0_.EVENT_ID=? (pour rcuprer les events de chaque participant et autant de requtes que dlments dans events) insert into PERSON_EVENT (PERSON_ID, EVENT_ID) values (?, ?)

124

load versus get (5/5)


// Si chargement la demande par dfaut Session session = HibernateUtil.getSessionFactory().getCurrentSession(); session.beginTransaction(); Person aPerson1 = (Person) session.get(Person.class, new Long(1)); Event aEvent1 = (Event) session.load(Event.class, new Long(6)); // Si association gre de manire unidirectionnelle aPerson1.getEvents().add(aEvent1); 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=? (si equals() et hashCode() redfinies sinon utilisation du proxy!!) insert into PERSON_EVENT (PERSON_ID, EVENT_ID) values (?, ?)

125

20

Oprations du gestionnaire de persistance (3/15)


Rcuprer une instance persistante dans EntityManager :
entitymanager.find(Class clazz, serializable id) session.get()
Person aPerson1 = (Person) em.find(Person.class, new Long(2)); select from PERSON person0_ where person0_.PERSON_ID=?

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

Oprations du gestionnaire de persistance (4/15)


Rendre une instance persistante :
session.save(objet) Pour rendre persistante un instance temporaire (transiante) Gnration dune commande INSERT uniquement excute au moment du lancement de la mthode session.commit() Gnration de lidentificateur de linstance (de type Serializable et retourn par la mthode) sauf si de type assigned ou composite session.persist(objet) ou entityManager.persist(objet) En accord avec les spcifications EJB 3.0 session.merge(objet) ou entityManager.merge(objet) Fusionne une instance dtache avec une instante persistante (existante ou charge depuis la base) Effectue un SELECT avant pour dterminer sil faut faire INSERT ou UPDATE ou rien (JPA)

On reviendra sur ces mthodes pour la persistance des graphes dobjets


Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Pat05], [BK07] et [Gri09] + doc Hibernate 3

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 :

<id name="id" column="EVENT_ID"> <generator class="native"/> </id> ou dans les annotations :


@Id @GeneratedValue @Column(name="EVENT_ID") public Long getId() { return id; }

On y reviendra!!

insert into EVENTS (EVENT_DATE, title, EVENT_ID) values (?, ?, ?)

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 code du transparent prcdent : select nextval ('hibernate_sequence')


insert into EVENTS (EVENT_DATE, title, EVENT_ID) values (?, ?, ?)

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

Oprations du gestionnaire de persistance (5/15)


Rendre persistante les modifications apportes dune instance persistante :
Pas de mthode particulire (automatic dirty checking) Tout modification dune instance persistante transactionnelle (objet charg, sauvegard, cr ou requt par la Session) est rendu persistant par la mthode flush() Surveillance (dirty checking) de toutes les instances persistantes par la session Instance persistante modifie = instance sale (dirty) Synchronisation avec la base dfinitive une fois la transaction sous-jacente valide 130

Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Pat05] et [Gri09] + doc Hbernate 3

automatic dirty checking


// Aprs le code du transparent prcdent Session session = HibernateUtil.getSessionFactory().getCurrentSession(); session.beginTransaction(); Person aPerson1 = (Person) session.load(Person.class, new Long(2)); aPerson1.setAge(32); session.getTransaction().commit();

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

Avec le flush() ou si la requte est ("from Event") :

132

Oprations du gestionnaire de persistance (6/15)


Rendre persistante les modifications apportes dune instance dtache :
Pas de surveillance possible des instances dtaches ncessit de r-attacher les instances en rendant persistant les modifications apportes session.merge(objet) ou entityManager.merge(objet) Effectue un SELECT avant lUPDATE pour rcuprer les donnes dans la base et les fusionner avec les modifications apportes

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

merge versus update (1/2)


Session session = HibernateUtil.getSessionFactory().getCurrentSession(); session.beginTransaction(); Event theEvent = new Event(); theEvent.setTitle("Event1"); theEvent.setDate(new Date()); session.persist(theEvent); session.getTransaction().commit(); theEvent.setTitle("Event2"); //theEvent est dtach Session session2 = HibernateUtil.getSessionFactory().getCurrentSession(); session2.beginTransaction(); session2.update(theEvent); // theEvent redevient persistant session2.getTransaction().commit(); select nextval ('hibernate_sequence')

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

merge versus update (2/2)


Session session = HibernateUtil.getSessionFactory().getCurrentSession(); session.beginTransaction(); Event theEvent = new Event(); theEvent.setTitle("Event1"); theEvent.setDate(new Date()); session.persist(theEvent); session.getTransaction().commit(); theEvent.setTitle("Event2"); //theEvent est dtach Session session2 = HibernateUtil.getSessionFactory().getCurrentSession(); session2.beginTransaction(); // Rcupration du prcdent objet via une requte Event anEvent3 = (Event) session2.createCriteria(Event.class) .add( Restrictions.eq("id", theEvent.getId()) ) .uniqueResult(); session2.update(theEvent); // theEvent redevient persistant session2.getTransaction().commit(); select nextval ('hibernate_sequence')

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

Oprations du gestionnaire de persistance (7/15)


Dtecter automatiquement un tat : Soit pour sauvegarder une instance temporaire en gnrant un nouvel identifiant soit pour mettre jour/rattacher les instances dtaches associes l'identifiant courant session.saveOrUpdate(objet)

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();

select select insert update

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=?

Si on ajoute aprs le 1er saveOrUpdate() :


Event anEvent1 = (Event) session2.get(Event.class, theEvent.getId());

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

Oprations du gestionnaire de persistance (8/15)


Utilisation de update() ou saveOrUpdate()
Dans le cas dun scnario du type du scnario suivant :

1. Chargement dun objet dans une premire session 2. Objet pass la couche utilisateur

3. Modifications effectues sur l'objet


4. Objet retourn la couche logique mtier 5. Persistance de ces modifications ralises en appelant update() dans une seconde session
Maude Manouvrier - Univ. Paris Dauphine repris de la doc Hbernate 3

138

Oprations du gestionnaire de persistance (9/15)


Fonctionnement de saveOrUpdate() : Si objet dj persistant et non mis jour dans la session courante ne fait rien Si un autre objet associ la session avec le mme identifiant lve un exception Si objet sans proprit d'identifiant save() Si identifiant de l'objet avec une valeur assigne un objet nouvellement instanci save() Si objet versionn (par <version> ou <timestamp>) et si proprit de version de mme valeur que celle assigne un objet nouvellement instanci save() Sinon update() 139

Maude Manouvrier - Univ. Paris Dauphine repris de la doc Hbernate 3

27

Oprations du gestionnaire de persistance (10/15)


Fonctionnement de merge() :

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

Maude Manouvrier - Univ. Paris Dauphine repris de la doc Hbernate 3

Oprations du gestionnaire de persistance (11/15)


R-attacher une instance dtache :
Session.lock(objet, LockMode) Diffre de merge() par la non prise en compte des modifications effectues avant le r-attachement de linstance Permet deffectuer une vrification de version pour les objets versionns et de verrouiller lenregistrement en base de donnes LockMode = type de verrouillage NONE : Aucun verrou et pas SELECT pour vrifier la version READ : Aucun verrou mais SELECT pour vrifier la version

!
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

Oprations du gestionnaire de persistance (12/15)


Dtacher une instance persistante : Plus (pas) de surveillance de linstance par le gestionnaire dentits : Plus (pas) aucune modification rendue persistante de manire transparente Erreur en cas de contact avec un proxy Trois moyens de dtacher une instance : En fermant la session : session/entityManager.close() En vidant la session : session/entityManager.clear() En dtachant une instance particulire : session.evict(objet) ou entityManager.detach(object)
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Pat05] et [Gri09] + doc Hbernate 3

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();

select nextval ('hibernate_sequence') Exception in thread "main" org.hibernate.SessionException: Session is closed!

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();

Exception in thread "main" java.lang.IllegalStateException: EntityManager is closed

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();

select nextval ('hibernate_sequence') Pas dinsertion mais valeur de lid initialise !!

Mme comportement avec session.clear() 149

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();

select nextval ('hibernate_sequence') Pas dinsertion mais valeur de lid initialise !!

Mme comportement avec session.evict(object) 150

Oprations du gestionnaire de persistance (13/15)


Rendre un objet transient :
Extraction dfinitive de lentit correspondante dans la base de donnes session.delete(objet) ou entityManager.remove(object) :

Enregistrement correspondant plus(pas) prsent dans la base

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=?

Mme comportement avec session.delete(object) avec chargement tardif par dfaut

152

Oprations du gestionnaire de persistance (14/15)


Possibilit dappeler ces mthodes au sein dun DAO :
/*** Home object for domain model class Departement.*/ public class DepartementHome { private static final Log log = LogFactory.getLog(DepartementHome.class); private final SessionFactory sessionFactory = getSessionFactory();

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

Oprations du gestionnaire de persistance (15/15)


Collections persistantes :
Implmentations des collections Set, List et Map propres Hibernate Utilisation des collections persistantes de la mme manire que pour les collections Java ordinaires. Initialisation par dfaut des variables d'instance avec une instance de HashSet
private Set emailAddresses = new HashSet();

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

Mta-donnes et fichiers de mapping des classes mtiers (1/2)


Fichier de correspondance (mapping) : Fichier XML permettant de faire la correspondance entre les classes persistantes et le modle relationnel Contenant un ensemble de paramtres ou mta-donnes Un fichier par classe de prfrence, dextension hbm.xml et plac dans le mme rpertoire que le fichier .java de la classe Langage de mapping Java-centrique : mappings construits partir des dclarations des classes persistantes et non des dclarations des tables Rfrence la DTD :
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> (http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd depuis la version 3.6)
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Gri09] et de la doc dHibernate 3

155

35

Mta-donnes et fichiers de mapping des classes mtiers (2/2)


lments des fichiers de mapping XML :
Dclaration de la DTD lment racine : <hibernate-mapping> Possibilit dy dfinir lattribut package pour viter de le spcifier chaque dclaration de classe et dassociation <class> : pour spcifier la correspondance entre une relation de base de donnes et une classe <property> : pour spcifier la correspondance entre une colonne de relation et une proprit de classe <many-to-one> et <one-to-one> : correspondance dune association vers une entit pour spcifier la

<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

Dans la suite : prsentation des annotations en parallle du XML 157

36

Mta-donnes et fichiers de mapping des classes mtiers

Description de la balise <class>



Balise XML

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">

@Entity Annotations @Table(name="departement",schema="public") public class Departement { }

+ 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

Mta-donnes et fichiers de mapping des classes mtiers

Description de llment <id> (1/3)


Identit relationnelle de lentit persistante
Pour dfinir la correspondance entre la proprit identificateur de la classe et la cl primaire de la relation Obligatoire pour toute classe reprsente par une relation de base de donnes name : nom de la proprit identifiant si non rfrenc Hibernate considre que la classe na pas didenifiant type : type Hibernate dduction par Hibernate du type SQL et du type Java - dtermin par dfaut par introspection de la classe column : nom de la colonne cl primaire par dfaut de mme nom que la proprit (attribut name) unsaved-value : valeur de la proprit d'identifiant pour indiquer que l'instance est nouvellement instancie (non sauvegarde), et la distinguer des instances transients sauvegardes ou charges dans une session prcdente par dfaut null access : stratgie utilise par Hibernate pour accder aux valeurs des proprits par dfaut property

Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Gri09] et de la doc dHibernate 3

159

37

Mta-donnes et fichiers de mapping des classes mtiers

Description de la balise <id> (2/3)


<generator> : gnration automatique did
Pratique conseille : cl artificielle Gnrateurs disponibles :
increment : gnre des identifiants de type long, short ou int qui ne sont uniques que si aucun autre processus n'insre de donnes dans la mme table native : choisit le gnrateur en fonction de la base de donnes (sequence pour Oracle ou PostgreSQL, identity pour MYSQL par ex.) assigned : laisse l'application affecter un identifiant l'objet avant que la mtode save() ou persist() ne soit appele.Stratgie par dfaut si aucun <generator> n'est spcifi + dautres cf. doc Hibernate <id name="id" column="PERSON_ID"> <generator class="native"/> </id>
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Gri09] et de la doc dHibernate 3

160

Mta-donnes et fichiers de mapping des classes mtiers

Description de la balise <id> (3/3)


Possibilit de spcifier le gnrateur un seul endroit pour faciliter le changement de stratgie
Exemple du projet caveatemptor dHibernate : Dans le fichier globals.dtd :
<!ENTITY idgenerator "identity" >

Dans lentte de chaque fichier de mapping XML :


<?xml version="1.0"?> <!DOCTYPE hibernate-mapping SYSTEM "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" [ <!ENTITY % globals SYSTEM "classpath://auction/persistence/globals.dtd"> %globals; ]>

Dans chaque fichier de mapping XML :


<id name= "id" type=" column= <generator class= "&idgenerator;" /> </id>
Maude Manouvrier - Univ. Paris Dauphine http://downloads.jboss.org/hibernate/caveatemptor/

161

38

Mta-donnes des classes mtiers

Annotation pour lidentificateur


@Id : dfinition de la proprit identifiant
Placement de lannotation avant le getter pour spcifier que laccs est indirect (~ property en XML) ou avant la proprit si laccs est direct comportement JPA par dfaut Possibilit dutiliser lannotation @AccessType("<startegy>") Hibernate

Gnrateurs disponibles : AUTO, TABLE, IDENTITY, SEQUENCE


@Id @GeneratedValue(strategy=GenerationType.AUTO) public Long getId() { ... }

cf. doc Hibernate 162

Maude Manouvrier - Univ. Paris Dauphine

Mta-donnes et fichiers de mapping des classes mtiers

Description de llment <composite-id> (1/2)


Cl composite :
Gestion interne : Possibilit de faire correspondre plusieurs attributs de la classe comme proprits identifiantes <key-property> : pour faire correspondre une colonne sans contrainte de cl trangre vers une autre relation <key-many-to-one> : pour faire correspondre une colonne soumise une contrainte de cl trangre vers une autre relation

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

Mta-donnes et fichiers de mapping des classes mtiers

Description de llment <composite-id> (2/2)


<class name="test1_package.Enseignement" table="enseignement" schema="public"> <composite-id name="id" class="test1_package.EnseignementId"> <key-property name="enseignementId" type="int"> <column name="enseignement_id" /> </key-property> <key-property name="departementId" type="int"> <column name="departement_id" /> </key-property> </composite-id> </class> public class EnseignementId implements java.io.Serializable { // Fields private int enseignementId; private int departementId; public EnseignementId() {} /** default constructor */ public boolean equals(Object other) { } public int hashCode() {} // Property accessors } public class Enseignement implements java.io.Serializable { // Fields private EnseignementId id; }
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Gri09] et de la doc dHibernate 3

164

Mta-donnes des classes mtiers

Annotations pour les cls composites (1/2)


@Embeddable : pour indiquer quune classe embarque dans une autre
@Embeddable public class EnseignementId { // Fields private int enseignementId; private int departementId; // Property accessors @Column(name="enseignement_id", unique=false, nullable=false, insertable=true, updatable=true) public int getEnseignementId() { return this.enseignementId; } @Column(name="departement_id", unique=false, nullable=false, insertable=true, updatable=true) public int getDepartementId() { return this.departementId; } }
Maude Manouvrier - Univ. Paris Dauphine

165

40

Mta-donnes des classes mtiers

Annotations pour les cls composites (2/2)


@EmbeddedId : Pour indiquer que lidentificateur est composite et est gr par une autre classe
@Entity @Table(name="enseignement",schema="public") public class Enseignement { // Fields private EnseignementId id; // Property accessors @EmbeddedId @AttributeOverrides( { @AttributeOverride(name="enseignementId", column=@Column(name="enseignement_id) ), @AttributeOverride(name="departementId", column=@Column(name="departement_id) } ) public EnseignementId getId() { return this.id; }
Maude Manouvrier - Univ. Paris Dauphine

166

Mta-donnes et fichiers de mapping des classes mtiers

Description de la balise <natural-id> (1/2)


Recommandation de l'utilisation de cl primaire gnre Mais ncessit didentifier des cls mtier (naturelles) pour toutes les entits Utilisation de la balise <natural-id> Recommandation d'implmenter equals() et hashCode() pour comparer les cls naturelles de l'entit
<natural-id mutable="true|false"/> <property ... /> <many-to-one ... /> ...... </natural-id>

Maude Manouvrier - Univ. Paris Dauphine repris et adapt de la doc dHibernate 3

167

41

Mta-donnes et fichiers de mapping des classes mtiers

Description de la balise <natural-id> (2/2)


Fichier de correspondance
<class name="User" table="AuctionUser" lazy="true"> <comment>Users may bid for or sell auction items.</comment> <id name="id"> <generator class="native"/> </id> <natural-id mutable="true"> <property name="userName" length="10"/> </natural-id> </class> CREATE TABLE Auctionuser ( id SERIAL NOT NULL, username varchar(10) NOT NULL, CONSTRAINT auctionuser_pkey PRIMARY KEY (id), CONSTRAINT auctionuser_username_key UNIQUE (username) )
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de la doc dHibernate 3

Instruction SQL

168

Mta-donnes des classes mtiers

Annotation pour les cls mtiers : @NaturalId


@Entity public class Citizen { @Id @GeneratedValue private Integer id; private String firstname; private String lastname; @NaturalId @ManyToOne private State state; @NaturalId private String ssn; ... } // Exemple de requte List results = s.createCriteria( Citizen.class ) .add( Restrictions.naturalId() .set( "ssn", "1234" ) .set( "state", ste ) ).list();
Maude Manouvrier - Univ. Paris Dauphine repris de la doc Hibernate

169

42

Mta-donnes des classes mtiers

Annotation pour les contraintes dunicit


@UniqueConstraint en conjonction avec @Table
@Entity @Table(name="departement",schema="public", uniqueConstraints = { @UniqueConstraint( columnNames = { "nom_departement" } ) } ) public class Departement { @Column(name="nom_departement", unique=true, nullable=false, insertable=true, updatable=true, length=25) public String getNomDepartement() { return this.nomDepartement; } }
Maude Manouvrier - Univ. Paris Dauphine

170

Mta-donnes et fichiers de mapping des classes mtiers

Description de llment <property> (1/2)


Dclaration de proprit persistante :
name : nom de la proprit, avec une lettre initiale en minuscule (cf. convention JavaBean) column : nom de la colonne de base de donnes correspondante par dfaut de mme nom que la proprit type : nom indiquant le type Hibernate - dtermin par dfaut par introspection de la classe update, insert : indique que les colonnes mappes doivent tre incluses dans les UPDATE et/ou les INSERT - par dfaut true Mettre les deux false empche la propagation en base de donnes (utile si vous savez qu'un trigger affectera la valeur la colonne) access : stratgie utilise par Hibernate pour accder aux valeurs des proprits par dfaut property unique : Gnre le DDL d'une contrainte d'unicit pour les colonnes - optionnel not-null : Gnre le DDL d'une contrainte de non nullit pour les colonnes optionnel + dautres cf. doc Hibernate

Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Gri09] et de la doc dHibernate 3

171

43

Mta-donnes et fichiers de mapping des classes mtiers

Description de llment <property> (2/2)


<hibernate-mapping>
<class name="events.Event" table="EVENTS"> <id name="id" column="EVENT_ID"> <generator class="native"/> </id> <property name="date" type="timestamp" column="EVENT_DATE"/> <property name="title"/> </class> </hibernate-mapping>
<property name="nomDepartement" type="string"> <column name="nom_departement" length="25" not-null="true" unique="true" /> </property>
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Gri09] et de la doc dHibernate 3

172

Mta-donnes des classes mtiers

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

Mta-donnes et fichiers de mapping des classes mtiers

Correspondance des associations (1/12)


Partie la plus complexe dont dpend les performances de lapplication Balises de correspondance des collections : <set>, <list>; <map>, <bag>, <array> Tags de correspondance des cardinalits/multiplicits : <one-to-one>, <many-to-one>, <many-tomany> Si correspondance dune collection : utilisation dune balise de collection contenant un tag de cardinalit Si correspondance dune association uni ou bidirectionnelle vers une entit : utilisation des balises de cardinalit 174

Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Gri09] et de la doc dHibernate 3

Mta-donnes et fichiers de mapping des classes mtiers

Correspondance des associations (2/12)


<many-to-one> et <one-to-one> : associations uni ou bi-directionnelle vers une entit
name : nom de la proprit column : nom de la cl trangre possibilit de balise <column> class : nom de la classe associe optionnel par dfaut le type de la proprit dtermin par rflexion cascade : Propagation des oprations de l'objet pre vers les objets associs optionnel lazy : pour le chargement de lassociation valeur : proxy|no-proxy|false optionnel par dfaut : proxy fetch : Pour choisir entre le chargement de type outer-join ou le chargement par select successifs - optionnel par dfaut select update, insert : Indication des colonnes mappes devant tre incluses dans des UPDATE et/ou des INSERT - optionnel par dfaut true + dautres cf. doc Hibernate

Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Gri09] et de la doc dHibernate 3

175

45

Mta-donnes et fichiers de mapping des classes mtiers

Correspondance des associations (3/12)


Exemple dassociation uni-directionnelle :
<class name="test1_package.Enseignement" table="enseignement" schema="public">

<many-to-one name="departement" class="test1_package.Departement"> <column name="departement_id" not-null="true" /> </many-to-one>

</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

Mta-donnes des classes mtiers

Correspondance des associations (3bis/12)


Exemple dannotation pour une association uni-directionnelle : Enseignement *
1

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

Mta-donnes et fichiers de mapping des classes mtiers

Correspondance des associations (4/12)


<one-to-one> : constrained : dans le cas de cls primaires partages entre deux relations

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

Mta-donnes et fichiers de mapping des classes mtiers

Correspondance des associations (4/12)


<one-to-one> : Stratgie Hibernate spciale de gnration d'identifiants par foreign <class name="person" table="PERSON"> <id name="id" column="PERSON_ID"> <generator class="foreign"> <param name="property">employee</param> </generator> </id> ... <one-to-one name="employee" class="Employee" constrained="true"/> </class> Attribution de la mme valeur de cl primaire une instance frachement enregistre de Person et l'instance de Employee rfrence par la proprit employee de Person
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Gri09] et de la doc dHibernate 3

179

47

Mta-donnes des classes mtiers

Correspondance des associations (4bis/12)


Annotation @OneToOne :
@Entity public class Employee { ... @Id public Long getId() { return id; } @OneToOne(cascade = CascadeType.ALL) @PrimaryKeyJoinColumn public Person getPerson() { return person; } ... } @Entity public class Person { ... @GeneratedValue(generator = "system-foreign") @GenericGenerator(name = "system-foreign", strategy = "foreign", parameters = { @Parameter(name = "property", value = "employee") }) public String getId() {return _id;} @OneToOne(mappedBy = "employee") public Employee getEmployee() {return _employee;} ... }
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Gri09] et de la doc dHibernate 3

180

Mta-donnes et fichiers de mapping des classes mtiers

Correspondance des associations (5/12)


<component> : associations vers une valeur Pour faire correspondre deux classes lies par une association one-to une seule relation de base de donnes Classe rfrence dans la balise <component> = valeur (par opposition entit - i.e. pas de cycle de vie propre et pas de possibilit dtre rfrence par plusieurs entits) name : nom de la proprit class : nom de la classe du composant optionnel par dfaut le type de la proprit dtermin par rflexion + dautres cf. doc Hibernate lazy : pour charger le composant ds le premier accs la variable d'instance par dfaut false On reviendra sur les stratgies de chargement
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Gri09] et de la doc dHibernate 3

181

48

Mta-donnes et fichiers de mapping des classes mtiers

Correspondance des associations (6/12)


<component> : associations vers une valeur
<class name="Person" > <component name="Address"> <property name="address"/> <property name="zip"/> <property name="country"/> </component> </class> Une classe Person et une classe Address Mais une seule relation de base de donnes : Person Possibilit dinclure une rfrence au conteneur : balise parent <parent name="AdressedPerson"/> 182 Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Gri09] et de la doc dHibernate 3

Mta-donnes et fichiers de mapping des classes mtiers

Correspondance des associations (6bis/12)


@Embeddable public class Adresse { private int numero; private String rue; private String ville; . . . } @Entity public class Person { @Embedded private Adresse adresse; ou @Embedded Adresse getAdresse() { }; . . . }

Maude Manouvrier - Univ. Paris Dauphine repris de [Gri09]

183

49

Mta-donnes et fichiers de mapping des classes mtiers

Correspondance des associations (6ter/12)


@Embeddable public class Address implements Serializable { @Column(length = 255, nullable = false) private String street; @Column(length = 16, nullable = false) private String zipcode; @Column(length = 255, nullable = false) private String city; } @Entity @Table(name = "USERS") public class User implements Serializable { @Embedded @AttributeOverrides( { @AttributeOverride(name = "street", column = @Column(name="HOME_STREET", length = 255) ), @AttributeOverride (name = "zipcode", column = @Column(name="HOME_ZIPCODE", length = 16) ), @AttributeOverride (name = "city", column = @Column(name="HOME_CITY", length = 255) ) }) private Address homeAddress; }
Maude Manouvrier - Univ. Paris Dauphine repris de http://downloads.jboss.org/hibernate/caveatemptor/

184

Mta-donnes et fichiers de mapping des classes mtiers

Correspondance des associations (7/12)


Correspondance des collections : Implmentations des collections Set, List et Map propres Hibernate Balise propre chaque type dinterface : <set>, <list>, <map> etc.
name : nom de la proprit contenant la collection table : nom de la relation contenant la collection - optionnel par dfaut nom de la proprit - non utilis pour les associations oneto-many lazy : pour dsactiver l'initialisation tardive - par dfaut = true inverse : Pour dfinir la collection comme extrmit "inverse" de l'association bidirectionnelle + dautres cf. doc Hibernate + prcision des cardinalit et type de collections
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Gri09] et de la doc dHibernate 3

185

50

Mta-donnes et fichiers de mapping des classes mtiers

Correspondance des associations (8/12)


Balise <key column= > :
Pour spcifier comment effectuer la jointure entre les deux relations entrant en jeu dans lassociation to-many column : nom de la cl trangre
<set name="events" table="PERSON_EVENT"> <key column="PERSON_ID"/> <many-to-many column="EVENT_ID" class="events.Event"/> </set> <set name="enseignements" inverse="true"> <key> <column name="departement_id" not-null="true" /> </key> <one-to-many class="package.Enseignement" /> </set>

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

Mta-donnes et fichiers de mapping des classes mtiers

Correspondance des associations (8bis/12)


@Entity @Table(name="departement",schema="public", uniqueConstraints = { @UniqueConstraint( columnNames = { "nom_departement" } ) }) public class Departement implements java.io.Serializable {

@OneToMany(cascade={CascadeType.ALL}, fetch=FetchType.LAZY, mappedBy="departement") public Set<Enseignement> getEnseignements() { return this.enseignements; }

}
@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

Mta-donnes et fichiers de mapping des classes mtiers

Correspondance des associations (9/12)


Balise <element> : collection de valeurs column : nom de la colonne contenant les valeurs de l'lment de la collection formula : formule SQL utilise pour valuer l'lment optionnel type : type de l'lment de la collection
<set name="emailAddresses" table="PERSON_EMAIL_ADDR"> <key column="PERSON_ID"/> <element type="string" column="EMAIL_ADDR"/> </set> Balise quivalente lannotation @ElementCollection
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Gri09] et de la doc dHibernate 3

188

Mta-donnes et fichiers de mapping des classes mtiers

Correspondance des associations (9bis/12)


Annotation @ElementCollection : collection de valeurs
@Entity public class User { [...] public String getLastname() { ...} @ElementCollection @CollectionTable(name="Nicknames", joinColumns=@JoinColumn (name="user_id")) @Column(name="nickname") public Set<String> getNicknames() { ... } }

Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Gri09] et de la doc dHibernate 3

189

52

Mta-donnes et fichiers de mapping des classes mtiers

Correspondance des associations (10/12)


Balise <one-to-many> : Liaison de deux relations de BD de deux classes par une cl trangre class : nom de la classe associe not-found : spcification de comment grer les identifiants cachs qui rfrencent des lignes manquantes optionnel par dfaut exception
<! Dans le fichier Departement.hnm.xml > <set name="enseignements" inverse="true">
<key> <column name="departement_id" not-null="true" /> </key> <one-to-many class="test1_package.Enseignement" /> </set>

Balise quivalente lannotation @OneToMany


Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Gri09] et de la doc dHibernate 3

190

Mta-donnes et fichiers de mapping des classes mtiers

Correspondance des associations (10bis/12)


<one-to-many> et @OneToMany : exemple
<set name="categorizedItems" cascade="all, delete-orphan" inverse="true" fetch="subselect"> <key column="CATEGORY_ID" not-null= "true"/> <one-to-many class="CategorizedItem"/> </set> @OneToMany(cascade = CascadeType.ALL, mappedBy = "category") @org.hibernate.annotations.Cascade(value = org.hibernate.annotations.CascadeType.DELETE_ORPHAN) @org.hibernate.annotations.Fetch (org.hibernate.annotations.FetchMode.SUBSELECT) private Set<CategorizedItem> categorizedItems = new HashSet<CategorizedItem>();

Maude Manouvrier - Univ. Paris Dauphine repris de http://downloads.jboss.org/hibernate/caveatemptor/

191

53

Mta-donnes et fichiers de mapping des classes mtiers

Correspondance des associations (11/12)


Balise <many-to-many> : en cas de cration dune relation dite dassociation column : nom de la colonne cl trangre class : nom de la classe associe fetch : Activation des rcuprations par jointures externes ou par selects squentiels pour cette association - par dfaut join
Dans le fichier Person.hbm.xml <set name="events" table="PERSON_EVENT"> <key column="PERSON_ID"/> <many-to-many column="EVENT_ID" class="events.Event"/> </set> <set name="participants" table="PERSON_EVENT" inverse="true"> <key column="EVENT_ID"/> <many-to-many column="PERSON_ID" class="events.Person"/> </set>

Dans le fichier Event.hbm.xml

Balise quivalente lannotation @ManyToMany


Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Gri09] et de la doc dHibernate 3

192

Mta-donnes et fichiers de mapping des classes mtiers

Correspondance des associations (12/12)


Correspondance des associations :
Ne pas oublier de grer les deux extrmits des associations En relationnel, contrairement au Java, ralisation dune seule opration : mise jour ou initialisation de la cl trangre En Java : deux oprations une chaque extrmit de lassociation Ne pas oublier de spcifier inverse= "true" lune des extrmit dans le fichier de correspondance (ou lannotation mappedBy dans lune des classes Java) pour viter la cration de deux ordres SQL Penser regrouper les mthodes dinstanciation au sein dune mthode mtier de cohrence 193 Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Gri09] et de la doc dHibernate 3

54

Mta-donnes et fichiers de mapping des classes mtiers

Correspondance des cls naturelles



Fichier de correspondance

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

Mta-donnes et fichiers de mapping des classes mtiers

Correspondance dune hirarchie de classes (1/10)


Trois stratgies d'hritage de base possible sous Hibernate : Une relation de BD par hirarchie de classe Une relation de BD par classe

- Avec ou sans discriminateur


Une relation de BD par classe concrte - Avec ou sans polymorphisme implicite Possibilit d'utiliser diffrentes stratgies de mapping pour diffrentes branches d'une mme hirarchie
195

Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Gri09] et de la doc dHibernate 3

55

Mta-donnes et fichiers de mapping des classes mtiers

Correspondance dune hirarchie de classes (2/10)


Une relation par hirarchie de classes :
Correspondance de la totalit de la hirarchie au sein dune seule relation Balise <subclass> : pour introduire une sous-classe de la racine de la hirarchie (pouvant contenir une sous-balise <subclass>) Balise <discriminateur> : pour indiquer la colonne qui contient la valeur permettant de diffrencier les lignes correspondant aux sous-classes Rappels : Pas de jointure ncessaire Gestion du polymorphisme Mais pas de contrainte NOT NULL do possibilit dincohrence

Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Gri09] et de la doc dHibernate 3

196

Mta-donnes et fichiers de mapping des classes mtiers

Correspondance dune hirarchie de classes (3/10)


Une relation par hirarchie de classes :
<class name="Payment" table="PAYMENT"> <id name="id" type="long" column="PAYMENT_ID"> <generator class="native"/> </id> <discriminator column="PAYMENT_TYPE" type="string"/> <property name="amount" column="AMOUNT"/> ... <subclass name="CreditCardPayment" discriminator-value="CREDIT"> <property name="creditCardType" column="CCTYPE"/> ... </subclass> <subclass name="CashPayment" discriminator-value="CASH"> ... </subclass> <subclass name="ChequePayment" discriminator-value="CHEQUE"> ... </subclass> </class>
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Gri09] et de la doc dHibernate 3

197

56

Mta-donnes et fichiers de mapping des classes mtiers

Correspondance dune hirarchie de classes (3bis/10)


Une relation par hirarchie de classes :
@Entity @Inheritance(strategy=InheritanceType.SINGLE_TABLE) @DiscriminatorColumn( name="PAYMENT-TYPE", discriminatorType=DiscriminatorType.STRING ) @DiscriminatorValue("PAYMENT") public abstract class Payment { ... } @Entity @DiscriminatorValue("CREDIT") public class CreditCardPayment extends Payment { ... }

Maude Manouvrier - Univ. Paris Dauphine

198

Mta-donnes et fichiers de mapping des classes mtiers

Correspondance dune hirarchie de classes (4/10)


Une relation par classe :
Correspondance de chaque classe (abstraite ou concrte) avec une relation de base de donnes Balise <joined-subclass> : Pour introduire une sous-classe de la racine de la hirarchie (pouvant contenir une sous-balise <joined-subclass>) Contenant une balise <key> pour spcifier la cl trangre vers la relation correspondant la classe mre (cl primaire de la relation correspondant la sous-classe) Rappels : Ncessit de jointures Garantie de la cohrence Accs au polymorphisme

Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Gri09] et de la doc dHibernate 3

199

57

Mta-donnes et fichiers de mapping des classes mtiers

Correspondance dune hirarchie de classes (5/10)


Une relation par classe :
<class name="Payment" table="PAYMENT"> <id name="id" type="long" column="PAYMENT_ID"> <generator class="native"/> </id> <property name="amount" column="AMOUNT"/> ... <joined-subclass name="CreditCardPayment" table="CREDIT_PAYMENT"> <key column="PAYMENT_ID"/> <property name="creditCardType" column="CCTYPE"/> ... </joined-subclass> <joined-subclass name="CashPayment" table="CASH_PAYMENT"> <key column="PAYMENT_ID"/> ... </joined-subclass> <joined-subclass name="ChequePayment" table="CHEQUE_PAYMENT"> <key column="PAYMENT_ID"/> ... </joined-subclass> </class>
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Gri09] et de la doc dHibernate 3

200

Mta-donnes et fichiers de mapping des classes mtiers

Correspondance dune hirarchie de classes (5bis/10)


Une relation par classe :
@Entity @Inheritance(strategy=InheritanceType.JOINED) public abstract class Payment implements Serializable { ... } // Pas besoin de spcifier quoique cela soit pour les // sous-classes @Entity public class CreditCardPayment extends Payment { ... } // Possibilit de spcifier explicitement le nom de // colonne de jointure @Entity @PrimaryKeyJoinColumn(name="CHEQUE_ID") public class ChequePayment extends Payment { ... }
Maude Manouvrier - Univ. Paris Dauphine

201

58

Mta-donnes et fichiers de mapping des classes mtiers

Correspondance dune hirarchie de classes (6/10)


Une relation par classe avec discriminateur :
Mlange des deux stratgies prcdentes Mlange des balises <subclass>, <discriminateur> et <join>
<class name="Payment" table="PAYMENT"> <id name="id" type="long" column="PAYMENT_ID"> <generator class="native"/> </id> <discriminator column="PAYMENT_TYPE" type="string"/> ... <subclass name="CreditCardPayment" discriminator-value="CREDIT"> <join table="CREDIT_PAYMENT"> <key column="PAYMENT_ID"/> <property name="creditCardType" column="CCTYPE"/> ... </join> </subclass> ... </class>

stratgie : Possibilit de crer une association polymorphique vers la classe


racine en utilisant <many-to-one> pour chaque sous-classe :
<many-to-one name="payment" column="PAYMENT_ID"
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Gri09] et de la doc dHibernate 3

class="Payment"/>

202

Mta-donnes et fichiers de mapping des classes mtiers

Correspondance dune hirarchie de classes (7/10)


Une relation par classe concrte :
Balise <union-subclass> Contraintes respecter : Mme nom de colonne pour toutes les classes filles pour toute proprit de la classe mre mise en correspondance avec la base de donnes Stratgie du gnrateur d'identifiant non permise dans l'hritage de classes filles par union abstract="true" : pour une classe mre abstraite (sinon ncessit davoir une relation de BD correspondante) Rappels : Insertion dans une seule relation par instance (si classe mre abstraite) Slection par UNION ( + lourd et- performant) Garantie de lintgrit des donnes Accs au polymorphisme

Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Gri09] et de la doc dHibernate 3

203

59

Mta-donnes et fichiers de mapping des classes mtiers

Correspondance dune hirarchie de classes (8/10)


Une relation par classe concrte :
<class name="Payment"> <id name="id" type="long" column="PAYMENT_ID"> <generator class="sequence"/> </id> <property name="amount" column="AMOUNT"/> ... <union-subclass name="CreditCardPayment" table="CREDIT_PAYMENT"> <property name="creditCardType" column="CCTYPE"/> ... </union-subclass> <union-subclass name="CashPayment" table="CASH_PAYMENT"> ... </union-subclass> <union-subclass name="ChequePayment" table="CHEQUE_PAYMENT"> ... </union-subclass> </class>
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Gri09] et de la doc dHibernate 3

204

Mta-donnes et fichiers de mapping des classes mtiers

Correspondance dune hirarchie de classes (8bis/10)


Une relation par classe concrte :
@Entity @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) public abstract class Payment implements Serializable {... } @Entity @Table(name="CREDIT_PAYMENT") public class CreditCardPayment extends Payment { ... }

Maude Manouvrier - Univ. Paris Dauphine

205

60

Mta-donnes et fichiers de mapping des classes mtiers

Correspondance dune hirarchie de classes (9/10)


Une relation par classe concrte avec polymorphisme implicite:
<class name="CreditCardPayment" table="CREDIT_PAYMENT"> <id name="id" type="long" column="CREDIT_PAYMENT_ID"> <generator class="native"/> </id> <property name="amount" column="CREDIT_AMOUNT"/> ... </class> <class name="CashPayment" table="CASH_PAYMENT"> <id name="id" type="long" column="CASH_PAYMENT_ID"> <generator class="native"/> </id> <property name="amount" column="CASH_AMOUNT"/> ... </class> <class name="ChequePayment" table="CHEQUE_PAYMENT"> <id name="id" type="long" column="CHEQUE_PAYMENT_ID"> <generator class="native"/> </id> <property name="amount" column="CHEQUE_AMOUNT"/> ... </class>
Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Gri09] et de la doc dHibernate 3

206

Mta-donnes et fichiers de mapping des classes mtiers

Correspondance dune hirarchie de classes (9bis/10)


Une relation par classe concrte avec polymorphisme implicite:
@MappedSuperclass public abstract class Payment implements Serializable {... } @Entity @Table(name="CREDIT_PAYMENT") @AttributeOverride( name="overrided_att", column = @Column(name="column") ) @AssociationOverride( name="association", joinColumns = @JoinColumn(name="association_fk") ) public class CreditCardPayment extends Payment { ... }

Maude Manouvrier - Univ. Paris Dauphine repris et adapt de la doc dHibernate 3

207

61

Mta-donnes et fichiers de mapping des classes mtiers

Correspondance dune hirarchie de classes (10/10)


Une relation par classe concrte avec polymorphisme implicite: Association polymorphique dfinie par
<any> <any name="payment" meta-type="string" id-type="long"> <meta-value value="CREDIT" class="CreditCardPayment"/> <meta-value value="CASH" class="CashPayment"/> <meta-value value="CHEQUE" class="ChequePayment"/> <column name="PAYMENT_CLASS"/> <column name="PAYMENT_ID"/> </any>

Prfrer la stratgie par union

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

Rcupration des instances persistantes (1/3)


Chargement la demande ou tardif (lazy loading) : Pour anticiper les problmes de performance dus au chargement de gros graphes dobjets Possibilit de charger les entits et collections dentits persistantes en une fois ou de manire progressive Configuration des fichiers de mapping / annotations et possibilit de redfinir les paramtres lexcution Requtes : HQL (Hibernate Query Language) EJB-QL (EJB Query Language) API Criteria Requtes natives en SQL (Native Query)

Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Pat05] et de la doc dHibernate 3

209

62

Rcupration des instances persistantes (2/3)


Stratgies de chargement dHibernate3 :
Chargement par jointure : Rcupration de linstance ou la collection dans un mme SELECT, en utilisant un OUTER JOIN Chargement par select : Utilisation dun second SELECT pour rcuprer l'instance ou la collection Chargement tardif second SELECT excut uniquement lors de laccs rel lassociation Chargement par sous-select : Utilisation dun second SELECT pour rcuprer les associations pour toutes les entits rcupres dans une requte ou un chargement pralable Chargement tardif second SELECT excut uniquement lors de laccs rel lassociation Chargement par lot : stratgie d'optimisation pour le chargement par SELECT = rcupration dun lot d'instances ou de collections en un seul SELECT en spcifiant une liste de cl primaire ou de cl trangre

Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Pat05] et de la doc dHibernate 3

210

Rcupration des instances persistantes (3/3)


Types de chargement dHibernate3 :
Chargement immdiat dune association, une collection ou un attribut : ds le chargement de lobjet auquel appartient llment Chargement tardif d'une collection : lors de linvocation dune mthode sur cette collection par l'application (mode de chargement par dfaut pour les collections) Chargement "super tardif" d'une collection : rcupration individuelle des lments de la collection depuis la base de donnes lorsque ncessaire pas de chargement de toute la collection en mmoire sauf si absolue ncessit (bien adapt aux trs grandes collections) Chargement par proxy dune association vers un seul objet : lors de lappel sur l'objet associ d'une mthode autre que le getter sur l'identifiant est appele Chargement "sans proxy" dune association vers un seul objet : lors de laccs cet objet Approche moins tardive que par proxy mais plus transparente Chargement tardif des attributs : un seul attribut ou objet associ charg lors de son accs

Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Pat05] et de la doc dHibernate 3

211

63

Rcupration des instances persistantes

Paramtres de chargement (1/3)


Par dfaut dans Hibernate 3 : Chargement tardif par SELECT collections ! Stratgie diffrente en JPA!! pour les

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

Rcupration des instances persistantes

Paramtres de chargement (2/3)


Valeurs de fetch : select : valeur par dfaut - excution dun ordre SELECT supplmentaire la demande pour rcuprer les informations join : utilisation dune jointure externe (left outer join) pour rcuprer en une requte la partie du graphe concern fetch disponible pour les balises <many-toone>, <one-to-one>, <many-to-many> et pour les collections et balise <join>
213

Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Pat05] et de la doc dHibernate 3

64

Rcupration des instances persistantes

Paramtres de chargement (3/3)


Affectation par la stratgie de chargement dfinie par fetch dans les fichiers de mapping : Rcupration via get() ou load() Rcupration implicite lors de la navigation travers une association Requtes de type Criteria Requtes HQL si utilisation du chargement par subselect En gnral : conservation du comportement par dfaut et surcharge pour une transaction particulire via HQL ou API Criteria
214

Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Pat05] et de la doc dHibernate 3

Exemples de stratgies de chargement (1/4)


Chargement tardif (lazy) par dfaut pour les deux collections events et participants : Person aPerson1 = (Person) session.get(Person.class, new Long(4)); select from PERSON person0_ where person0_.PERSON_ID=? Chargement agressif (eager) pour la collection events avec stratgie par dfaut (select): Person aPerson1 = (Person) session.get(Person.class, new Long(4)); 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=? Chargement agressif pour la collection events avec stratgie charg. par jointure (join) : Person aPerson1 = (Person) session.get(Person.class, new Long(4)); select from PERSON person0_ left outer join PERSON_EVENT events1_ on person0_.PERSON_ID=events1_.PERSON_ID left outer join EVENTS event2_ on events1_.EVENT_ID=event2_.EVENT_ID where person0_.PERSON_ID=?

215

65

Exemples de stratgies de chargement (2/4)


Chargement agressif pour les deux collections et avec stratgie charg. par sous-select pour participants : Person aPerson1 = (Person) session.get(Person.class, new Long(2)); // La personne 2 est associe 2 vnements dont un associ 2 // autres personnes 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 PERSON_EVENT participan0_ inner join PERSON person1_ on participan0_.PERSON_ID=person1_.PERSON_ID where participan0_.EVENT_ID in (select event1_.EVENT_ID from PERSON_EVENT events0_ inner join EVENTS event1_ on events0_.EVENT_ID=event1_.EVENT_ID where events0_.PERSON_ID=?) select from PERSON_EVENT events0_ inner join EVENTS event1_ on events0_.EVENT_ID=event1_.EVENT_ID where events0_.PERSON_ID=? select from PERSON_EVENT events0_ inner join EVENTS event1_ on events0_.EVENT_ID=event1_.EVENT_ID where events0_.PERSON_ID=? select from PERSON_EVENT participan0_ inner join PERSON person1_ on participan0_.PERSON_ID=person1_.PERSON_ID where participan0_.EVENT_ID in (select event1_.EVENT_ID from PERSON_EVENT events0_ inner join EVENTS event1_ on events0_.EVENT_ID=event1_.EVENT_ID where events0_.PERSON_ID=?)

216

Exemples de stratgies de chargement (3/4)


Table PERSON_EVENT

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

Exemples de stratgies de chargement (4/4)


Chargement agressif pour les deux collections et avec stratgie charg. par select pour participants : Person aPerson1 = (Person) session.get(Person.class, new Long(2)); // La personne 2 est associe 2 vnements dont un associ 2 // autres personnes 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 PERSON_EVENT participan0_ inner join PERSON person1_ on participan0_.PERSON_ID=person1_.PERSON_ID where participan0_.EVENT_ID=? 2 fois car 2 vnements au lieu du sous select!! select from PERSON_EVENT events0_ inner join EVENTS event1_ on events0_.EVENT_ID=event1_.EVENT_ID where events0_.PERSON_ID=? select from PERSON_EVENT events0_ inner join EVENTS event1_ on events0_.EVENT_ID=event1_.EVENT_ID where events0_.PERSON_ID=? select from PERSON_EVENT participan0_ inner join PERSON person1_ on participan0_.PERSON_ID=person1_.PERSON_ID where participan0_.EVENT_ID=? 2 fois car 2 vnements au lieu du sous select!!

Faire exo 1 exam fv.. 2012

218

Requtes

Requte HQL (1/4)


"Langage de requtes orientes objet" ou encapsulation du SQL selon une logique oriente objet Requtes HQL (et SQL natives) reprsentes avec une instance de org.hibernate.Query Obtention dune Query en utilisant la Session courante : session.createQuery (string) Clauses : from, select, where Invocation de la mthode list() retour du rsultat sous forme de liste
219

List result = session.createQuery("from Event").list();


Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Pat05] et de la doc dHibernate 3

67

Requtes

Requte HQL (2/4)


from : Clause suivie dun nom de classe et non de relation de BD : from Event Possibilit dappliquer la clause sur tout type de classe (abstraite ou concrte, interface) select : Non obligatoire Raisonnement objet possibilit de naviguer travers le graphe dobjets
select elements(emailAddresses) from Person

element : pour rcuprer les lments dune collection

Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Pat05] et de la doc dHibernate 3

220

Requtes

Requte HQL (3/4)


join : Pour excuter des jointures (inner join) Exemple : select p from Person p join p.events where p.id = 4 left join : Jointure externe (left outer join) select p from Person p left join p.events where p.id = 4

Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Pat05] et de la doc dHibernate 3

221

68

Requtes

Requte HQL (4/4)


Lier les paramtres :
Long personId ; Person aPerson = (Person) session .createQuery("select p from Person p left join fetch p.events where p.id = :pid") .setParameter("pid", personId) .uniqueResult();

Gnrer dynamiquement les requtes : API Criteria


Event anEvent = (Event) session .createCriteria(Event.class) .setFetchMode("participants", FetchMode.JOIN) .add( Expression.eq("id", eventId) ) .uniqueResult();

Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Pat05] et de la doc dHibernate 3

222

Requtes

API Criteria (1/2)


API d'interrogation par critres dite intuitive et extensible appartenant au noyau
Obtention des instances persistances dune classe
Criteria crit = session.createCriteria(Person.class); List resultat = crit.list();

Excution de la requte

Dfinition de critres de recherche


List resultat = session.createCriteria(Person.class) .add( Restrictions.like("name", "Manou%") ) .add( Restrictions.or( Restrictions.eq( "age", new Integer(0) ), Restrictions.isNull("age") ) ) .list();

Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Pat05] et de la doc dHibernate 3

223

69

Requtes

API Criteria (2/2)


Peuplement d'associations de manire dynamique
List resultat = session.createCriteria(Person.class) .add( Restrictions.like("name", "Manou%") ) .setFetchMode("events", FetchMode.JOIN) .list();

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

Requtes par l'exemple


Person p = new Person(); p.setName("Manouvrier"); List results = session.createCriteria(Person.class) .add( Example.create(p) ) .list();

Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Pat05] et de la doc dHibernate 3

224

Requtes

Requtes SQL natives


Pour utiliser des requtes optimises et tirer partie des spcificits du SGBD utilis Requtes natives du noyau
session.createSQLQuery("SELECT * FROM PERSON").list(); Retourne une liste dObject[] avec des valeurs scalaires pour chaque colonne de la table PERSON (i.e. retourne une table comme pour les requtes classiques JDBC) session.createSQLQuery("SELECT * FROM PERSON") .addEntity(Person.class); Retourne une liste dobjets de la classe Person

Requtes natives en JPA

Besoin de mta-donnes pour dfinir le rsultat de la requte sauf si le rsultat correspond des donnes dont le mapping est dj dcrit

entitymanager.createNativeQuery("SELECT * FROM PERSON", Person.class);

cf. doc Hibernate Entity Manager


Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [Pat05] et de la doc dHibernate 3

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

Dclenchement automatique de la synchronisation avec la BD

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

Maude Manouvrier - Univ. Paris Dauphine

Transactions (4/10)
Degrs disolation :

Dfinition du niveau 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

Mta-donnes pour la mise en place du versionnement :


<version> ou <timestamp> en XML ( placer aprs la prop. id) @Version en annotation (de type int, Integer, Short, Long ou Timestamp)

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

Gestion pessimiste de la concurrence :



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)

Mthodes permettant dobtenir explicitement un niveau de verrouillage :


Session.load() en spcifiant un niveau verrouillage LockMode. Session.lock() (rattache lobjet) ou EntityManager.lock() (valable uniquement pour les entits persistantes ne rattache pas lobjet) Query.setLockMode()

Accs non transactionnel aux donnes


Recommand par EJB3 pour les conversation (longues transactions applicatives) longue Possibilit dimplmenter les conversations en Hibernate, JPA/EJB3
o o Par un gestionnaire dentits multiples et des objets dtachs (manipulation dentits dtaches problme de rattachement) Par la mise en place dun contexte de persistance tendu (pas de manipulation dentits dtaches problme de stockage du cycle de vie du gestionnaire dentits et pour empcher la synchronisation avec la BD avant la fin de la conversation)

Maude Manouvrier - Univ. Paris Dauphine repris et adapt de [BK07,Pat05] et de la doc dHibernate 3

236

76

Vous aimerez peut-être aussi