Entity - e

Transcription

Entity - e
JAVA PERSISTENCE API
Jean-Jacques LE COZ
Introduction

Historique
Le manque de solutions a freiné l'utilisation des
langages orientés objet dans les entreprises
 Notamment pour les applications de gestion


Les intergiciels
Type ODBC ou JDBC
 Trop bas niveau
 Ne masquent pas la non correspondance des
paradigmes objet et relationnel

Solutions


Récentes, fin des années 90
Produits de mapping O/R


Persistance des objets
Frameworks de mapping O/R
Persistance des objets

Outils
 Conception du mapping



Classes persistantes
Tables de la base de données
Standardisation

Pour la plateforme Java


JPA (Standard Java Persistence API)
Pour les platefomes C++, .NET, Python

Aucun standard
Plateforme Java

JPA
Sources de données relationnelles
 Convergence entre JDO et EJB
 Versions J2EE EJB3 et JDO 2


JDO Java Data Object
Interface de programmation universelle
 Toutes les sources de données


Relationnelles, Objets, Transactionnelles, XML, ...
Outils pour Java (1)

Au standard JPA

Produits commerciaux


TopLink (Oracle : contributeur de l'implémentation de
référence)
Produits libres


Hibernate (Communauté libre Hibernate)
GlassFish (Sun Micro-system)
Outils pour Java (2)

Au standard JDO

Produits commerciaux





Kodo JDO (SolarMetric)
Implémentation de référence JDO1(Sun Microsystems)
Open Access JDO (Versant Corporation)
LiDO (Xcalia)
Produits libres





JODInstruments
Speedo
Triactive JDO
XORM
JPOX (Implémentation de référence JDO2)
Outils pour Java (3)

Non standardisés

Commerciaux



CocoBase (Thought Inc)
Nombreux autres produits
Libres



Castor
Cayenne (en cours de standardisation JPA)
iBatis
Hibernate
Produit phare pour Java

Hibernate
Enorme succès
 Tous les types d'entreprise
 Tous les types d'application
 Nombreuses ressources





Documentations
Livres
Retours d'expérience
Site officiel

www.hibernate.org
Hibernate
Produit Open Source
Licence LGPL
Supporte tous les SGBDR du marché
Solution orthogonale
Supporte tous les concepts objets

Héritage
 Polymorphisme
 Composition

Supporte les transactions

Hibernate pourquoi faire ?

Pour les architectures
Applications Web
 Applications distribuées


Pour les disponibilités
Forte montée en charge
 Transactions longues


Solution industrielle
Versions du logiciel Hibernate

Versions antérieures à 3.1


Solution propriétaire
Versions postérieures à 3.1

Standardisée JPA
JPA avec HIBERNATE
État des objets persistants

Trois états possibles

Transient


Persistant


Objet nouvellement créé
Objet transient sauvé ou objet retrouvé
Détaché


Objet persistant hors d'une session hibernate
Peut être ré-attaché
Cycle de vie des objets
Identité JPA

Chaque objet persistant possède deux
identités :

Identité Java


OID affecté à l'objet par la JVM
Identité JPA


ID affecté à l'objet par HIBENRATE
Correspond à une valeur de clef primaire dans
la base de données
Verrouillage

Optimiste
Garantie la montée en charge
 Basé sur le comportement du SGBDR


multiversion concrrency control



Numérotation des versions
Estampille
Pessimiste
Verrouillage explicite
 Adaptation aux possibilités du SGBDR

Verrouillage optimiste
Gestion au niveau applicatif
 Gestion automatique

Objets détachés
 Sessions longues
 Personnalisation

Verrouillage pessimiste
Lecture
 Écriture
 Mise-à-jour

Performances
Seulement 10% moins rapide que JDBC
 Options de gestion des performances

Lazy initialisation + objets proxies
 Caches


Cache par défaut


Premier niveau de cache

Niveau session
Caches supplémentaires


Second niveau de cache

