IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

JPA Java Discussion :

[JPA / Hibernate] Table avec des jointures non naturelles


Sujet :

JPA Java

  1. #1
    Membre averti
    Homme Profil pro
    Développeur Java
    Inscrit en
    Février 2006
    Messages
    380
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : Enseignement

    Informations forums :
    Inscription : Février 2006
    Messages : 380
    Points : 314
    Points
    314
    Par défaut [JPA / Hibernate] Table avec des jointures non naturelles
    Bonjour,
    Ja précise que nous travaillons en JPA 2 avec hibernate, donc il est possible, même si ce n'est pas souhaitable d'avoir des annotations purement hibernate.

    Avec mes collègues nous avons besoin de créer une table de traduction et voici la solution que nous envisageons au niveau de la base (les noms de tables sont en gras , le nom des champs en italique :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    langue
    id (pk)
    code
    libelle
    
    a
    id (pk)
    
    b
    id (pk)
    
    traduction
    nomTable(Pk)
    nomChamp(Pk)
    idDansLaTable(Pk)
    idLangue(Pk)(FK)
    texte
    Nous aurions donc des entitys nommés Traduction,Langue,A et B comme on le voit il n'y a pas de vraies références de Traduction ni vers A ni vers B.
    On ne fera pas de détails sur l'objet traduction si ce n'est qu'à mon avis il ne pourra pas contenir de référence vers A ni B. Voici ce que nous aimerions avoir très schématiquement

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    class A{
    id
    Map<Langue,Traduction> libelle
    Map<Langue,Traduction> description
    }
     
    class B{
    id
    Map<Langue,Traduction> libelleCourt
    Map<Langue,Traduction> libelleLong
    Map<Langue,Traduction> autre
    }
    J'ai déjà une partie de réponse pour ce qui est de la MAP on peu utiliser des
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    @MapKeyColumn
    ou
    @MapKeyClass
    Nous avons vu une annotation @JoinColumnsOrFormulas, mais il y a peu de documentation

  2. #2
    Membre averti
    Homme Profil pro
    Développeur Java
    Inscrit en
    Février 2006
    Messages
    380
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : Enseignement

    Informations forums :
    Inscription : Février 2006
    Messages : 380
    Points : 314
    Points
    314
    Par défaut
    Bon voilà j'ai réussi mon mapping
    voici :
    pour l'objet A on remarquera que de ce côté de l'objet on a que du JPA pur. L'annotation @MapKey nous permet de mapper directement un objet dans mon entité destination.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
     
    import java.io.Serializable;
    import java.util.HashMap;
    import java.util.Map;
     
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;
    import javax.persistence.MapKey;
    import javax.persistence.OneToMany;
    import javax.persistence.SequenceGenerator;
    import javax.persistence.Table;
     
    import fr.utbm.cri.pedago.jpa.utbm_pedago.Langue;
    @Entity
    @Table(name = "A",schema="UTBM_PEDAGO")
    public class A implements Serializable {
    	private static final long serialVersionUID = 1L;
     
    	@Id
    	@SequenceGenerator(name = "ID_A_GENERATOR", sequenceName = "UTBM_PEDAGO.A_SEQ", allocationSize = 1, initialValue = 1)
    	@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ID_A_GENERATOR")
    	@Column(name = "ID_A")
    	private long idA;
     
    	public A() {
    	}
     
    	@OneToMany(mappedBy="aLibelle")
    	@MapKey(name="langue")
    	private Map<Langue,TraductionTest> listeTraductionTestLibelle=new HashMap<>();
     
    	@OneToMany(mappedBy="aLibelleCourt")
    	@MapKey(name="langue")
    	private Map<Langue,TraductionTest> listeTraductionTestLibelleCourt=new HashMap<>();
     
    	public long getIdA() {
    		return this.idA;
    	}
     
    	public void setIdA(long idA) {
    		this.idA = idA;
    	}
     
    	public Map<Langue, TraductionTest> getListeTraductionTestLibelle() {
    		return listeTraductionTestLibelle;
    	}
     
    	public void setListeTraductionTestLibelle(Map<Langue, TraductionTest> listeTraductionTestLibelle) {
    		this.listeTraductionTestLibelle = listeTraductionTestLibelle;
    	}
     
    	public Map<Langue, TraductionTest> getListeTraductionTestLibelleCourt() {
    		return listeTraductionTestLibelleCourt;
    	}
     
    	public void setListeTraductionTestLibelleCourt(Map<Langue, TraductionTest> listeTraductionTestLibelleCourt) {
    		this.listeTraductionTestLibelleCourt = listeTraductionTestLibelleCourt;
    	}
    }


    objet B (à peu près identique)=> je zappe les imports vu que c'est à peu près les mêmes
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    @Entity
    public class B implements Serializable {
    	private static final long serialVersionUID = 1L;
     
    	@Id
    	@SequenceGenerator(name="B_IDB_GENERATOR", sequenceName="B_SEQ", allocationSize = 1, initialValue = 1)
    	@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="B_IDB_GENERATOR")
    	@Column(name="ID_B")
    	private long idB;
     
    	public B() {
    	}
     
    	@OneToMany(mappedBy="bLibelle")
    	@MapKey(name="langue")
    	private Map<Langue,TraductionTest> listeTraductionTestLibelle=new HashMap<>();
     
     
    	public long getIdB() {
    		return this.idB;
    	}
     
    	public void setIdB(long idB) {
    		this.idB = idB;
    	}
     
    	public Map<Langue, TraductionTest> getListeTraductionTestLibelle() {
    		return listeTraductionTestLibelle;
    	}
     
    	public void setListeTraductionTestLibelle(Map<Langue, TraductionTest> listeTraductionTestLibelle) {
    		this.listeTraductionTestLibelle = listeTraductionTestLibelle;
    	}
     
     
    }

    objet TraductionTest on remarquera l'utilisation de l'annotation @Where qui vient d'hibernate.
    Cette annotation nous permet de faire une sélection précise et donc d'affiner notre mapping. il est important de noter le (insertable=false et updatable=false, sans quoi le mapping ne fonctionnera pas.

    On remarquera le setter des différents objets permettant de ne pas faire d'erreurs sur les champs et libellés.


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
     
    package fr.cri.pedago.jpa.special;
     
    import java.io.Serializable;
    import javax.persistence.*;
     
    import org.hibernate.annotations.Where;
     
    import fr.utbm.cri.pedago.jpa.utbm_pedago.Langue;
     
    /**
     * The persistent class for the TRADUCTION_TEST database table.
     * 
     */
    @Entity
    @Table(name = "TRADUCTION_TEST")
    public class TraductionTest implements Serializable {
    	private static final long serialVersionUID = 1L;
     
    	@Id
    	@SequenceGenerator(name = "TRADUCTION_TEST_IDTRADUCTIONTEST_GENERATOR", sequenceName = "TRADUCTION_TEST_SEQ", allocationSize = 1, initialValue = 1)
    	@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "TRADUCTION_TEST_IDTRADUCTIONTEST_GENERATOR")
    	@Column(name = "ID_TRADUCTION_TEST")
    	private Long id;
     
    	@Column(name = "ID_DANS_TABLE")
    	private Long idDansTable;
     
    	@Column(name = "NOM_CHAMP")
    	private String nomChamp;
     
    	@Column(name = "NOM_TABLE")
    	private String nomTable;
     
    	@ManyToOne
    	@JoinColumn(name = "ID_DANS_TABLE", referencedColumnName = "ID_A", insertable = false, updatable = false)
    	@Where(clause = "NOM_TABLE='A' AND NOM_CHAMP='LIBELLE'")
    	private A aLibelle;
     
     
    	@ManyToOne
    	@JoinColumn(name = "ID_DANS_TABLE", referencedColumnName = "ID_A", insertable = false, updatable = false)
    	@Where(clause = "NOM_TABLE='A' AND NOM_CHAMP='LIBELLE_COURT'")
    	private A aLibelleCourt;
     
    	@ManyToOne
    	@JoinColumn(name = "ID_DANS_TABLE", referencedColumnName = "ID_B", insertable = false, updatable = false)
    	@Where(clause = "NOM_TABLE='B' AND NOM_CHAMP='LIBELLE'")
    	private B bLibelle;
     
    	@ManyToOne
    	@JoinColumn(name = "ID_LANGUE")
    	private Langue langue;
     
    	private String texte;
     
    	public TraductionTest() {
    	}
     
    	public Long getId() {
    		return id;
    	}
     
    	public void setId(Long id) {
    		this.id = id;
    	}
     
    	public Long getIdDansTable() {
    		return this.idDansTable;
    	}
     
    	public void setIdDansTable(Long idDansTable) {
    		this.idDansTable = idDansTable;
    	}
     
    	public String getNomChamp() {
    		return this.nomChamp;
    	}
     
    	public void setNomChamp(String nomChamp) {
    		this.nomChamp = nomChamp;
    	}
     
    	public String getNomTable() {
    		return this.nomTable;
    	}
     
    	public void setNomTable(String nomTable) {
    		this.nomTable = nomTable;
    	}
     
    	public String getTexte() {
    		return this.texte;
    	}
     
    	public void setTexte(String texte) {
    		this.texte = texte;
    	}
     
    	public Langue getLangue() {
    		return langue;
    	}
     
    	public void setLangue(Langue langue) {
    		this.langue = langue;
    	}
     
    	public A getaLibelle() {
    		return aLibelle;
    	}
     
    	public void setaLibelle(A aLibelle) {
    		this.aLibelle = aLibelle;
    		nomTable = "A";
    		nomChamp = "LIBELLE";
    		idDansTable=aLibelle.getIdA();
    		this.aLibelle = aLibelle;
     
    	}
     
    	public A getaLibelleCourt() {
    		return aLibelleCourt;
    	}
     
    	public void setaLibelleCourt(A aLibelleCourt) {
    		this.aLibelleCourt = aLibelleCourt;
    		nomTable = "A";
    		nomChamp = "LIBELLE_COURT";
    		idDansTable=aLibelleCourt.getIdA();
    		this.aLibelleCourt=aLibelleCourt;
    	}
     
    	public B getbLibelle() {
    		return bLibelle;
    	}
     
    	public void setbLibelle(B bLibelle) {
    		this.bLibelle = bLibelle;
    		nomTable = "B";
    		nomChamp = "LIBELLE";
    		idDansTable=bLibelle.getIdB();
    		this.bLibelle = bLibelle;
    	}
     
     
    }
    Enfin voici comment il est possible d'utiliser nos objets très simplement
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
     
    emf = Persistence.createEntityManagerFactory("pedago.jpa");
    em = emf.createEntityManager();
     
    Langue francais = em.createQuery("Select l from Langue l where code= :codeLangue", Langue.class).setParameter("codeLangue", "fr").getSingleResult();
    Langue anglais = em.createQuery("Select l from Langue l where code= :codeLangue", Langue.class).setParameter("codeLangue", "en").getSingleResult();
     
    em.getTransaction().begin();
     
    System.out.println("id langue=" + francais.getId());
    ////////////////////////////////////
    ////début de la transaction/////////
    ////////////////////////////////////
     
    // création de A
    A a = new A();
    em.persist(a);
    // création de B
    B b = new B();
    em.persist(b);
     
    // /////////////////////////////////////////////
    // création de TraductionLibelle A en français//
    // /////////////////////////////////////////////
     
    TraductionTest traductionLibelleAFrancais = new TraductionTest();
    traductionLibelleAFrancais.setaLibelle(a);
    traductionLibelleAFrancais.setLangue(francais);
    traductionLibelleAFrancais.setTexte("mon tailleur est riche");
    francais.getListeTraductionTest().add(traductionLibelleAFrancais);
    a.getListeTraductionTestLibelle().put(francais, traductionLibelleAFrancais);
    em.persist(traductionLibelleAFrancais);
     
    // //////////////////////////////////////////////////
    // création de TraductionLibelleCourt A en français//
    // //////////////////////////////////////////////////
    TraductionTest traductionLibelleCourtAFrancais = new TraductionTest();
    traductionLibelleCourtAFrancais.setaLibelleCourt(a);
    traductionLibelleCourtAFrancais.setLangue(francais);
    traductionLibelleCourtAFrancais.setTexte("mon tailleur");
     
    francais.getListeTraductionTest().add(traductionLibelleCourtAFrancais);
    a.getListeTraductionTestLibelleCourt().put(francais, traductionLibelleCourtAFrancais);
     
    em.persist(traductionLibelleCourtAFrancais);
     
    // ////////////////////////////////////////////
    // création de TraductionLibelle A en anglais//
    // ////////////////////////////////////////////
    TraductionTest traductionLibelleAAnglais = new TraductionTest();
    traductionLibelleAAnglais.setaLibelle(a);
    traductionLibelleAAnglais.setLangue(anglais);
    traductionLibelleAAnglais.setTexte("my taylor is rich");
    anglais.getListeTraductionTest().add(traductionLibelleAAnglais);
    a.getListeTraductionTestLibelle().put(anglais, traductionLibelleAAnglais);
     
    em.persist(traductionLibelleAAnglais);
     
    // ///////////////////////////////////////////////
    // création de TraductionLibelleCourt en anglais//
    // ///////////////////////////////////////////////
    TraductionTest traductionLibelleCourtAAnglais = new TraductionTest();
    traductionLibelleCourtAAnglais.setaLibelleCourt(a);
    traductionLibelleCourtAAnglais.setLangue(anglais);
    traductionLibelleCourtAAnglais.setTexte("my taylor");
     
    anglais.getListeTraductionTest().add(traductionLibelleCourtAAnglais);
    a.getListeTraductionTestLibelleCourt().put(anglais, traductionLibelleCourtAAnglais);
    em.persist(traductionLibelleCourtAAnglais);
     
    // /////////////////////////////////////////////
    // création de TraductionLibelle B en français//
    // /////////////////////////////////////////////
    TraductionTest traductionLibelleBFrancais = new TraductionTest();
    traductionLibelleBFrancais.setbLibelle(b);
    traductionLibelleBFrancais.setLangue(francais);
    traductionLibelleBFrancais.setTexte("vos fleurs sont belles");
    francais.getListeTraductionTest().add(traductionLibelleBFrancais);
    b.getListeTraductionTestLibelle().put(francais, traductionLibelleBFrancais);
    em.persist(traductionLibelleBFrancais);
     
    // ////////////////////////////////////////////
    // création de TraductionLibelle B en anglais//
    // ////////////////////////////////////////////
    TraductionTest traductionLibelleBAnglais = new TraductionTest();
    traductionLibelleBAnglais.setbLibelle(b);
    traductionLibelleBAnglais.setLangue(anglais);
    traductionLibelleBAnglais.setTexte("your flowers are beautiful");
    anglais.getListeTraductionTest().add(traductionLibelleBAnglais);
    b.getListeTraductionTestLibelle().put(anglais, traductionLibelleBAnglais);
    em.persist(traductionLibelleBAnglais);
     
    ////////////////////////////
    //fin de la transaction/////
    ////////////////////////////
    em.getTransaction().commit();
     
    // lecture d'un objet a
    A aLu = em.createQuery("Select a from A a where id= :id", A.class).setParameter("id", a.getIdA()).getSingleResult();
    for (Langue element : aLu.getListeTraductionTestLibelle().keySet()) {
    	System.out.println("---> Langue : " + element.getLibelle() + " traduction A Libellé : " + aLu.getListeTraductionTestLibelle().get(element).getTexte());
    }
    for (Langue element : aLu.getListeTraductionTestLibelleCourt().keySet()) {
    	System.out.println("---> Langue : " + element.getLibelle() + " traduction A LibelléCourt : " + aLu.getListeTraductionTestLibelleCourt().get(element).getTexte());
    }
    //lecture d'un objet B
    B bLu = em.createQuery("Select b from B b where id= :id", B.class).setParameter("id", b.getIdB()).getSingleResult();
    for (Langue element : bLu.getListeTraductionTestLibelle().keySet()) {
    	System.out.println("---> Langue : " + element.getLibelle() + " traduction B Libellé : " + bLu.getListeTraductionTestLibelle().get(element).getTexte());
    }
     
    em.close();
    emf.close();
    il y a probablement moyen de faire mieux en utilisant des génériques et de l'héritage sur l'objet Traduction, il faut que je travaille ça, je posterai quand ce sera ok

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 2
    Dernier message: 11/05/2009, 09h36
  2. Jointure entre 2 tables avec des champs de types différents
    Par qltmi dans le forum Requêtes et SQL.
    Réponses: 4
    Dernier message: 27/11/2008, 20h58
  3. Réponses: 3
    Dernier message: 12/06/2007, 23h31
  4. Création des tables avec les jointures.
    Par alexandrebergercyr dans le forum Langage SQL
    Réponses: 6
    Dernier message: 06/03/2007, 15h25
  5. Peut on utiliser OR avec des jointures de tables??
    Par gins06 dans le forum Langage SQL
    Réponses: 2
    Dernier message: 04/10/2005, 12h40

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo