Mapping avec JPA


De UML à SQL : Relation ManyToMany avec attributs

Article faisant partie d’une série présentant les différentes annotations permettant de traduire des relations entre classes persistantes en bases de données relationnelles.

  Sommaire  

 Présentation

Voyons d’abord comment représenter une relation ManyToMay possédant des attributs en UML. Nous prendrons comme exemple les classes L et M avec comme attribut d’association une donnée nommée options de type String.

En UML nous sommes obligé de passer par une classe d’association, nommée ClasseLM dans cet exemple.

Pour pouvoir traduire notre exemple en Java avec JPA  , nous allons être obligé de modifier notre diagramme de classes pour traduire notre classe d’association en classe standard. Ce qui donne :

Ce qui nous donne 2 jointures de type OneToMany sur la classe LM qui correspondra à une table de jointure dans la base de données. Il reste maintenant à définir l’identifiant de cette classe qui sera composé des 2 clés des classes L et M.

Code Java

Comme la classe LM servant de jointure possède une clé composée, nous somme obligé de créer d’abord une classe pour la clé :

Code de la classe clé composite :

  1. public class ClasseLM_pk implements Serializable
  2. {
  3.   private Long idL;
  4.   private Long idM;
  5.  
  6.   @Override
  7.   public int hashCode()
  8.   {
  9.     ...
  10.   }
  11.  
  12.   @Override
  13.   public boolean equals( Object obj )
  14.   {
  15.     ...
  16.   }

Télécharger

Cette classe n’est pas une entity mais doit être Sérializable et doit avoir ces méthodes hashCode() et equals() de redéfinies pour pouvoir être utilisée comme clé composite.

Pour les 3 classes suivantes, nous nous retrouverons avec des relations OnToMany bidirectionnelles.

Voici le code de la classe L.

  1. @Table( name = "T_TABLE_L")
  2. public class ClasseL implements Serializable
  3. {
  4.   @Id
  5.   @GeneratedValue( strategy = GenerationType.IDENTITY )
  6.   @Column( name = "L_ID" )
  7.   private Long id;
  8.  
  9.   @Column( name = "L_REMARQUE" )
  10.   private String remarque;
  11.  
  12.   @OneToMany( mappedBy = "classeL", cascade =  CascadeType.PERSIST )
  13.   private List< ClasseLM > listeM;
  14. ...

Télécharger

Le code de la classe M ;

  1. @Table( name = "T_TABLE_M" )
  2. public class ClasseM implements Serializable
  3. {
  4.   @Id
  5.   @GeneratedValue( strategy = GenerationType.IDENTITY )
  6.   @Column( name = "M_ID" )
  7.   private Long id;
  8.  
  9.   @Column( name = "M_REMARQUE" )
  10.   private String remarque;
  11.  
  12.   @OneToMany( mappedBy = "classeM", cascade = CascadeType.PERSIST )
  13.   private List< ClasseLM > listeL;
  14. ...

Télécharger

Le code de la classe intermédiaire LM.

  1. @Table( name = "T_TABLE_LM" )
  2. @IdClass( ClasseLM_pk.class )
  3. public class ClasseLM implements Serializable
  4. {
  5.   @Id
  6.   @Column( name = "LM_ID_L_FK", nullable = false )
  7.   private Long idL;
  8.  
  9.   @Id
  10.   @Column( name = "LM_ID_M_FK", nullable = false )
  11.   private Long idM;
  12.  
  13.   @Column( name = "LM_OPTIONS" )
  14.   private String options;
  15.  
  16.   @ManyToOne( cascade = CascadeType.PERSIST )
  17.   @JoinColumn( name = "LM_ID_L_FK", insertable = false, updatable = false )
  18.   private ClasseL classeL;
  19.  
  20.   @ManyToOne( cascade = CascadeType.PERSIST )
  21.   @JoinColumn( name = "LM_ID_M_FK", insertable = false, updatable = false )
  22.   private ClasseM classeM;
  23. ...

Télécharger

Les tables correspondantes

Structure de la table L :

Structure de la table M :

Structure de la table LM ;

Et voici le script SQL   permettant de générer les tables :

Je ne vous retranscrit pas ici les scripts des tables L et M qui n’on rien de particulier mais uniquement celui de la table de jointure.

Script de la table T_TABLE_LM :

  1.  CREATE TABLE `T_TABLE_LM` (
  2.   `LM_ID_L_FK` BIGINT(20) NOT NULL,
  3.   `LM_ID_M_FK` BIGINT(20) NOT NULL,
  4.   `LM_OPTIONS` VARCHAR(255) DEFAULT NULL,
  5.   PRIMARY KEY (`LM_ID_L_FK`,`LM_ID_M_FK`),
  6.   KEY `FK_T_TABLE_LM_LM_ID_M_FK` (`LM_ID_M_FK`),
  7.   CONSTRAINT `FK_T_TABLE_LM_LM_ID_M_FK` FOREIGN KEY (`LM_ID_M_FK`) REFERENCES `T_TABLE_M` (`M_ID`),
  8.   CONSTRAINT `FK_T_TABLE_LM_LM_ID_L_FK` FOREIGN KEY (`LM_ID_L_FK`) REFERENCES `T_TABLE_L` (`L_ID`)
  9. ) ENGINE=InnoDB DEFAULT CHARSET=latin1

Télécharger

On peut remarquer que cette table dispose bien d’une clé primaire composite mais que nous avons également chaque champs de cette clé comme clé étrangère vers les 2 autres tables.

 Conclusion

Nous avons vu que pour traduire le concept UML de classe d’association, nous devons passer par une modification du modèle pour transformer une relation ManyToMany en 2 relations OneToMany.

Article n° 51

Crée par: chris

Créé le: 3 octobre 2015

Modifié le: 3 octobre 2015

Nombre de visites: 2923

Popularité: 10 %

Popularité absolue: 2

Mots clés de cet article


SPIP

2003-2019 LePpf
Plan du site | | Contact | RSS 2.0

Visiteurs connectés : 5

Nombre moyen de visites quotidiennes sur le site: 217