Vous êtes sur la page 1sur 20

28/02/2012

Framework de persistance

Hibernate
BOUSETTA Ibrahim

MOR

Les difficultés de cohabitation entre les


mondes objets et relationnels sont
résolues grâce au concept de Mapping
objet-relationnel (O/R Mapping)
Ce terme (ORM) décrit la technique
consistant à faire le lien entre la
représentation objet des données et sa
représentation relationnelle, basé sur un
schéma SQL.

ibbousetta@gmail.com BOUSETTA Ibrahim

1
28/02/2012

Architecture Multi-niveaux
Séparation des couches

3 BOUSETTA Brahim

Frameworks de persistance

Outils permettant de :
modéliser un système de données,(UML ou en XML), et de
générer tous les DAO ainsi que les objets métiers.
De plus, ils prennent en charge des concepts avancés
comme :
le cache des objets,
la concurrence,
les transactions distribuées,
le chargement des données via des requêtes objets, et
peuvent également offrir une totale indépendance vis-à-vis du
serveur de bases de données.
Ils créent des systèmes complètement autonomes de
gestion du système d’information, autorisent un fort
découplage avec la base de données, améliorent les
performances et apportent 4une grande simplicité
BOUSETTA Brahim
d’utilisation.

2
28/02/2012

Hibernate

Hibernate est un framework puissant de


Java qui permet la persistance des objets.
Hibernate est un projet open source, libre
et employé couramment par les sociétés.
Hibernate est un framework de mapping
objet relationnel ou objet persistent.
En effet, l’application voit la couche
d’accès aux données comme des objets
qui seront sauvegardés après que
l’application soit éteinte.

5 BOUSETTA Brahim

vue d'ensemble générale de


l'architecture d’Hibernate

6 BOUSETTA Brahim

3
28/02/2012

7 BOUSETTA Brahim

Les fichiers de mapping xml


Comme beaucoup de frameworks J2EE, Hibernate
est configuré par des fichiers xml.
Le fichier de mapping mappe les tables de la base
de données.
L’application lira ce fichier pour créer les objets à
partir de la base de données.
Exemple d’une classe Catalogue .

8 BOUSETTA Brahim

4
28/02/2012

class Catalogue
public class Catalogue {

private int numCat;


private String desCat;
private ArrayList<Article> articles;

public Catalogue(int numCat, String desCat, ArrayList<Article>


articles) {
super();
this.numCat = numCat;
this.desCat = desCat;
this.articles = articles;
}
}

9 BOUSETTA Brahim

class Article
public class Article {

private int idA;


private String descA;
private double prix;
Getters et setters
}

ibbousetta@gmail.com BOUSETTA Ibrahim

5
28/02/2012

Le fichier de mapping xml


(MaClasse.hbm.xml)

<!DOCTYPE hibernate-mapping PUBLIC "-


//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-
3.0.dtd">
<hibernate-mapping>
…..
</hibernate-mapping>

Les éléments des fichiers de mapping Hibernate


contiennent les propriétés des classes persistantes
liant les objets et les tables de la base de données.
Voici le mapping correspondant à la classe Account :
11 BOUSETTA Brahim

Article.hbm
<hibernate-mapping package="caisse.bo">
<class name="Article" table="ARTICLE">
<id column="IDARTICLE" name="idA" type="integer" >
<generator class="sequence" />
</id>
<property column="PRIX" length="5" name="prix" not-
null="false" type="float" />
<property column="LIBELLE" length="50" name="descA"
not-null="false" type="string"
/>
</class>
</hibernate-mapping>

ibbousetta@gmail.com BOUSETTA Ibrahim

6
28/02/2012

Catalogue.hbm.xml
<hibernate-mapping package="caisse.bo">
<class name="Catalogue" table="CATALOGUE">
<id column="NUMCAT" name="Numcat" type="integer" >
<generator class="sequence" />
</id>
<property column="DESCAT" length="50" name="Descat"
not-null="false" type="string" />
<set inverse="false" lazy="true" name="articles" >
<key column="NUMCAT" />
<one-to-many class="Article" />
</set>
</class>
</hibernate-mapping>

13 BOUSETTA Brahim

The Hibernate configuration file


On dois configurer Hibernate avec la source de
données.
Pour la configuration d'Hibernate on peut employer :
un simple fichier hibernate.properties,
un fichier hibernate.cfg.xml ou
nous pouvons faire la configuration dans le code.
J'emploierai un fichier hibernate.cfg.xml pour faire la
configuration.
Exemple de Hibernate avec la base de données
PostgreSQL.
Les pilotes JDBC PostgreSQL peuvent être téléchargés sur :
http://jdbc.postgresql.org/download.html.
Les fichiers jar sont à inclure dans le dossier contenant toutes
les librairies et a ajouter au class path de l’application.
14 BOUSETTA Brahim

