Java Persistence API (la suite)

publicité
Java Persistence API (la suite)
Quelques liens :
La page JPA chez Sun
http://java.sun.com/javaee/technologies/persistence.jsp
Javadoc de l’API JPA 1.0 (JEE 5)
http://java.sun.com/javaee/5/docs/api/javax/persistence/package-summary.html
Javadoc de l’API JPA 2.0 (JEE 6)
http://java.sun.com/javaee/6/docs/api/javax/persistence/package-summary.html
Le tutorial JPA 1.0 (JEE 5)
http://java.sun.com/javaee/5/docs/tutorial/doc/bnbpy.html
Le tutorial JPA 2.0 (JEE 6)
http://java.sun.com/javaee/6/docs/tutorial/doc/bnbpy.html
La page de Wikipedia
http://en.wikipedia.org/wiki/Java Persistence API
De très bons exemples
http://schuchert.wikispaces.com/EJB+3+and+Java+Persistence+API
http://www.java2s.com/Tutorial/Java/0355 JPA/Catalog0355 JPA.htm
Un petit manuel de référence
http://jszyzx.scu.edu.cn/resin-doc/amber/index.xtp
Une documentation sur JPQL
http://download.oracle.com/docs/cd/E13189 01/kodo/docs40/full/html/ejb3 overview query.html
1
Rendre la DAO plus générique
Afin d’éviter la création de nombreuses méthodes (quatre pour chaque entité), nous pouvons maintenant doter
notre classe Dao de nouvelles méthodes génériques :
public <T> T find(Class<T> clazz, Object id) {
EntityManager em = null;
try {
em = newEntityManager();
return em.find(clazz, id);
} finally {
closeEntityManager(em);
}
}
public <T> Collection<T> findAll(String query, Class<T> clazz) {
EntityManager em = null;
try {
em = newEntityManager();
TypedQuery<T> q = em.createQuery(query, clazz);
return q.getResultList();
} finally {
closeEntityManager(em);
}
}
ajout, mise à jour et destruction :
1
public <T> T add(T entity) {
EntityManager em = null;
try {
em = newEntityManager();
em.persist(entity);
em.getTransaction().commit();
return (entity);
} finally {
closeEntityManager(em);
}
}
public <T> T update(T entity) {
EntityManager em = null;
try {
em = newEntityManager();
entity = em.merge(entity);
em.getTransaction().commit();
} finally {
closeEntityManager(em);
}
return entity;
}
public <T> void remove(Class<T> clazz, Object pk) {
EntityManager em = null;
try {
em = newEntityManager();
T entity = em.find(clazz, pk);
if (entity != null) {
em.remove(entity);
}
em.getTransaction().commit();
} finally {
closeEntityManager(em);
}
}
2
2.1
Héritage
Héritage avec table unique
Nous allons étudier la représentation d’un arbre d’héritage dans une structure relationnelle. Définissons trois
classes : une pour les UE, une autre (qui hérite de la première) pour les UE de master et une troisième (qui hérite
également de la première) pour les UE de Licence :
2
package monpkg.entities;
import java.io.Serializable;
import javax.persistence.Basic;
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class UE implements Serializable {
private static final long serialVersionUID = 1L;
@Id()
private String code;
@Basic()
private int credits;
public UE() {
super();
}
public UE(String code, int credits) {
super();
this.code = code;
this.credits = credits;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public int getCredits() {
return credits;
}
public void setCredits(int credits) {
this.credits = credits;
}
@Override
public String toString() {
return String.format("UE(code=%s,credits=%d)", code, credits);
}
}
Les UE de Master :
3
package monpkg.entities;
import javax.persistence.Basic;
import javax.persistence.Entity;
@Entity
public class MasterUE extends UE {
private static final long serialVersionUID = 1L;
@Basic
private String masterName;
public MasterUE() {
super();
}
public MasterUE(String code, int credits, String masterName) {
super(code, credits);
this.masterName = masterName;
}
public String getMasterName() {
return masterName;
}
public void setMasterName(String masterName) {
this.masterName = masterName;
}
@Override
public String toString() {
return String.format("MasterUE(code=%s,credits=%d,master=%s)",
getCode(), getCredits(), masterName);
}
}
Les UE de Licence :
4
package monpkg.entities;
import javax.persistence.Basic;
import javax.persistence.Entity;
@Entity
public class LicenceUE extends UE {
private static final long serialVersionUID = 1L;
@Basic
private String description;
public LicenceUE() {
super();
}
public LicenceUE(String code, int credits, String description) {
super(code, credits);
this.description = description;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@Override
public String toString() {
return String.format("LicenceUE(code=%s,credits=%d,description=%s)",
getCode(), getCredits(), description);
}
}
Travail à faire : Faites un test unitaire en créant (en base) une instance de chaque classe. Analysez la table
unique créée par JPA. Utilisez ensuite la méthode findAll pour chaque classe et vérifiez que vous obtenez 3 UE,
1 UE de Master et 1 UE de Licence.
2.2
Héritage avec table de jointure
Dans cette deuxième stratégie, les classes sont représentées par plusieurs tables mais les propriétés communes
sont représentées une seule fois :
...
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class UE implements Serializable {
...
}
Travail à faire : N’oubliez pas détruire la table précédente avant d’exécuter cette version. Analysez les tables
créées par JPA.
5
2.3
Héritage avec tables séparées
Dans cette troisième stratégie, les classes sont représentées par plusieurs tables spéparées :
...
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class UE implements Serializable {
...
}
Travail à faire : N’oubliez pas détruire la table précédente avant d’exécuter cette version. Analysez les tables
créées par JPA.
3
Requêtes construites par programmation
Jusqu’à maintenant nous avons directement utilisé des requêtes JPQL sous la forme de chaı̂ne de caractères
éventuellement paramétrées. A partir de JPA 2 il est possible de construire dynamiquement une requête bien
typée à partir d’une API.
Travail à faire : En vous aidant de ce chapitre du tutoriel JEE˜6 1 , améliorez la méthode findAll en supprimant
le paramètre query que nous utilisions avant.
public <T> Collection<T> findAll(Class<T> clazz) {
...
}
Tentez ensuite de construire une méthode qui renvoie les UE de Master à 6 crédits. Pour ce faire, vous devez ajouter
un critère à votre requête (méthode where appliquée à l’instance de la classe CriteriaQuery<MasterUE>).
1. http://download.oracle.com/javaee/6/tutorial/doc/gjivm.html
6
Téléchargement