Vous êtes sur la page 1sur 198

Persistance dans Java EE 6 : JPA2 et EJB 3.

1
Michel Buffa (buffa@unice.fr), UNSA 2011

Note importante


Ce cours couvre les besoins les plus importants, vous pourrez retrouver un cours trs complet sur JPA2 et sur la persistence en java en gnral sur la page de Richard Grin


http://deptinfo.unice.fr/~grin/mescours/minfo/modper sobj/supports/index.html

Aussi, une bonne rfrence en ligne sur JPA2




http://www.objectdb.com/api/java/jpa, en particulier la section JPA2 annotations

Contexte


Java EE 6 propose ce quon appelle un web profile


Un sous-ensemble de java EE pour le dveloppement dapplication web simples  La suite sera aborde en partie lan prochain


Dans ce web profile on propose :


Vue : JSP ou facelets/JSF2  Contrleur web : Servlets ou web service  Composant mtier : EJB type session + managed beans + classes java standard,  Accs aux donnes dans une BD via JPA2/EJB type entity


Contexte

Contexte

Entity Bean, introducton




Un Entity Bean reprsente


Des objets persistants stocks dans une base de donne,  Des noms, des donnes  Gestion via JPA2 + sessions beans


Dans ce chapitre on tudiera


Le concept de persistance,  Ce qu'est un entity bean, du point de vue du programmeur,  Les caractristiques des entity beans,  Les concepts de programmation des entity beans.


La persistance par srialisation




Srialisation = sauvegarde de l'tat d'un objet sous forme d'octets.


  

Rappel : l'tat d'un objet peut tre quelque chose de trs compliqu. Etat d'un objet = ses attributs, y compris les atributs hrits. Si les attributs sont eux-mme des instances d'une classe, il faut sauvegarder aussi les attributs de ces instances, etc

 

A partir d'un tat srialis, on peut reconstruire l'objet En java, au travers de l'interface java.io.Serializable, des mthodes de java.io.ObjectInputStream et java.io.ObjectOutputStream

La persistance par srialisation


  

Dfauts nombreux Gestion des versions, maintenance Pas de requtes complexes




Ex : on srialize mille comptes bancaires. Comment retrouver ceux qui ont un solde ngatif ?

Solution : stocker les objets dans une base de donne!

La persistance par mapping objet/BD relationelle




On stocke l'tat d'un objet dans une base de donne. Ex : la classe Personne possde deux attributs nom et prenom, on associe cette classe une table qui possde deux colonnes : nom et prenom. On dcompose chaque objet en une suite de variables dont on stockera la valeur dans une ou plusieurs tables. Permet des requtes complexes.

La persistance par mapping objet/BD relationelle

La persistance par mapping objet/BD relationelle




Pas si simple
Dtermination de l'tat d'un objet parfois difficile, tout un art  Il existe des produits pour nous y aider EclipseLink, TopLink (WebGain), Hibernate (JBoss),  Aujourd'hui la plupart des gens font a la main avec JDBC ou SQL/J.  Mais SQL dur tester/debugger source de


La persistance l'aide d'une BD Objet




Les Base de donnes objet stockent directement des objets. Plus de mapping ! Object Query Language (OQL) permet de manipuler les objets Relations entre les objets videntes (plus de join ) Bonnes performances mais mauvaise scalabilit.

 

Le modle de persistence JPA 2

JPA 2 propose un modle standard de persistance laide des Entity beans  Les outils qui assureront la persistance (Toplink, Hibernate, EclipseLink, etc.) sont intgrs au serveur dapplication et devront tre compatibles avec la norme JPA 2.  Java EE 6 repose tous les niveaux sur de linjection de code via des annotations de code  Souvent, on ne fera pas de new , les variables seront cres/initialises par injection de code.


Qu'est-ce qu'un Entity Bean




Ce sont des objets qui savent se mapper dans une base de donne. Ils utilisent un mcanisme de persistance (parmi ceux prsents) Ils servent reprsenter sous forme d'objets des donnes situes dans une base de donne


Le plus souvent un objet = une ou plusieurs ligne(s) dans une ou plusieurs table(s)

Qu'est-ce qu'un Entity Bean




Exemples
  

Compte bancaire (No, solde), Employ, service, entreprises, livre, produit, Cours, lve, examen, note,

Mais au fait, pourquoi nous embter passer par des objets ?


   

Plus facile manipuler par programme, Vue plus compacte, on regroupe les donnes dans un objet. On peut associer des mthodes simples pour manipuler ces donnes On va gagner la couche middleware !

Exemple avec un compte bancaire

On lit les informations d'un compte bancaire en mmoire, dans une instance d'un entity bean, On manipule ces donnes, on les modifie en changeant les valeurs des attributs d'instance, Les donnes seront mises jour dans la base de donnes automatiquement ! Instance d'un entity bean = une vue en mmoire des donnes physiques

Fichiers composant un entity bean




Schma classique :
  

 