7
28/02/2012

The Hibernate configuration file


<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.url">
jdbc:oracle:thin:@localhost:1521:XE </property>
<property name="hibernate.connection.driver_class">
oracle.jdbc.driver.OracleDriver </property>
<property
name="hibernate.connection.username">caisse2</property>
<property name="hibernate.connection.password">
caisse2</property>
<property name="dialect"> org.hibernate.dialect.OracleDialect
</property>
<mapping resource="caisse/bo/Catalogue.hbm" />
<mapping resource="caisse/bo/Article.hbm" />
</session-factory>
</hibernate-configuration>

15 BOUSETTA Brahim

Session Factory
public class HibernateUtil {
public static Session currentSession() throws HibernateException
{
Session session = null;
try {
Configuration cfg = new Configuration();
cfg.configure("/hibernate.cfg.xml");
SessionFactory sessionFactory = cfg.buildSessionFactory();
session = sessionFactory.openSession() ;
} catch (Exception e) {
System.err.println(e.getMessage());
e.printStackTrace();
}
return session;
}

} 16 BOUSETTA Brahim

8
28/02/2012

Lister les données :

public static void main(String[] args) {


Session session = HibernateUtil.currentSession();
List<Article> arts = session.createQuery("select a from
Article a ").list();
for(Article a:arts)
System.out.println(a.getDescA());

ibbousetta@gmail.com BOUSETTA Ibrahim

Session (org.hibernate.Session)

C’est un objet à durée de vie courte qui


représente une conversation entre l'application et
l'entrepôt de persistance. Il encapsule une
connexion JDBC.
Hibernate définit et comprend les états suivants :
Éphémère (NdT : transient) - un objet est éphémère
s'il a juste été instancié en utilisant l'opérateur new. Il
n'a aucune représentation persistante dans la base
de données et aucune valeur d'identifiant n'a été
assignée.
Persistant - une instance persistante a une
représentation dans la base de données et une valeur
d'identifiant.
Détaché - une instance détachée est un objet qui a
été persistant, mais dont sa Session a été fermée.
18 BOUSETTA Brahim

9
28/02/2012

Rendre un objet persistant : insertion


Les instances nouvellement instanciées d'une classe
persistante sont considérées éphémères par Hibernate.
Nous pouvons rendre une instance éphémère persistante en
l'associant avec une session :

Article a= new Article(100,"desca",200);


session.beginTransaction();
Integer generatedId =(Integer)session.save(a);
//ou encore session.save(a, new Integer(100));
session.getTransaction().commit();

generatedId permet de récupérer l’id affecté à


l’articlecourant

19 BOUSETTA Brahim

Chargement d'un objet


Les méthodes load() de Session vous donnent un moyen de
récupérer une instance persistante si vous connaissez déjà son
identifiant.
load() prend un objet de classe et chargera l'état dans une
instance nouvellement instanciée de cette classe, dans un état
persistant.
art = (Article ) session.load(Article.class, generatedId);
Alternativement, vous pouvez charger un état dans une instance
donnée :
Article a = new Article ();
session.load( a, new Long(pkId) );
Si vous n'êtes pas certain qu'une ligne correspondante existe,
vous devriez utiliser la méthode get(), laquelle accède à la base
de données immédiatement et retourne null s'il n'y a pas de ligne
correspondante.
Article a = (Article ) session.get(Article .class, id);

20 BOUSETTA Brahim

10
28/02/2012

Il est possible de re-charger un objet et toutes ses


collections à n'importe quel moment, en utilisant la
méthode refresh(). C'est utile lorsque des "triggers"
de base de données sont utilisés pour initialiser
certains propriétés de l'objet.
session.save(Article );
session.flush(); //force the SQL INSERT
session.refresh(Article ); //re-read the state (after
the trigger executes)
Session.flush() permet de s’assurer que les
changements sont synchronisés avec la base de
données.
Cependant, si vous utilisez une Transaction, l'appel de
la méthode commit() l'appellera automatiquement.

21 BOUSETTA Brahim

Modifier des objets persistants

Les instances persistantes transactionnelles


(c'est-à-dire des objets chargés, sauvegardés,
créés ou requêtés par la Session) peuvent être
manipulées par l'application et n'importe quel
changement vers l'état persistant sera persisté
lorsque la Session est "flushée" .

Article a = (Article ) sess.load(Article .class, new Integer(1) );


cat.setLibelle("Produit xxx");
sess.flush(); // changes to cat are automatically detected and persisted

22 BOUSETTA Brahim

11
28/02/2012

Suppression d'objets persistants


Session.delete() supprimera l'état d'un objet de la
base de données.
Bien sûr, votre application pourrait encore conserver
une référence vers un objet effacé.
Il est mieux de penser à delete() comme rendant une
instance persistante éphémère.
session.delete(art);
Vous pouvez effacer des objets dans l'ordre que vous
voulez, sans risque de violations de contrainte de clef
étrangère.
Il est encore possible de violer une contrainte NOT
NULL sur une colonne de clef étrangère en effaçant
des objets dans le mauvais ordre, par exemple si vous
effacer le parent, mais oubliez d'effacer les enfants.
23 BOUSETTA Brahim

Article a3=(Article)session.load(Article.class, new


Integer(32));
System.out.println(a3.getIdA()+"--"+a3.getDescA());
a3.setDescA("new desc");
Session.flush();
a3=(Article)session.load(Article.class, new Integer(32));
System.out.println(a3.getIdA()+"--"+a3.getDescA());
session.delete(a3);

ibbousetta@gmail.com BOUSETTA Ibrahim

12
28/02/2012

Hibernate Annotations

ibbousetta@gmail.com BOUSETTA Ibrahim

Configuration
Tout d'abord, paramétrez votre classpath (après
avoir créer un nouveau projet dans votre IDE
favori) :
Copiez toutes les bibliothèques du noyau
Hibernate3 et toutes les bibliothèques tierces
requises (voir lib/README.txt dans Hibernate).
Copiez aussi hibernate-annotations.jar et
lib/ejb3-persistence.jar de la distribution
Hibernate Annotations dans votre classpath.

