Précédent   Forum des professionnels en informatique > Java > Général Java > Persistance > JPA
JPA Forum d'entraide sur l'API de persistance JPA (Java Persistence API)
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 01/02/2012, 11h53   #1
Membre régulier
 
Homme Gaël
Ingénieur développement logiciels
Inscription : octobre 2008
Messages : 139
Détails du profil
Informations personnelles :
Nom : Homme Gaël
Localisation : France, Isère (Rhône Alpes)

Informations professionnelles :
Activité : Ingénieur développement logiciels
Secteur : High Tech - Opérateur de télécommunications

Informations forums :
Inscription : octobre 2008
Messages : 139
Points : 86
Points : 86
Par défaut Peut-on réaliser une relation oneToOne avec plusieurs clefs étrangères de même type ?

Bonjour,

je ne suis pas certain que mon titre est clair, alors je vais détailler un peu plus ma question.
Tout d'abord, il est important de préciser que je ne maîtrise pas du tout JPA et hibernate; mes connaissances à ce sujet sont purement empiriques et il me manque donc certainement des notions fondamentales. Je dois pourtant intervenir dessus, d'où des questions dont les réponses seront souvent triviales à des initiés!

J'en viens donc à ma question.

Je dispose d'une classe "Operation" qui possède plusieurs clefs de même type vers un objet de type "Promotion". Pour des raisons très spécifiques au projet, on ne peut pas changer ce fait.
Celà ressemble à:
Code :
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
@Entity
@Table(name = "operation")
public class Operation {
 
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int                id;
 
    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "promotion_fk")
    private Promotion               promotion;
 
    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "promotion_interne_fk")
    private Promotion               privatePromotion;
 
    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "promotion_legale_fk")
    private Promotion               legalPromotion;
 
    // + getters/ setters
 
    }
 
 
@Entity
@Table(name = "promotion")
public class Promotion {
    @Id
    @GeneratedValue
    private int     id;
 
    // ICI ce que je voudrais
 
    @OneToOne
    @MappedBy(???)
    Operation parentOperation;
 
    // + getters/ setters
    }
Je voudrais pouvoir, depuis n'importe quelle promotion, trouver son parent.
Est-il possible de réaliser cette relation sans changer la structure de la base, juste en jouant avec les annotations, voire en rajoutant un ou plusieurs champs.

Je sais que celà est possible en créant des descendants de Promotion et en les typant, mais c'est une solution que je ne peux malheureusement pas mettre en œuvre (à cause principalement de l'impact sur le projet).

Si quelqu'un(e) a idée, je suis tout ouï. Et en attendant, je vous remercie déjà de m'avoir lu jusque là!
__________________
Roger l'Âne: le lapin devenu grand....
_______________________________________________________________
Développeur bio-informatique; spécialiste en rien, généraliste en tout.

Capitan ! Capitan ! On a aperçu le Loup ! Il a pris d'assaut une chaise à porteurs, à l'aide d'un cul-de-jatte et d'un lapin !
(Pavillon noir !, Alain Ayroles/Jean-Luc Masboux, éd. Delcourt, coll. Terres de Légendes, 1997, p. 18)
Roger_Rabbit est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 03/02/2012, 09h24   #2
Expert Confirmé
 
Homme
Ingénieur développement logiciels
Inscription : juin 2007
Messages : 2 259
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France

Informations professionnelles :
Activité : Ingénieur développement logiciels

Informations forums :
Inscription : juin 2007
Messages : 2 259
Points : 2 578
Points : 2 578
Oui techniquement c'est possible,il faut que tu mettes ton mappedBy du coté de l'entité propriétaire de la jointure, Promotion par exemple:
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 
@Entity
@Table(name = "promotion")
public class Promotion {
    @Id
    @GeneratedValue
    private int     id;
 
    // ICI ce que je voudrais
 
    @OneToOne(mappedBy="parentLegalOperation")
    Operation parentLegalOperation;
 
    // + getters/ setters
    }
Ensuite dans Promotion :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Entity
@Table(name = "promotion")
public class Promotion {
    @Id
    @GeneratedValue
    private int     id;
 
    // ICI ce que je voudrais
 
    @OneToOne
    @JoinColumn(name = "promotion_legale_fk")
    Operation parentLegalOperation;
 
    // + getters/ setters
    }
Et ainsi de suite. Ceci dit je pense qu'il y'a un souci de conception, normalement il ne devrait y avoir qu'une seule relation entre Operation et Promotion, et dans la Promotion il devait y avoir une colonne permettant de dire quel type de promotion il s'agit. Suppose que demain on rajoute ou supprime une promotion, tu seras obligé de reconcevoir tout ton mapping.Mais le pb de conception ne se situe pas au niveau mapping ORM, mais plutot au niveau physique. Voila voila
DevServlet est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 03/02/2012, 10h00   #3
Expert Confirmé
 
Homme
Inscription : septembre 2006
Messages : 2 291
Détails du profil
Informations personnelles :
Sexe : Homme