La classe du bean se mappe dans une base de donnes. Cest une classe java normale (POJO) avec des attributs, des accesseurs, des modifieurs, etc. On utilisera les mta-donnes ou attributs de code pour indiquer le mapping, la cl primaire, etc.  Cl primaire = un objet srializable, unique pour chaque instance. C'est la cl primaire au sens SQL.  Note : on peut aussi utiliser un descripteur XML la place des annotations de code On manipulera les donnes de la BD laide des EntityBeans + laide dun PERSISTENT MANAGER. Le PM soccupera de tous les accs disque, du cache, etc.  Lui seul contrle quand et comment on va accder la BD, cest lui qui gnre le SQL, etc.

Exemple dentity bean : un livre


@Entity public class Book { @Id @GeneratedValue private Long id; @Column(nullable = false) private String title; private Float price; @Column(length = 2000) private String description; private String isbn; private Integer nbOfPage; private Boolean illustrations; // Constructors, getters, setters }

Exemple dentity bean : un livre


@Entity public class Book { @Id @GeneratedValue private Long id; @Column(nullable = false) private String title; private Float price; @Column(length = 2000) private String description; private String isbn; private Integer nbOfPage; private Boolean illustrations

Les annotations de code JPA 2




Remarques gnrales (suite)


Nombreuses valeurs par dfaut, par exemple une classe entit Personne se mappera dans la table PERSONNE par dfaut, un attribut nom sur la colonne NOM, etc.  Il existe de trs nombreux attributs pour les annotations, ce cours prsente les principaux, pour une tude dtaille, voir la spcification, un livre, ou le tutorial Java EE 6  Les rgles de JDBC sappliquent pour le mapping des types. String vers VARCHAR, Long vers BIGINT, Boolean vers SMALLINT, etc.


Les annotations de code JPA 2




Remarques gnrales
String vers VARCHAR(255) par dfaut,  Les rgles peuvent changer dun SGBD lautre, par exemple String est mapp sur VARCHAR avec Derby, mais sur VARCHAR2 avec Oracle. Un Integer sur un INTEGER avec Derby mais sur un NUMBER avec Oracle. Etc.  Dans le cas des cls primaires auto-incrmentes, la manire dont elles sont gres dpend du SGBD et de loutil de mapping relationnel-objet  Si on en change -> la structure des tables change !


Exemple dinsertion dun livre


public class Main { public static void main(String[] args) { // On cre une instance de livre Book book = new Book(); book.setTitle("The Hitchhiker's Guide to the Galaxy"); book.setPrice(12.5F); book.setDescription("Science fiction comedy book"); // On rcupre un pointeur sur lentity manager // Remarque : dans une appli web, pas besoin de faire tout cela ! EntityManagerFactory emf = Persistence.createEntityManagerFactory("chapter02PU"); EntityManager em = emf.createEntityManager(); // On rend lobjet persistant dans la base (on linsre) EntityTransaction tx = em.getTransaction(); tx.begin(); em.persist(book); tx.commit(); em.close(); emf.close(); }

Client sous forme de session bean




Dans le cas o le client est un session bean


du code peut tre inject ,  Les transactions sont dclenches par dfaut,


@stateless public class UnSessionBean { @PersistenceContext(unitName="EmployeeService") EntityManager em; public Employee createEmployee(int id, String name, long salary , byte[] pic) { Employee emp = new Employee(id); emp.setName(name); em.persist(emp); return emp; }

Client sous forme de session bean




Dans le cas o le client est un session bean


du code peut tre inject ,  Les transactions sont dclenches par dfaut,


@stateless public class UnSessionBean { @PersistenceContext(unitName="EmployeeService") EntityManager em; public Employee createEmployee(int id, String name, long salary , byte[] pic) { Employee emp = new Employee(id); emp.setName(name); em.persist(emp); return emp; }

Client sous forme de session bean


@Stateless public class BookBean { @PersistenceContext(unitName = "chapter04PU") private EntityManager em; public void createBook() { Book book = new Book(); book.setId(1234L); book.setTitle("The Hitchhiker's Guide to the Galaxy"); book.setPrice(12.5F); book.setDescription("Science fiction created by Douglas Adams."); book.setIsbn("1-84023-742-2"); book.setNbOfPage(354); book.setIllustrations(false); em.persist(book); // Rcupre le livre dans la BD par sa cl primaire book = em.find(Book.class, 1234L); System.out.println(book); } }

Remarques : quoi correspond le session bean ?




On codera la partie mtier


Souvent on utilise un session bean pour la couche DAO (avec des fonctions de cration, recherche, modification et suppression dentity beans)  Exemple : GestionnaireUtilisateurs  On utilisera aussi des session beans pour implmenter des services composites  Exemple : GestionnaireDeCommandes, qui utilisera dautres gestionnaires


Autres annotations
@Entity public class Book { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; @Column(name = "book_title", nullable = false, updatable = false) private String title; private Float price; @Column(length = 2000) private String description; private String isbn; @Column(name = "nb_of_page", nullable = false) private Integer nbOfPage; private Boolean illustrations; @Basic(fetch = FetchType.LAZY) @Lob private byte[] audioText; // Constructors, getters, setters }

Autres annotations (suite)




@Column permet dindiquer des prfrences pour les colonnes




Attributs possibles : name, unique, nullable, insertable, updatable, table, length, precision, scale

@GeneratedValue
Indique la stratgie de gnration automatique des cls primaires,  La valeur : GenerationType.auto est recommande,  Va ajouter une table de squence


@Lob indique large object (pour un BLOB)




Souvent utilis avec @Basic(fetch = FetchType.LAZY) pour indiquer quon ne chargera lattribut que lorsquon fera un get dessus

Autres annotations (suite)




Il existe de nombreuses autres annotations,




Voir par exemple : JPA Reference http://www.objectdb.com/api/java/jpa

Il se peut que les TPs en introduisent certaines. Les curieux peuvent consulter la spcification java EE 6 ou le tutorial (ou un bon livre)

Exemple de fichier persistence.xml




Ce fichier configure le persistence manager

<?xml version="1.0" encoding="UTF-8"?> <persistence version="1.0" mlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"> <persistence-unit name="IGift-ejbPU" transaction-type="JTA"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <jta-data-source>jdbc/igift</jta-data-source> <properties> <property name="hibernate.hbm2ddl.auto" value="update"/> </properties> </persistence-unit> </persistence>

Un exemple dentity bean : un compte bancaire

La classe = POJO, Srializable, Un attribut = la cl primaire Cest tout !

Client de lentity bean prcdent : un session bean (servant de faade/DAO)

Ce session bean est stateless, Utilise un EntityManager, Sert envoyer des requtes JPQL, Mthode persist(entity) pour crer une nouvelle entre (insert) Le reste passe par des appels de mthodes classiques de lentity bean.

Autre version : on garde dans le session bean la mmoire de lentity bean


Le session bean est stateful, Il garde la rfrence de lentity bean, On a du tendre la porte du Persistence Manager

Suite de lexemple

Dans getBalance() on nutilise plus de find, On utilise les Exceptions

Caractristiques des entity beans


 

Survivent aux crashes du serveur, du SGBD Ce sont des vues sur des donnes dans un SGBD

Modifier les donnes sans passer par le bean

Packager et dployer un Entity Bean Les EB sont dploys dans des persistence Units ,
Spcifi dans le fichier persistence.xml qui est dans le jar contenant les EJBs.  Exemple le plus simple :


Mais on peut ajouter de nombreux paramtres :  <description>, <provider>, <transaction type>, <mapping file> etc.

Que faire avec un entity manager ?

Etats dun Entity Bean

Un EB peut avoir 4 tats


1.

2.

3. 4.

New: le bean existe en mmoire mais nest pas encore associ une BD, il nest pas encore associ un contexte de persistence (via lentity manager) Managed : aprs le persist() par exemple. Le bean est associ avec les donnes dans la BD. Les changements seront rpercuts (transaction termines ou appel a flush()) Detached : le bean est nest plus associ au contexte de persistenced Removed : le bean est associ la BD, au contexte, et est programm pour tre supprim (les donnes seront supprimes aussi).

Utilisation du persistent manager

 

Remove() pour supprimer des donnes, Set(), Get(), appel de mthodes de lentity bean pour modifier les donnes, mais le bean doit tre dans un tat managed , Persist() pour crer des donnes, le bean devient manag, Merge pour faire passer un bean detached dans ltat managed .

Exemple de merge() avec le bean stateless

Recherche d'entity beans




Les entity beans correspondant des lignes dans une BD, on peut avoir besoin de faire des recherches. Similaire un SELECT Plusieurs fonctions sont proposes par lentity manager

 

Recherche dentity beans

Recherche par cl primaire :

Excution de requtes JPQL

Recherche dentity beans

Requtes SQL:

Requtes nommes:

JPQL : Quelques exemples

Voir le fichier PDF fourni avec les TPs !

JPQL : Quelques exemples (suite)

JPQL : Quelques exemples (suite)

JPQL : Quelques exemples (suite)

Liste toutes les commandes qui ne comprennent pas (LEFT) de produit dont le prix est suprieur une certaine quantit (et celles qui ne comprennent pas de produits)

JPQL : Quelques exemples (suite)




Requter sur plusieurs attributs renvoie soit un tableau dObject, soit une collection de tableaux dObject

texte = "select e.nom, e.salaire " + " from Employe as e"; query = em.createQuery(texte); List<Object[]> liste = (List<Object[]>)query.getResultList(); for (Object[] info : liste) { System.out.println(info[0] + "gagne" + info[1]); }

Table des compagnies

Table des employs

JPQL : Quelques exemples (suite)

Cette requte rcupre trois compagnies :

Mais celle-ci uniquement deux :

Celle-l : les trois (mme si join condition absente)

JPQL : Quelques exemples (suite)

Provoque le chargement des entities relies

 

Prend le devant sur @FetchType.LAZY Autre exemple :

JPQL : Quelques exemples (suite)

WHERE et requtes paramtres

Autre exemple avec paramtres nomms

JPQL : Quelques exemples (suite)

Expressions

Le % dans le LIKE = suite de caractres, le _ = un caractre

JPQL : Quelques exemples (suite)

MEMBER OF

Sous-Requtes

Fonctions sur chanes, arithmtique

Fonctions sur chanes, arithmtique (suite)

JPQL : Quelques exemples (suite)

JPQL : Quelques exemples (suite)

Utiliser des colonnes composites


@Embeddable public class Address { protected String street; protected String city; protected String state; @Embedded Zipcode zipcode; } @Embeddable public class Zipcode { String zip; protected String plusFour; }

Utiliser une cl primaire composite




Similaire lexemple prcdent sauf que au lieu dutiliser @Embedded / @Embeddable on utilisera @EmbbededId / Embeddable

@Embeddable public class CompositeId { String name; String email } @Entity public class Dependent { @EmbeddedId // indique que la cl primaire est dans une autre classe CompositeId id; @ManyToOne Employee emp; }

Relations avec les entity beans


Michel Buffa (buffa@unice.fr), UNSA 2011

On complique un peu l'tude des entity beans !




Les entity beans reprsentant des donnes dans une BD, il est logique d'avoir envie de s'occuper de grer des relations Exemples
Une commande et des lignes de commande  Une personne et une adresse  Un cours et les lves qui suivent ce cours  Un livre et ses auteurs


Nous allons voir comment spcifier ces relations dans notre modle EJB

Concepts abords
 

Cardinalit (1-1, 1-n, n-n ), Direction des relations (bi-directionnelles, unidirectionnelles), Agrgation vs composition et destructions en cascade, Relations rcursives, circulaires, agressive-load, lazyload, Intgrit rfrentielle, Accder aux relations depuis un code client, via des Collections, Comment grer tout a !

 

 

Direction des relations (directionality)




Unidirectionnelle


On ne peut aller que du bean A vers le bean B

Bidirectionnelle


On peut aller du bean A vers le bean B et inversement

Cardinalit
La cardinalit indique combien d'instances vont intervenir de chaque ct d'une relation One-to-One (1:1)


Un employ a une adresse

One-to-Many (1:N)


Un PDG et ses employs

Many-to-Many (M:N)


Des tudiants suivent des cours

Cardinalit

Relations 1:1


Reprsente typiquement par une cl trangre dans une BD Ex : une commande et un colis

Relations 1:1, le bean Order

Relations 1:1, le bean Order

Relations 1:1, le bean Shipment

Exemple de code pour insrer une commande avec une livraison relie

Relations 1:1, exemple de client (ici un main )

Version bidirectionnelle (on modifie Shipment)

Version bidirectionnelle (suite)

Version bi-directionnelle (suite, code qui fait le persist)




On peut maintenant ajouter au code de tout lheure (celui qui crit une commande) :

Version bi-directionnelle (suite, code du client)

Relations 1:N


Exemple : une entreprise a plusieurs employs

Relations 1:N


Exemple : une entreprise a plusieurs employs




Solution plus propre (viter les BLOBs!)

Relations 1:N exemple

Relations 1:N exemple

Exemple de code qui insre des compagnies

Exemple de code qui liste des compagnies

Exemple de client

Version bidirectionnelle

Version bidirectionnelle

Version bidirectionnelle

Relations M:N
Un tudiant suit plusieurs cours, un cours a plusieurs tudiants inscrits


Table de jointure ncessaire.

Relations M:N, choix de conception




Deux possibilits lorsqu'on modlise cette relation avec des EJBs


Utiliser un troisime EJB pour modliser la table de jointure. On veut peut-tre mmoriser la date o un tudiant s'est inscrit, etc Cet EJB possdera deux relations 1:N vers le bean Student et le vers le bean Course 2. Si on na rien besoin de plus part la relation, on peut utiliser simplement deux EJB, chacun ayant un attribut correspondant une Collection de l'autre EJB
1.

Relations M:N, exemple

Relations M:N, exemple

Relations M:N, exemple

Relations M:N, exemple

Relations M:N, exemple

La directionalit et le modle de donnes dans la DB




Quon soit en prsence dun modle normalis ou pas, les outils dORM sadaptent.

Schma normalis

Schma dnormalis

Choisir la directionalit ?
 

Premier critre : la logique de votre application, Second critre : si le schma relationnel existe, s'adapter au mieux pour viter de mauvaises performances.

Lazy-loading des relations




Agressive-loading
  

Lorsqu'on charge un bean, on charge aussi tous les beans avec lesquels il a une relation. Cas de la Commande et des Colis plus tt dans ce chapitre. Peut provoquer un norme processus de chargement si le graphe de relations est grand.

Lazy-loading
 

On ne charge les beans en relation que lorsqu'on essaie d'accder l'attribut qui illustre la relation. Tant qu'on ne demande pas quels cours il suit, le bean Etudiant n'appelle pas de mthode finder sur le bean Cours.

Agrgation vs Composition et destructions en cascade




Relation par Agrgation


  

Le bean utilise un autre bean Consquence : si le bean A utilise le bean B, lorsqu'on dtruit A on ne dtruit pas B. Par exemple, lorsqu'on supprime un tudiant on ne supprime pas les cours qu'il suit. Et vice-versa.

Relation par Composition


   

Le bean se compose d'un autre bean. Par exemple, une commande se compose de lignes de commande Si on dtruit la commande on dtruit aussi les lignes correspondantes. Ce type de relation implique des destructions en cascade..

Relations et JPQL


Lorsqu'on dfinit une relation en CMP, on peut aussi indiquer la requte qui permet de remplir le champs associ la relation. On fait ceci l'aide de JPQL SELECT o.customer FROM Order o
Renvoie tous les clients qui ont plac une commande

Principale diffrence avec SQL, l'oprateur "."




Pas besoin de connatre le nom des tables, ni le nom des colonnes

Relations et EJB-QL


On peut aller plus loin


SELECT o.customer.address.homePhoneNumber FROM Order o

On se promne le long des relations

Relations rcursives


Relation vers un bean de la mme classe




Exemple : Employ/Manager

Rien de particulier, ces relations sont implmentes exactement comme les relations non rcursives

Relations circulaires


Similaire au relations rcursives sauf qu'elles impliquent plusieurs types de beans




Ex : un employ travaille dans une division, une division possde plusieurs ordinateurs (workstation), une workstation est alloue un employ

Ce type de relation, en cas de agressive-loading peut mener une boucle sans fin


Mme problme avec les destructions en cascade

Relations circulaires


Plusieurs stratgies sont possibles


1.

2. 3. 4. 5.

Certains containers proposent d'optimiser le chargement d'un bean en chargeant toutes ses relations en cascade. Attention si relations circulaires ! Supprimer une des relations (!!!) si le modle de conception le permet. Supprimer la bidirectionnalit d'une des relations pour briser le cercle, si le modle de conception le permet. Utiliser le lazy-loading et ne pas faire de destruction en cascade. Les meilleurs moteurs CMP dtectent les relations circulaires et vous permettent de traiter le problme avant le runtime.

Intgrit rfrentielle


Un bean Compagnie, Division, etc relations avec un bean Employ




a des

Si on supprime un employ, il faut vrifier qu'il est bien supprim partout o on a une relation avec lui.

Problme classique dans les SGBDs


Rsolus l'aide de triggers. Ils se dclenchent sitt qu'une perte d'intgrit risque d'arriver et effectuent les oprations ncessaires.  On peut aussi utiliser des procdures stockes via JDBC. Ces procdures effectuent la vrification d'intgrit.


Intgrit rfrentielle


Grer l'intgrit dans le SGBD est intressant si la BD est attaque par d'autres applications que les EJBs Autre approche : grer l'intgrit dans les EJBs
Solution plus propre,  Le SGBD n'est plus aussi sollicit,  Avec les EJB: le travail est fait tout seul !


Intgrit rfrentielle
 

Et dans un contexte distribu ? Plusieurs serveurs d'application avec le mme composant peuvent accder des donnes sur le mme SGBD, Comment mettre jour les relations ? Problme rsolu par les transactions !!!

 

Trier les relations




Lorsquon accde aux relations par un getter, on ne contrle pas par dfaut lordre des lments. Plusieurs solutions sont possibles pour rcuprer des relations sous forme de collections tries
Utiliser lannotation @OrderBy juste avant la dclaration de la relation ou juste avant le getter  Utiliser une requte avec un Order By  Annoter lattribut correspondant la colonne qui sera ordonne, dans lentity de la relation


Trier des relations : annotation @OrderBy


@Entity public class Course { ... @ManyToMany @OrderBy("lastname ASC") List<Student> students; ... }


Remarques
ASC ou DESC pour lordre de tri, ASC par dfaut,  lastname est une proprit de lentit Student.java,  Si la proprit nest pas spcifie -> tri par lid


Trier des relations : annotation @OrderBy


@Entity public class Student { ... @ManyToMany(mappedBy="students") @OrderBy // tri par cl primaire (dfaut) List<Course> courses; ... }


Remarques
ASC ou DESC pour lordre de tri, ASC par dfaut,  lastname est une proprit de lentit Student.java,  Si la proprit nest pas spcifie -> tri par lid


Trier des relations : annotation @OrderBy




On peut utiliser loprateur . si on trie sur une colonne qui est dfinie dans une autre classe par @Embedded

@Entity public class Person { ... @ElementCollection @OrderBy("zipcode.zip, zipcode.plusFour") Set<Address> residences; ... }

Trier des relations : annotation @OrderBy


@Embeddable public class Address { protected String street; protected String city; protected String state; @Embedded Zipcode zipcode; } @Embeddable public class Zipcode { String zip; protected String plusFour; }

Concepts avancs sur la persistence

Introduction

  

Et le polymorphisme ? Et lhritage ? Et EJB-QL ?

Hritage

Stratgies de mapping entre classes et tables quand on a de lhritage ?


Une table pour toute la hirarchie de classes ?  Une table par classe/sous-classe ?  Autres solutions ?


Un exemple !

Code de RoadVehicle.java (classe racine)

Code de Motorcycle.java

Code de Car.java

Code de Roadster.java

Code de Coupe.java

Premier cas : une seule table !

 

Une seule table reprsente toute la hirarchie. Une colonne de discrimination est utilise pour distinguer les sous-classes. Cette solution supporte le polymorphisme. Dsavantages :
Une colonne pour chaque champ de chaque classe,  Comme une ligne peut tre une instance de chaque classe, des champs risquent de ne servir rien (nullable)


 

Regardons le code avec les annotations !

(suite)

Motorcycle.java annot !

Car.java annot

Roadster.java annot

Coupe.java annot

Table correspondante

Quelques objets persistants !

Et les donnes correspondantes

Deuxime stratgie : une table par classe


Il suffit de modifier quelques annotations !


Dans RoadVehicle.java

On peut retirer les @Discriminator des sous-classes (on aura des valeurs par dfaut) Le champ Id de la classe RoadVehicle sera une cl trangre dans les tables des sous-classes, Remarque : on utilise ici @TABLE pour ne pas que la table porte le mme nom que dans lexemple prcdent (facultatif)

Les tables !

Les tables (suite)

Requte SQL pour avoir tous les Roadsters

 

Il faut faire des joins ! Plus la hierarchie est profonde, plus il y aura de jointures : problmes de performance !

Conclusion sur cette approche

  

Supporte le polymorphisme, On alloue juste ce quil faut sur disque, Excellente approche si on a pas une hirarchie trop profonde, A viter sinon

Autres approches

Des classes qui sont des entity bean peuvent hriter de classes qui nen sont pas, Des classes qui ne sont pas des entity beans peuvent hriter de classes qui en sont, Des classes abstraites peuvent tre des entity beans, (dj vu : une classe qui est un entity bean hrite dune autre classe qui est un entity bean)

Cas 1 : Entity Bean tends classe java

On utilise lattribut @mappedsuperclass dans la classe mre




Indique quaucune table ne lui sera associe

Cas 1 (les sous-classes entities)

Cas 1 : les tables

Remarques sur le cas 1

 

RoadVehicle naura jamais sa propre table, Les sous-classes auront leur propre table, avec comme colonnes les attributs de RoadVehicle en plus des leurs, Si on navait pas mis @MappedSuperclass dans RoadVehicle.java, les attributs hrits nauraient pas t des colonnes dans les tables des sous-classes.

Classe abstraite et entity bean

Une classe abstraite peut tre un entity bean (avec @entity) Elle ne peut pas tre instancie, ses sousclasses concrtes oui, Elle aura une table ddie, Elle pourra faire lobjet de requtes (polymorphisme) : trs intressant !

 

Polymorphisme ! Exemple avec un SessionBean

Polymorphisme (suite)

Des requtes polymorphes ! Si ! Si !

Polymorphisme : code client

Polymorphisme : oui, a marche !

Cest bien la mthode toString() de chaque sous-classe qui est appele ! La requte rcupr tous les RoadVehicle (s)

JPQL : Quelques exemples

Voir le fichier PDF fourni avec les TPs !

JPQL : Quelques exemples (suite)

JPQL : Quelques exemples (suite)

JPQL : Quelques exemples (suite)

Liste toutes les commandes qui ne comprennent pas (LEFT) de produit dont le prix est suprieur une certaine quantit (et toutes celles qui nont pas de produits)

Table des compagnies

Table des employs

JPQL : Quelques exemples (suite)

Cette requte rcupre trois compagnies :

Mais celle-ci uniquement deux :

Celle-l en ramne trois aussi (le left matche celles qui nont pas de jointure)

JPQL : Quelques exemples (suite)

Provoque le chargement des entities relies

 

Prend le devant sur @FetchType.LAZY Autre exemple :

JPQL : Quelques exemples (suite)

WHERE et requtes paramtres

Autre exemple avec paramtres nomms

JPQL : Quelques exemples (suite)

Expressions

Le % dans le LIKE = suite de caractres, le _ = un caractre

JPQL : Quelques exemples (suite)

MEMBER OF

Sous-Requtes

Fonctions sur chanes, arithmtique

Fonctions sur chanes, arithmtique (suite)

JPQL : Quelques exemples (suite)

JPQL : Quelques exemples (suite)

Message-Driven Beans
Michel Buffa (buffa@unice.fr), UNSA 2011

Message-Driven Beans
 

Nouveaut apparue avec EJB 2.0, Messaging = moyen de communication lger, compar RMI-IIOP, Pratique dans de nombreux cas, Message-Driven beans = beans accessibles par messaging asynchrone.

 

Message-Driven Beans : motivation




Performance


Un client RMI-IIOP attend pendant que le serveur effectue le traitement d'une requte,

Fiabilit


Lorsqu'un client RMI-IIOP parle avec un serveur, ce dernier doit tre en train de fonctionner. S'il crashe, ou si le rseau crashe, le client est coinc.

Pas de broadcasting !


RMI-IIOP limite les liaisons 1 client vers 1 serveur

Messaging
C'est comme le mail ! Ou comme si on avait une troisime personne entre le client et le serveur !

Messaging


A cause de ce "troisime homme" les performances ne sont pas toujours au rendez-vous ! Message Oriented Middleware (MOM) est le nom donn aux middlewares qui supportent le messaging.


Tibco Rendezvous, IBM MQSeries, BEA Tuxedo/Q, Microsoft MSMQ, Talarian SmartSockets, Progress SonicMQ, Fiorano FioranoMQ, Ces produits fournissent : messages avec garantie de livraison, tolrance aux fautes, load-balancing des destinations, etc

The Java Message Service (JMS)




Les serveurs MOM sont pour la plupart propritaires : pas de portabilit des applications ! JMS = un standard pour normaliser les changes entre composant et serveur MOM,
Une API pour le dveloppeur,  Un Service Provider Interface (SPI), pour rendre connecter l'API et les serveurs MOM, via les drivers JMS


JMS : Messaging Domains




Avant de faire du mesaging, il faut choisir un domaine




Domaine = type de messaging

Domaines possibles


Publish/Subscribe (pub/sub) : n producteurs, n consommateurs (tv) Point To Point (PTP) : n producteurs, 1 consommateur

JMS : les tapes


1.

Localiser le driver JMS




lookup JNDI. Le driver est une connection factory obtenir une connection partir de la connection factory Il s'agit d'un objet qui va servir recevoir et envoyer des messages. On l'obtient partir de la connection. Il s'agit du canal, de la chane tl ! Normalement, c'est rgl par le dployeur. On obtient la destination via JNDI. Utiliss pour crire ou lire un message. On les obtient partir de la destination ou de la session.

2.

Crer une connection JMS




3.

Crer une session JMS




4.

Localiser la destination JMS




5.

Crer un producteur ou un consommateur JMS




6.

Envoyer ou recevoir un message

JMS : les tapes

JMS : les interfaces

JMS : exemple de code (1)

JMS : exemple de code (2)

Note : Dans 3) false = pas de transactions, AUTO_AKNOWLEDGE = inutile ici puisquon envoie des messages.

Intgrer JMS et les EJB


 

Pourquoi crer un nouveau type d'EJB ? Pourquoi ne pas avoir dlgu le travail un objet spcialis ? Pourquoi ne pas avoir augment les caractristiques des session beans ? Parce que ainsi on peut bnficier de tous les avantages dj rencontrs : cycle de vie, pooling, descripteurs spcialiss, code simple

Qu'est-ce qu'un Message-Driven Bean ?




Un EJB qui peut recevoir des messages




Il consomme des messages depuis les queues ou topics, envoys par les clients JMS

Qu'est-ce qu'un Message-Driven Bean ?




Un client n'accde pas un MDB via une interface, il utilise l'API JMS, Un MDB n'a pas d'interface Home, Local Home, Remote ou Local, Les MDB possdent une seule mthode, faiblement type : onMessage()


 

Elle accepte un message JMS (BytesMessage, ObjectMessage, TextMessage, StreamMessage ou MapMessage) Pas de vrification de types la compilation. Utiliser instanceof au run-time pour connatre le type du message.

Les MDB n'ont pas de valeur de retour




Ils sont dcoupls des producteurs de messages.

Qu'est-ce qu'un Message-Driven Bean ?




Pour envoyer une rponse l'expditeur : plusieurs design patterns Les MDB ne renvoient pas d'exceptions au client (mais au container), Les MDB sont stateless Les MDB peuvent tre des abonns durables ou nondurables (durable or nondurable subscribers) un topic
  

 

Durable = reoit tous les messages, mme si l'abonn est inactif, Dans ce cas, le message est rendu persistant et sera dlivr lorsque l'abonn sera de nouveau actif. Nondurable = messages perdus lorsque abonn inactif.

Qu'est-ce qu'un Message-Driven Bean ?




Le consommateur (celui qui peut les dtruire) des messages est en gnral le Container
C'est lui qui choisit d'tre durable ou non-durable,  S'il est durable, les messages rsistent au crash du serveur d'application.


Dvelopper un Message-Driven Bean




Les MDBs doivent implmenter


public void onMessage(Message message);

public interface javax.jms.MessageListener {

} public interface javax.ejb.MessageDrivenBean extends EnterpriseBean {

public void ejbRemove() throws EJBException;

public void setMessageDrivenContext(MessageDrivenContext ctx) throws EJBException; }

La classe d'implmentation doit fournir une mthode ejbCreate() qui renvoit void et qui n'a pas d'arguments.

Dvelopper un Message-Driven Bean




Mthodes qui doivent tre implmentes




onMessage(Message)
 Invoque

chaque consommation de message  Un message par instance de MBD, pooling assur par le container  setMessageDrivenContext(MessageDrivenC ontext)
 Appele

avant ejbCreate, sert rcuprer le contexte.  Ne contient que des mthodes lies aux transactions

Dvelopper un Message-Driven Bean

Un exemple simple


Un MDB qui fait du logging, c'est dire affiche des messages de textes l'cran chaque fois qu'il consomme un message.


Utile pour dbugger

Rappel : pas d'interfaces !

La classe du bean

La classe du bean (suite)

Question ?


Comment sait-on quelle queue ou quel topic de messages le bean consomme ?




Cela n'apparat pas dans le descripteur !

C'est fait exprs pour rendre les MDB portables et rutilisables. L'information se trouve dans l@ActivationConfigProperty au dbut du code

Exemple de descripteur spcifique, tir d'un autre exemple (Borland)


<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE ejb-jar PUBLIC "-//Borland Software Corporation//DTD Enterprise JavaBeans 2.0//EN" "http://www.borland.com/devsupport/appserver/dtds/ejb-jar_2_0-borland.dtd"> <ejb-jar> <enterprise-beans> <message-driven> <ejb-name>HelloEJBQueue</ejb-name> <message-driven-destination-name>serial://jms/q</message-driven-destination-name> <connection-factory-name>serial://jms/xaqcf</connection-factory-name> <pool> <max-size>20</max-size> <init-size>2</init-size> </pool> </message-driven> <message-driven> <ejb-name>HelloEJBTopic</ejb-name> <message-driven-destination-name>serial://jms/t</message-driven-destination-name> <connection-factory-name>serial://jms/tcf</connection-factory-name> <pool> <max-size>20</max-size> <init-size>2</init-size> </pool> </message-driven> </enterprise-beans> </ejb-jar>

Le client (1)
import javax.naming.*;

import javax.jms.*; import java.util.*;

public class Client { public static void main (String[] args) throws Exception { // Initialize JNDI Context ctx = new InitialContext(System.getProperties());

// 1: Lookup ConnectionFactory via JNDI TopicConnectionFactory factory = (TopicConnectionFactory) ctx.lookup("javax.jms.TopicConnectionFactory");

// 2: Use ConnectionFactory to create JMS connection TopicConnection connection = factory.createTopicConnection();

Le client (2)

// 3: Use Connection to create session TopicSession session = connection.createTopicSession( false, Session.AUTO_ACKNOWLEDGE);

// 4: Lookup Destination (topic) via JNDI Topic topic = (Topic) ctx.lookup("testtopic");

// 5: Create a Message Producer TopicPublisher publisher = session.createPublisher(topic);

// 6: Create a text message, and publish it TextMessage msg = session.createTextMessage(); msg.setText("This is a test message."); publisher.publish(msg); } }

Concepts avancs


Transactions et MBD,


La production et la consommation du message sont dans deux transactions spares

Scurit,


Les MDB ne reoivent pas les informations de scurit du producteur avec le message. On ne peut pas effectuer les oprations classiques de scurit sur les EJB.

Load-Balancing,
 

Modle idal : les messages sont dans une queue et ce sont les MDB qui consomment, d'o qu'ils proviennent. Comparer avec les appels RMI-IIOP pour les session et entity beans, ou on ne peut que faire des statistiques

Concepts avancs


Consommation duplique dans les architectures en clusters : utiliser une queue au lieu d'un topic si on veut que le message ne soit consomm qu'une fois ! Chaque container est un consommateur !

Concepts avancs

Piges !


Ordre des messages




Le serveur JMS ne garantit pas l'ordre de livraison des messages.

L'appel ejbRemove() n'est pas garanti, comme pour les session beans stateless
A cause du pooling,  En cas de crash.


Messages empoisonns (poison messages)




A cause des transactions un message peut ne jamais tre consomm

Piges !


Messages empoisonns (poison messages)




A cause des transactions un message peut ne jamais tre consomm

MDB empoisonn !
package examples;

import javax.ejb.*; import javax.jms.*;

public class PoisonBean implements MessageDrivenBean, MessageListener {

private MessageDrivenContext ctx;

public void setMessageDrivenContext(MessageDrivenContext ctx) { this.ctx = ctx; } public void ejbCreate() {} public void ejbRemove() {} ...

MDB empoisonn !
... public void onMessage(Message msg) try { System.out.println("Received msg " + msg.getJMSMessageID()); // Let's sleep a little bit so that we don't see rapid fire re-sends of the message. Thread.sleep(3000); {

// We could either throw a system exception here or // manually force a rollback of the transaction. ctx.setRollbackOnly(); } catch (Exception e) { e.printStackTrace(); } } }

MDB empoisonn !


Solutions
Ne pas lever d'exception,  Utiliser des transactions gres par le bean, non par le container,  Certains serveurs peuvent configurer une "poison message queue" ou possder un paramtre "nb max retries"
 

Comment renvoyer des rsultats l'expditeur du message ?




A faire la main ! Rien n'est prvu !

Comment renvoyer des rsultats l'expditeur du message ?




Nanmoins, des problmes se posent si le client est lui-mme un EJB de type stateful session bean
Que se passe-t-il en cas de passivation ?  Perte de la connexion la destination temporaire!


Solution : ne pas utiliser d'EJB SSB comme client! Utiliser une Servlet ou un JSP Autre solution : configurer un topic permanent pour les rponses, au niveau du serveur JMS.

Comment renvoyer des rsultats l'expditeur du message ?

Comment renvoyer des rsultats l'expditeur du message ?


 

D'autres solutions existent JMS propose deux classes javax.jms.QueueRequestor et javax.jms.TopicRequestor qui implmentent une pattern simple question/rponse Solution bloquante, pas de gestion de transactions JAVA EE 6: invocation de mthode asynchrone !