2010-08-14 4 views
0

Je suis assez perdu avec le mappage de la structure suivante avec les annotations JPA.Perdu avec JPA @OneToMany et composite PK

+===========+    +====================+ 
| Offer  |    | Text    | 
+-----------+ 1  0..* +--------------------+ 
| id (pk) |-------------| textkey (pk)  | 
| namekey |    | languagecode (pk) | 
| ...  |    | text    | 
+===========+    | ...    | 
          +====================+ 

Ainsi, chaque offre a un nom qui est i18n-aware. Comme j'ai les mêmes cas encore et encore dans l'application (offre a aussi un commentaire i18n, article a un nom i18n, etc.) Je veux avoir une entité de texte avec une clé primaire composite. Pour chaque clé, il existe autant d'enregistrements que de langues prises en charge. échantillons de texte:

+=====================================+ 
| textkey | languagecode | text | 
+=====================================+ 
| offer5Name | en   | foo  | 
| offer5Name | fr   | bar  | 
| offer6Name | en   | hello | 
... 

L'entité offre stockerait texte # textkey dans sa colonne namekey.

Du côté de Java j'aimerais offrir à un ensemble de noms ou même mieux une carte de noms ainsi je pourrais avoir une méthode comme Text getName(String language) au lieu de Set<Text> getNames().

Ce que j'ai déjà est Texte et son TextPK clé primaire composite:

@Entity 
public class Text { 

    @EmbeddedId 
    private TextPK primaryKey; 

    @Column(name = "text") 
    private String text; 

PK

@Embeddable 
public class TextPK implements Serializable { 

    @Column(name = "textkey") 
    private Long key; 

    @Column(name = "languagecode") 
    @Enumerated(EnumType.STRING) 
    private LanguageCode languageCode; 

Question: comment puis-je annote la variable membre 'noms' dans la classe d'offre pour obtenir Ce dont j'ai besoin?

Répondre

2

Ok, encore une fois je réponds à ma question ...

JPA 1.0 ne supporte pas OneToMany unidirectionnel (http://en.wikibooks.org/wiki/Java_Persistence/OneToMany#Example_of_a_JPA_2.0_unidirectional_OneToMany_relationship_database) et qui est un peu ce que j'aurais fini avec.

Ce qui a fonctionné le mieux pour mon cas était de créer une entité intermédiaire TextCollection. Chaque entité de domaine (telle que Offer) a une relation OneToOne avec un TextCollection pour chacun de ses attributs de texte (nom, description, etc.). L'entité de collecte elle-même n'a rien d'autre qu'une id et une relation OneToMany bidirectionnelle à Text.

@Entity 
@Table(name = "textcollection") 
public class TextCollection { 

    @Id 
    @Column(name = "textkey") 
    private String key; 

    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "textCollection") 
    private final Set<Text> texts = new HashSet<Text>(); 


@Entity 
@Table(name = "text") 
public class Text { 

    @EmbeddedId 
    private TextPK primaryKey; 

    @Column(name = "text", nullable = false) 
    private String text; 

    @ManyToOne 
    @JoinColumn(name = "textkey", insertable = false, updatable = false) 
    private TextCollection textCollection; 

@Entity 
@Table(name = "offer") 
public class Offer { 

    @OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL) 
    @JoinColumn(name = "namekey", nullable = false, insertable = true) 
    private TextCollection name; 
Questions connexes