2010-09-17 16 views
0

J'ai une table Catégorie et une table TranslatableText. La catégorie est comme çaHibernate: joindre à l'une des touches d'une table à plusieurs touches

create table Category (
    id int not null, 
    parent_id int default 0, 
    TranslatableDescriptionId int default 1, 
    primary key(id)); 

create table TranslatableText (
    id int not null, 
    lang enum ('NO','EN','FR'), 
    text mediumtext, 
    primary key(id, lang)); 

Dans mon entité Catégorie j'ai défini une cartographie:

@Fetch(FetchMode.SUBSELECT) 
@Cache(usage=CacheConcurrencyStrategy.READ_ONLY) 
@OneToMany(fetch=FetchType.LAZY) 
@JoinColumn(name="TranslatableDescriptionId") 
@ForeignKey(name="FK_TranslatableTextId") 
private Set<TranslatableText> translatableText; 

Mais quand il exécute, il tente d'accéder TranslatableDescriptionId, pas id. Même si l'entité TranslatableText a défini

@Id 
@Column(name = "id", nullable = false) 
private Integer id; 

@Id 
@Column(name = "lang", nullable = false) 
@Enumerated(EnumType.STRING) 
private String lang; 

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

La requête avec le nom incorrect sélectionné:

sélectionnez translatab0_.TranslatableDescriptionId comme Translat4_13_1_, translatab0_.id comme id1_, translatab0_.lang comme Lang1_, translatab0_.id comme id22_0_ , translatab0_.lang comme Lang22_0_, translatab0_.text comme Text22_0_ de tblTranslateableText translatab0_ où translatab0_.TranslatableDescriptionId dans ('126', '119', '103', '116', '121', '107', '113', ' 101 ',' 109 ',' 105 ',' 123 ',' 106 ',' 125 ',' 124 ',' 114 ')

Si je change les mappages @JoinColumn à re ad

@JoinColumn(name="TranslatableDescriptionId", referencedColumnName="id") 

je reçois l'erreur suivante lors du chargement de mon application:

org.hibernate.MappingException: Impossible de trouver la colonne avec le nom logique: id dans org.hibernate.mapping.Table (Catégorie) et son supertables connexes et tables secondaires

Pour une bonne mesure j'ai aussi essayé:

@JoinColumn(name="id", referencedColumnName="TranslatableDescriptionId") 

Cela m'a donné l'erreur:

org.hibernate.MappingException: Impossible de trouver la colonne avec le nom logique: TranslatableDescriptionId dans org.hibernate.mapping.Table (Catégorie) et ses supertables connexes et tables secondaires

Toute suggestion à ce que je dois faire? Je veux vraiment translateableText de catégorie pour contenir toutes les traductions pour sa description, donc je veux vraiment rejoindre Category.TranslatableDescriptionId == TranslatableText.id

Update1: TranslatableText est utilisé par de nombreuses entités, afin de mettre en categoryId dans et inverser la relation n'est pas une option.

MAJ2: j'ai pu le charger en disant @JoinColumn(name="id"), mais cela conduit à une ClassCastException dans Hibernate où, au lieu d'avoir un nombre entier comme une clé, a un tableau contenant un seul entier comme une clé. Cela ne peut pas être transformé en chaîne et donc en SQL correct.Il est donc sans doute pas encore la cartographie Je veux

Vive

Nik

Répondre

2

Ce type de cartographie est possible, mais pas très pratique car vous aurez à gérer l'identité de TranslatableText s manuellement (c'est pourquoi Hibernate se plaint de la colonne non cartographié TranslatableDescriptionId):

public class Category implements Serializable { 
    ... 
    private Long translatableDescriptionId; 

    @OneToMany 
    @JoinColumn(name="id", referencedColumnName="TranslatableDescriptionId") 
    private Set<TranslatableText> translatableText; 
    ... 
} 

donc, vous devez attribuer manuellement translatableDescriptionId uniques s à tous les « cibles » de TranslatableText (catégories , éléments, dossiers comme vous le dites) et définir manuellement ces valeurs comme id de TranslatableText avant de le persister (vous ne pouvez pas simplement ajouter TranslatableText dans le Set).

-

Cependant, la conception plus pratique est d'introduire une entité intermédiaire pour maintenir l'identité de tous transalations attatched à une cible spécifique:

public class Category { 
    ... 
    @OneToOne(cascade = CascadeType.ALL) 
    @JoinColumn(name = "targetId") 
    private TranslationTarget target; 
} 

public class TranslationTarget { 
    @Id @GeneratedValue 
    private Long id; 

    @OneToMany 
    @JoinColumn(name = "targetId") 
    private Set<TranslatableText> texts; 
} 

-

create table Category (    
    targetId int, 
    ...);   

create table TranslationTargets (
    id int primary key 
);  

create table TranslatableText (    
    targetId int not null,    
    lang enum ('NO','EN','FR'),    
    text mediumtext,    
    primary key(targetId, lang)); 
+0

Merci Pour la suggestion, je vais essayer ce design tout de suite et rendre compte :-) Je suis un peu confus, cependant, puisque la façon dont je l'ai lu, je pousse simplement le problème d'un pas en face de moi? – niklassaers

+0

'name = "targetId"' dans Catégorie points à Category.targetId, non? Ou devrait-il être 'name = "id"' parce qu'il pointe vers TranslationTargets.id, tout comme 'name = "targetId' 'de TranslationTarget pointe vers TranslatableText.targetId? – niklassaers

+0

En faisant cela, je reçois l'exception suivante. Y a-t-il quelque chose dans les cartographies que j'ai manqué? com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Colonne inconnue 'texts0_.targetId' dans 'liste des champs' – niklassaers