ibbousetta@gmail.com BOUSETTA Ibrahim

13
28/02/2012

Fichier de configuration
Il est le meme que pour le mapping classique avec les fichier xml.
Les balises <mapping resource="…"/>
<mapping resource="caisse/bo/Catalogue.hbm" />
<mapping resource="caisse/bo/Article.hbm" />
Seront remplacées par :
<session-factory>
<mapping package="test.bo"/>
<mapping class="test.bo.Article"/>
<mapping class="test.bo.Catalogue"/>
</session-factory>
Le mapping de classe peut etre omis dans le fichier de
configuration et défini à la creation de session factory avec les
methode s:
.addPackage("metier.bo")
.addAnnotatedClass(metier.bo.Salarie.class)
ibbousetta@gmail.com BOUSETTA Ibrahim

Session Factory

public static Session getSession() throws HibernateException {


SessionFactory sessionFactory = new
AnnotationConfiguration().configure("/hibernate.cfg.xml")
.addPackage(“metier.bo")
.addAnnotatedClass(metier.bo.Salarie.class)
.addAnnotatedClass(metier.bo.Article.class)
.addAnnotatedClass(metier.bo.TypeArticle.class)
//….
.buildSessionFactory();

return sessionFactory.openSession();
}

ibbousetta@gmail.com BOUSETTA Ibrahim

14
28/02/2012

Entity Beans
@Entity déclare la classe comme un entity bean,
@Id déclare la propriété identifiante de cet entity bean.
Les autres déclarations de mapping sont implicites.
Ce concept de déclaration par exception est un composant
essentiel de la nouvelle spécification EJB3 et une
amélioration majeure.
La classe Article est mappée sur la table Article, en utilisant
la colonne id comme colonne de la clef primaire.
@Entity
public class Article {

@Id
private int idA;
private String desc;

}
ibbousetta@gmail.com BOUSETTA Ibrahim

Définir la table :
@Table est positionnée au niveau de la classe ; cela vous
permet de définir le nom de la table, du catalogue et du
schéma pour le mapping de votre entity bean.
Si aucune @Table n'est définie les valeurs par défaut sont
utilisées : le nom de la classe de l'entité (sans le nom de
package).
//@Table(name="Article")
public class Article {

L'élément @Table contient aussi un attribut schema et un


attribut catalog, si vous avez besoin de les définir.
Vous pouvez aussi définir des contraintes d'unicité sur la
table en utilisant l'annotation @UniqueConstraint en
conjonction avec @Table (pour une contrainte d'unicité
n'impliquant qu'une seule colonne, référez-vous à
@Column).
ibbousetta@gmail.com BOUSETTA Ibrahim

15
28/02/2012

Mapping de simples propriétés


Chaque propriété (champ ou méthode) non statique non
transient d'un entity bean est considérée persistante, à
Entity Beans moins que vous l'annotiez comme @Transient.
Ne pas avoir d'annotation pour votre propriété est
équivalent à l'annotation @Basic. L'annotation @Basic vous
permet de déclarer la stratégie de récupération pour une
propriété :

public class Caisse {


@Id
private int idCaisse;
@Basic
private String descr;
@Transient
private Vente ventecourante=null;

ibbousetta@gmail.com BOUSETTA Ibrahim

Déclarer des attributs de colonne


@Entity
public class Flight {
...
@Column(updatable = false, name = "flight_name", nullable
= false, length=50)
private String name;

@Column(
name="columnName";
boolean unique() default false;
boolean nullable() default true;
boolean insertable() default true;
boolean updatable() default true;
String table() default ""; (
int length() default 255;
int precision() default 0; // decimal precision (9)
ibbousetta@gmail.com BOUSETTA Ibrahim

16
28/02/2012

Mapper des propriétés identifiantes


L'annotation @Id vous permet de définir quelle propriété identifie votre
entity bean. Cette propriété peut être positionnée par l'application elle-
même ou générée par Hibernate (préféré).
Vous pouvez définir la stratégie de génération de l'identifiant grâce à
l'annotation @GeneratedValue :
AUTO - soit la colonne identity, soit la séquence, soit la table selon la
base de données sous-jacente
TABLE - table contenant l'id
IDENTITY - colonne identity
SEQUENCE - séquence
@Entity
@javax.persistence.SequenceGenerator( name="seqc",
sequenceName="seq_c" )
@Table(name="caisse")
public class Caisse {

@Id @GeneratedValue(strategy=GenerationType.SEQUENCE,
generator="seqc")
private int idCaisse;
ibbousetta@gmail.com BOUSETTA Ibrahim

Mapper l'héritage
EJB3 prend en charge les trois types d'héritage :
Stratégie d'une table par classe concrète : l'élément
<union-class> dans Hibernate
Stratégie d'une seule table par hiérarchie de classe :
l'élément <subclass> dans Hibernate
Stratégie d'une table par classe fille : l'élément <joined-
subclass> dans Hibernate
La stratégie choisie est déclarée au niveau de la classe de
l'entité la plus haute dans la hiérarhie en utilisant
l'annotation @Inheritance.

ibbousetta@gmail.com BOUSETTA Ibrahim

17
28/02/2012

@Entity
@Inheritance(strategy=InheritanceType.JOINED)
public abstract class Salarie implements Serializable {
@Id
private int matricule;
….
}

@Entity
@PrimaryKeyJoinColumn(name="matricule")
public class Caissier extends Salarie{

}

ibbousetta@gmail.com BOUSETTA Ibrahim

Mapper des associatiion


One-to-one
@Entity
@PrimaryKeyJoinColumn(name="matricule")
public class Caissier extends Salarie{
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name="idcaisse")
private Caisse caisse;
….

@Entity
public class Caisse {

@Id
private int idCaisse;
@OneToOne(mappedBy = "caisse")
private Caissier caissier;

ibbousetta@gmail.com BOUSETTA Ibrahim

18
28/02/2012

Many-to-one
public class LigneVente {

@Id
private int idLV;

@ManyToOne( cascade = {CascadeType.PERSIST,


CascadeType.MERGE,CascadeType.REMOVE} )
@JoinColumn(name="numvente")
private Vente vente;

@ManyToOne( cascade = {CascadeType.PERSIST,


CascadeType.MERGE,CascadeType.ALL} )
@JoinColumn(name="idarticle")
private Article article;

ibbousetta@gmail.com BOUSETTA Ibrahim

One-to-Many
public class Vente {
@Id
@Column(name="numVente")
private int numV;

@ManyToOne( cascade = {CascadeType.PERSIST,


CascadeType.MERGE} )
@JoinColumn(name="idCaisse")
private Caisse caisse;

@OneToMany(mappedBy="vente", cascade = {CascadeType.PERSIST,


CascadeType.MERGE, CascadeType.ALL})
private List<LigneVente> Lventes;

ibbousetta@gmail.com BOUSETTA Ibrahim

19
28/02/2012

Many-to-Many
@Entity
public class Auteur {
@ManyToMany( targetEntity=Livre.class,
cascade={CascadeType.PERSIST, CascadeType.MERGE})
@JoinTable( name="Ecrire", joinColumns=@JoinColumn(name="idA"),
inverseJoinColumns=@JoinColumn(name="ISBN") )
private List<Livre> livres;
...
}

@Entity
public class Livre {
@ManyToMany( cascade = {CascadeType.PERSIST,
CascadeType.MERGE},
mappedBy = "livres", targetEntity = Auteur.class
)
private List<Auteur> auteurs;
}
ibbousetta@gmail.com BOUSETTA Ibrahim

20