Avec l'arrivée de la norme JEE 6, JPA dévoile sa version 2.0.
Nous allons voir ensemble les nouveautés apportées par cette nouvelle version.
Pour ceux qui ne sont pas encore familiarisés avec JPA 1er du nom, je vous conseille la lecture de ce tutoriel.
A l'aide de nouvelles annotations, JPA 2 offre de nouvelles manières de mapper et de persister les collections.
@ElementCollection
L'annotation ElementCollection offre des facilités pour la persistence des listes de types primitifs ou de types de base de Java comme Integer ou String.
Auparavant, pour persister une liste de String par exemple, il était nécessaire de persister sous forme de Blob un objet sérialisé contenant les valeurs à enregistrer, cet objet pouvant être une ArrayList ou un HashSet par exemple . Le "probleme" venant du fait que le type String n'étant pas une entité JPA, il ne pouvait être mappé avec un traditionnel @ManyToOne ou @ManyToMany. Un autre contournement possible était de créer une entité JPA comprenant uniquement le String à persister entant qu'attribut et éventuellement une clé technique. Créer une telle table parait logique si on analyse le problème d'un point de vue relationnel, par contre d'un point de vue objet il est dommage d'avoir à s'encombrer d'une telle classe.
Heureusement avec JPA 2 et l'annotation ElementCollection , ce genre de mapping devient beaucoup plus naturel.
Cette annotation s'utilise comme ceci :
@ElementCollection @CollectionTable(name = "nom") @Column(name = "value") List<String> noms;
En utilisant cette annotation, une table comprenant une clé technique + la valeur à enregistrer pour chaque String sera créee automatiquement et utilisée de manière transparente. JPA fait donc bien son travail : s'occuper des problématiques de stockage des données dans le modèle relationnel, en laissant le développeur créer un modèle cohérent d'un point de vue objet.
L'annotation Column permet de spécifier le nom de la colonne qui contiendra les valeurs (des String dans notre exemple) à persister.
Enfin, l'annotation CollectionTable permet de spécifier le nom de la table à générer pour stocker ces valeurs.
Les annotation Column et CollectionTable sont optionnelles, si elles ne sont pas présentes des valeurs par défauts seront utilisées pour les noms de tables et de colonnes.
Et pour les Maps ?
Si l'on désire persister une Map, l'annotation MapKeyColumn permet de spécifier le nom de la colonne qui contient la clé de la Map . On mappe ici des numéros de mois avec le nom du mois , par exemple (3,"Mars") :
@ElementCollection @CollectionTable(name="track") @MapKeyColumn (name = "monthNumber") @Column(name = "month") private Map<Integer,String> months;
Orphan removal
L'option orphanRemoval a été ajoutée aux annotations @OneToMany et @OneToOne.
Ainsi si un objet anciennement référencé comme lié à votre entité n'est plus attachée à celle ci, il sera supprimé de la base. Ceci évite donc d'avoir des données orphelines qui trainent dans la base. Cela n'est malheureusement pas possible pour les liens de type ManyToMany et ManyToOne car l'ORM ne peut pas savoir après suppression d'un lien si l'ancien objet lié n'est pas référencé par un autre objet sans lancer une requête.
Order column
Enfin, la dernière annotation que nous allons voir aujourd'hui : @OrderColumn permet de spécifier pour une collection d'entités une colonne de tri, pour la lecture et pour l'écriture.
Ainsi au moment de persister la collection, un tri sera effectué pour que les données soient ordonnées en base selon ce critère. Lors de la lecture, un simple "order by" sera utilisé pour ramener les données dans l'ordre souhaité.
Par exemple on trie ici les livres d'une bibliothèque en fonction de leur titre :
@Entity
public class Bibilotheque {
@Id int id;
@ManyToMany
@OrderColumn(name="titre")
List<Livre> livres;
}
4 commentaires:
Salut,
je tenais à te féliciter pour le partage de ton savoir sur JPA 2eme du nom. Cela nous permet de bien comprendre les apports de cette nouvelle version par rapport à l'ancienne si je peux dire.
Merci bien.
Merci à toi c'est le genre de commentaire qui fait vraiment plaisir :)
Merci Loïc pour cet article qui permet de se mettre à jour à la nouvelle version de JPA. Pour la liste, je crois que tu devrais montrer en exemple comment spécifier la colonne qui permet l'ordre. Aussi, je n'ai pas trouvé le mode flush manuel qu'à Hibernate pour la gestion du contexte de persistance dans la nouvelle version de JPA. Je trouve ça malheureux car ça nous force à maintenir l'état pour les DAO avec des stateful session beans même si on n'en a pas besoin. J'espère que ça viendra plus tard mais il est un peu tard...
Est ce que quelqu'un sait si l'annotation @OrderColumn fonctionne avec le lazy loading :
fetch=FetchType.LAZY ?
Enregistrer un commentaire