Informations forums :
Inscription : septembre 2006
Messages : 2 291
Points : 2 738
Points : 2 738
La méthode la plus souple serait d'utiliser une Map :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 
@Entity
@Table(name = "operation")
public class Operation {
 
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int                id;
 
    @OneToMany(…,orphanRemoval=true)
    @ForeignKey(name="fk_oppromo",inverseName="fk_promo")
    @JoinTable([schema="SCHEMA_NAME",]name="OPPROMOS_JOIN_TABLE_NAME",
		joinColumns= @JoinColumn(name="REF_OPERATION_FIELDNAME"),
		inverseJoinColumns = @JoinColumn(name = "REF_PROMO_FIELDNAME"))
    private Map<PROMO_TYPE,Promotion> promotions ;}
mais cela implique que vous puissiez adapter le schéma.

PROMO_TYPE dans ce cas peut être une String, un Integer, un enum… (ou un UserType, mais sans doute trop lourd pour ce cas simple).
JeitEmgie est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 03/02/2012, 12h08   #4
Membre régulier
 
Homme Gaël
Ingénieur développement logiciels
Inscription : octobre 2008
Messages : 139
Détails du profil
Informations personnelles :
Nom : Homme Gaël
Localisation : France, Isère (Rhône Alpes)

Informations professionnelles :
Activité : Ingénieur développement logiciels
Secteur : High Tech - Opérateur de télécommunications

Informations forums :
Inscription : octobre 2008
Messages : 139
Points : 86
Points : 86
Merci de vos réponses.

par contre, DevServlet, je n'ai pas compris ce que tu m'expliquais : est-ce que je me trompe ou est-ce que tu as bien utilisé par erreur deux fois la classe promotion , en omettant l'entité propriétaire : "opération"?


Citation:
Envoyé par DevServlet Voir le message
Ceci dit je pense qu'il y'a un souci de conception, normalement il ne devrait y avoir qu'une seule relation entre Operation et Promotion, et dans la Promotion il devait y avoir une colonne permettant de dire quel type de promotion il s'agit. ...
Citation:
Envoyé par JeitEmgie Voir le message
La méthode la plus souple serait d'utiliser une Map
...
mais cela implique que vous puissiez adapter le schéma.
Je suis d'accord avec vous deux, mais lorsqu'on intervient comme pompier, on n'a pas toujours la possibilité de reconstruire le bâtiment. Il faut parfois faire au moins mal à défaut de faire au mieux.
__________________
Roger l'Âne: le lapin devenu grand....
_______________________________________________________________
Développeur bio-informatique; spécialiste en rien, généraliste en tout.

Capitan ! Capitan ! On a aperçu le Loup ! Il a pris d'assaut une chaise à porteurs, à l'aide d'un cul-de-jatte et d'un lapin !
(Pavillon noir !, Alain Ayroles/Jean-Luc Masboux, éd. Delcourt, coll. Terres de Légendes, 1997, p. 18)
Roger_Rabbit est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 06/02/2012, 09h55   #5
Expert Confirmé
 
Homme
Ingénieur développement logiciels
Inscription : juin 2007
Messages : 2 259
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France

Informations professionnelles :
Activité : Ingénieur développement logiciels

Informations forums :
Inscription : juin 2007
Messages : 2 259
Points : 2 578
Points : 2 578
Citation:
Envoyé par DevServlet Voir le message
Oui techniquement c'est possible,il faut que tu mettes ton mappedBy du coté de l'entité propriétaire de la jointure, Promotion par exemple:
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 
@Entity
@Table(name = "operation")
public class Operation{
    @Id
    @GeneratedValue
    private int     id;
 
    // ICI ce que je voudrais
 
    @OneToOne(mappedBy="parentLegalOperation")
    Promotion parentLegalPromotion;
 
    // + getters/ setters
    }
Ensuite dans Promotion:
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Entity
@Table(name = "promotion")
public class Promotion{
    @Id
    @GeneratedValue
    private int     id;
 
    // ICI ce que je voudrais
 
    @OneToOne
    @JoinColumn(name = "promotion_legale_fk")
    Operation parentLegalOperation;
 
    // + getters/ setters
    }
Et ainsi de suite. Ceci dit je pense qu'il y'a un souci de conception, normalement il ne devrait y avoir qu'une seule relation entre Operation et Promotion, et dans la Promotion il devait y avoir une colonne permettant de dire quel type de promotion il s'agit. Suppose que demain on rajoute ou supprime une promotion, tu seras obligé de reconcevoir tout ton mapping.Mais le pb de conception ne se situe pas au niveau mapping ORM, mais plutot au niveau physique. Voila voila
Autant pour moi. J'ai corrigé. Effectivement je te comprends, et c'est d'ailleurs j'ai bien ciblé le souci de conception en disant qu'il venait de la base.Sur laquelle tu n'aurais pas forcément une large manœuvre.Tiens nous au courant
DevServlet est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 17h24.


 
 
 
 
Partenaires

Hébergement Web