1

J'ai déjà posé cette question sur le Hibernate's forum, mais j'ai pensé que je le demanderais aussi ici.Mapper des objets de valeur complexe dans Hibernate

Je suis en train de cartographier le modèle suivant, tout en préservant la sémantique de la valeur des objets de valeur et TranslatedTextTranslation:

enter image description here

Les deux valeurs comme des objets dépendants

Idéalement je mapper TranslatedText en tant que <component> au sein de Question et Translation en tant que <bag> de <composite-element> au sein de TranslatedText.

Il aurait été simple à la carte si Question faisait référence à un seul TranslatedText, mais comme il fait référence à deux je besoin d'une sorte de discriminateur en fonction du nom de la propriété contenant la valeur (title ou description) afin de cartographier la Translation avec une clé de composition composée de (question_id,property_name,language_code). Un problème avec cela est que le propertyName ne fait pas partie du modèle et ne devrait pas, mais je n'ai pas trouvé un moyen de forcer Hibernate à insérer une valeur qui ne vient pas du modèle.

Par conséquent, j'ai essayé de changer le modèle et mettre en place des classes spécialisées Title et Description pour que j'aurais un type là-dedans que je pouvais utiliser comme un discriminateur.

enter image description here

A la fin qui ne permet pas vraiment beaucoup:

<component name="title" class="TranslatedText"> 

    <bag name="translations" table="Translation"> 
     <key> 
      <!-- PROBLEM: Could not find a way to create a custom join expression on question.id and question.title.type in here. --> 
     </key> 

     <composite-element class="Translation"> 
      <!-- PROBLEM: Could not found a way to make Hibernate insert title.type from here, without having this value on the Translation object. --> 
      <property name="languageCode" type="string" column="language_code"/> 
      <property name="text" type="string"/> 
     </composite-element> 
    </bag> 
    </component> 

TranslatedText avec <many-to-one>

j'ai réussi à obtenir quelque chose à ce que je besoin par cartographie TranslatedText comme une entité au sein Question en utilisant un <many-to-one> puis mappez Translation sous la forme d'une collection de valeurs au sein de TranslatedText, mais le problème principal m avec cette approche est qu'il n'y a pas de moyen facile de se débarrasser de l'orphelins TranslatedText et Translation. Je devrais soit faire ceci avec un déclencheur de DB ou un processus programmé.

Conclusion

À ce stade, je suis sous l'impression que Hibernate est pas assez souple pour cartographier le modèle initial avec la sémantique appropriée, mais nous espérons que je me trompe et il y a une façon de le faire.

Répondre

1

Je n'ai pas trouvé un moyen de les mapper en tant que valeurs. Cependant, la solution suivante fonctionne et cela pourrait vous être utile. J'ai enlevé TranslatedText et lié Question directement avec la collection de Translation.

@Entity 
public class Question { 
    @Id 
    private String id; 

    @JoinTable 
    @OrderColumn 
    @OneToMany(fetch = EAGER, cascade = ALL) 
    private List<Translation> titleTranslations; 

    @JoinTable 
    @OrderColumn 
    @OneToMany(fetch = EAGER, cascade = ALL) 
    private List<Translation> descriptionTranslations; 
} 

L'inconvénient est ici que Translation doit être Entity classe.

@Entity 
public class Translation { 
    @Id 
    private String id; 
    private String languageCode; 
    private String text; 
} 
+0

Eh bien, 'TranslatedText' est utile car elle assure qu'une seule traduction par le code, donc je ne peux pas me débarrasser, à moins que j'appliquer la règle avec une contrainte de DB, mais le modèle ne serait pas aussi expressif. Je pourrais utiliser 'Set 'à la place s'il était en Java, mais nous ne pouvons pas le faire puisque le modèle est en réalité écrit en ColdFusion (oui ce langage horrible), pas en Java. – plalx

+0

Il est difficile de comprendre vos contraintes sans contexte, mais il est possible d'avoir une telle relation en faisant les trois classes comme '@ Entity' (chacune d'elles aura son propre' @ Id'). Est-ce que ça va pour toi? Si oui, je peux préparer une telle configuration. –

+0

Eh bien, comme je l'ai dit, j'ai réussi à le faire déjà en mappant 'TranslatedText' en tant qu'entité. Cependant, je ne peux pas faire 'cascade-delete-orphan' dans ce cas puisque j'ai utilisé un' many-to-one'. Les objets de valeur sont simplement des valeurs immuables simples telles que 'Date' ou' Integer'. Les mapper en tant que composants d'hibernation permettrait de résoudre le problème des orphelins. Je suis vraiment surpris qu'un tel scénario commun soit si difficile à cartographier. – plalx