Niveau application
Pour les résultats des requêtes
Compromis

Limiter le nombre d'entrées/sorties
Ici les requêtes SQL

Solution par anté-mémoires (caches)


Limiter l'encombrement mémoire
Ici les caches

Solution par lecture incrémentale

Stratégies de chargement

Deux principes

Quand est fait le chargement



Immédiatement (eager)
Tardivement (lazy)
Comment est fait le chargement


Par jointure
Par multiple requêtes
Objets mandataires (1)

Les proxys HIBERNATE
Supportent le polymorphisme
 Utilisés pour les relations



Un vers plusieurs
Un vers un
Avec le type de chargement tardif (lazy)
 Pour chaque objet dépendant



Charge uniquement son ID hibernate et sa version
Crée un objet proxy avec ces deux caractéristiques
Objets mandataires (2)

Les proxys HIBERNATE

Créés dynamiquement à l'exécution

Par manipulation du Byte Code Java
Par spécialisation de la classe de l'objet
 Quand une invocation arrive sur l'objet



chargement de l'objet
Délégation entre le proxy et l'objet
Développer au standard JPA
Introduction
Basé sur J2SE version 5
 Pas besoin de fichiers de mapping XML
 « bootsrap » d'une application JPA


La classe EntityManager
Stanard JPA et EJB3
Basé sur les nouveautés Java Tiger
(Java 5)
 Annotations Java 5


Syntaxe : @uneAnnotation
Compatibilité EJB3
 Exemple

@Entity
public class Etudiant {
...
Fichier technique
Le fichier persistence.xml
 Déploiement


Dans le répertoire META-INF
Déclaration des classes persistantes
 Paramétrage de la connexion JDBC
 Déclaration du pool de connexions JDBC
 Options

Exemple de persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence>
<persistence-unit name="manageur" transaction-type="RESOURCE_LOCAL">
<class>modele.Etudiant</class>
<class>modele.Promotion</class>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
<property name="hibernate.connection.driver_class" value="org.postgresql.Driver"/>
<property name="hibernate.connection.username" value="postgres"/>
<property name="hibernate.connection.password" value="jjlcoz"/>
<property name="hibernate.connection.url" value="jdbc:postgresql://localhost/hibernate01"/>
<property name="hibernate.max_fetch_depth" value="3"/>
<!-- création du schéma automatiquement -->
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
</properties>
</persistence-unit>
</persistence>
Une classe persistante

Une classe POJO persistante
Annotation @Entity
 Mapping vers une relation



@Table(name=''matable'')
Identité JPA



@Id
Correspond à une clef primaire non composée
Peut être une sequence ou une identity (clef
auto-incrémentée)

@GeneratedValue
Exemple de classe persistante
@Entity
@Table(name="TAB_ETUDIANT")
public class Etudiant {
private int id;
private String nom;
private String prenom;
private String adresse;
public Etudiant(String nom, String prenom, String adresse) {
this.setNom(nom);
this.setPrenom(prenom);
this.setAdresse(adresse); }
@Id
@GeneratedValue
public int getId() { return id; }
public void setId(int id) {this.id = id; }
...
Les clefs surrogate

Annotation générale


@GeneratedValue
Stratégies

AUTO





Option par défaut
La couche de persistance choisit une des stratégies
suivantes
TABLE
IDENTITY
SEQUENCE
Stratégie de génération de clef

TABLE


SEQUENCE


La couche de persistance utilise une table pour
gérer la génération elle-même
La couche de persistance utilise une séquence
de la base de données pour la génération
IDENTITY

La couche de persistance se repose entièrement
sur base de données pour la gestion de la
génération
Exemple SEQUENCE
@Entity
@SequenceGenrator(name=''LA_TABLE_DE_SEQUENCES'',
sequenceName=''MA_SEQUENCE'',
initialValue=1, allocationSize=10)
public class MaClasse {
...
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE,
generator=''LA_TABLE_DE_SEQUENCE'')
public int getId() { ....
Exemple IDENTITY
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name=''MACLEF'')
public Long getId() { ....
Propriétés

Propriétés non persistantes

Annotation


@Transient
Propriétés persistantes
Par défaut
 Annotation



@Basic
Permet d'associer une stratégie de chargement

@Basic(fetch = FetchType.LAZY ou EAGER)
Propriétés gros grains
Fichiers BLOB, CLOB
 BLOB (Binary Large Object)

java.sql.Blob, Byte[ ], byte[ ]
 Types serializable


CLOB (Characters Large Object)


java.sql.Clob, Character[ ], char[ ], String
Annotation

@Lob
Mapping propriété/colonne
Déclaré sur la méthode get...
 Annotation

@Column
 Attributs




name, unique, nullable, insertable, updatable
length, precision, scale
Exemple

@Column(name=CODE,nullable=false,unique=true)
Gestion des transactions
Par l'objet EntityManager
 Avec Java SE

Obtenu par un EntityManagerFactory
 A partir de l'interface Persistence


Dans les environnements gérés
Obtenu par injection
 Annotation @PersistenceContext

Utilisation des classes
public static void main(String[] args) {
EntityManagerFactory emf =
Persistence.createEntityManagerFactory("manageur", new HashMap());
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
Promotion mod7 = new Promotion("MOD7",new Date(), new Date());
Etudiant e1 = new Etudiant("Dupont","Jacques","PARIS");
Etudiant e2 = new Etudiant("Martin","Pierre","LILLE");
Etudiant e3 = new Etudiant("Abellard","Sophie","LYON");
mod7.addEtudiant(e1);
mod7.addEtudiant(e2);
mod7.addEtudiant(e3);
em.persist(mod7);
em.getTransaction().commit();
em.close();
emf.close();
}
Les relations
Relations
Tous les types de relation entre objets sont
supportés
 Mono-directionnelles
 Bi-directionnelles

Multiplicités
Toutes les multiplicités sont supportées
 Cardinalités


1,1 – 1,1


1,1 – 1,N


@OneToOne
@ManyToOne et @OneToMany
1,N – 1,N

@ManyToMany
Génération de schéma

Relations @OneToOne et @OneToMany

Possibilité de relation directe entre tables avec
clef(s) étrangère(s)



@JoinColumn
Possibilité de table associative
Relation @ManyToMany

Effectuée avec une table associative
Relations mono-directionnelles
Maître et esclave de la relation
La relation mono-directionnelle ne détermine
que le rôle maître ou possesseur de la
relation
 C'est le côté maître d'une relation qui
détermine les mises à jour dans la base de
données

Synchronisation
 Cascade

Modèle UML
Exemple avec OneToMany
@Entity
@Table(name="PROMOTION")
public class Promotion {
...
private Collection<Etudiant> etudiants;
...
@OneToMany(cascade=CascadeType.ALL)
@JoinColumn(name="PROMOTION_ID")
public Collection<Etudiant> getEtudiants() { return etudiants; }
...
Modèle UML
Exemple avec ManyToOne
@Entity
@Table(name="ETUDIANT")
public class Etudiant {
...
private Promotion promotion;
...
@ManyToOne
public Promotion getPromotion() { return promotion; }
...
Relations bi-directionnelles
Maître et esclave de la relation

Côté inverse de la relation (esclave)
Doit définir l'attribut mappedBy
 La donnée membre pointée par mappedBy
est une propriété de la classe persistante
maîtresse (possesseur) de la relation


Côté possesseur (maître)
Côté Many d'une relation ManyToOne
 Côté(s) Many d'une relation ManyToMany
 Côté contenant la clef étrangère d'une
relation OneToOne

Modèle UML
Exemple avec OneToMany
@Entity
@Table(name="PROMOTION")
public class Promotion {
...
private Collection<Etudiant> etudiants;
...
@OneToMany(mappedBy=''promotion'', cascade=CascadeType.ALL)
public Collection<Etudiant> getEtudiants() {return etudiants; }
...
Exemple avec ManyToOne
@Entity
@Table(name="ETUDIANT")
public class Etudiant {
...
private Promotion promotion;
...
@ManyToOne
public Promotion getPromotion() { return promotion; }
...
Persistance par navigation
Persistance transitive
 Opérations propagées
 Attribut cascade
 Associé à un tableau de types de cascade



CascadeType
Le type ALL
Tous les types sont associés
 CascadeType.ALL

Les types de cascade

Types

CascadeType.PERSIST



CascadeType.MERGE
CascadeType.REMOVE


Persistance par navigation
Suppression en cascade (cascade delete)
CascadeType.REFRESH
Clefs primaires composées
Clefs primaires composées (1)
Les clés composées doivent être
implémentées par des classes
 Les classes de clés primaires doivent
implémentées l'interface Serializable
 Elles doivent implémenter aussi

La méthode hashCode()
 La méthode equals()

Clefs primaires composées (2)

Annotation spécifique pour les classes
clef primaire composée


@Embeddable
Définitions d'un classe clef pour une
classe persistante
Annotation @IdClass
 Annotation @EmbededId

Exemple de clé primaire
@Embeddable
public class ParlerPK implements Serializable {
private static final long serialVersionUID = 1L;
private int etudiantid;
private int langueid;
public int getEtudiantid() {return etudiantid;}
public void setEtudiantid(int etudiantid) {this.etudiantid = etudiantid;}
public int getLangueid() {return langueid;}
public void setLangueid(int langueid) {this.langueid = langueid;}
}
Exemple de classe avec clé
@Entity
@Table(name="PARLER")
@IdClass(ParlerPK.class)
public class Parler {
private static final long serialVersionUID = 1L;
private int etudiantid;
private int langueid;
private Etudiant etudiant;
private Langue langue;
private double note;
...
Spécialisation
Modèle UML
Types d'implémentation

Une table par classe

Annotation


Une table pour toute la hiérarchie

Annotation


@Inheritance(strategy = InheritanceType.JOINED)
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
Une table par sous-classe concrète

Annotation

@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
Une table par classe
Cette stratégie d'implémentation supporte
les relations de type 1 vers N si elles sont bidirectionnelles
 Cette stratégie ne supporte pas IDENTITY
 L'identifiant doit être partagé entre les tables


Donc pas de possibilité de AUTO pour les
« sous-tables »
Une table par hiérarchie

Distinction du type des instances
Par discriminant
 Annotations




@DiscriminatorColumn( name="nom du type"
discriminatorType=DiscriminatorType.STRING
@DiscriminatorValue("valeur")
Implémenter par une colonne supplémentaire
dans la table
Une table par sous-classe

Les tables sont jointes par une même
clef primaire

Annotation

@PrimaryKeyJoinColumn(name="nom clef")
Héritage de propriétés

A partir d'une classe non mappée
@MappedSuperclass
public class EntiteDeBase {
@Basic
@Temporal(TemporalType.TIMESTAMP)
public Date getDerniereMAJ() { ... }
public String getCommercial() { ... }
... }
@Entity class Commande extends EntiteDeBase {
@Id public Integer getId() { ... }
...
}
Réécriture de propriétés
@MappedSuperclass
public class FlyingObject {
public int getAltitude() { return altitude; }
@Transient
public int getMetricAltitude() { return metricAltitude; }
...
}
@Entity
@AttributeOverride( name="altitude", column=@Column(name="fld_altitude") )
public class Plane extends FlyingObject {
...
}
Bibliographie

Hibernate in Action – Manning

Pro Hibernate 3 – Apress

Professional Hibernate – Wrox

Hibernate : A Developer's Notebook – O'Reilly

Java Data Objects – O'Reilly

Core Java Data Objects – Prentice Hall

Using and Understanding Java Data Objects - Apress