Hiberner :Le mappage OneToMany n'est pas basé sur PK ?
-
26-09-2020 - |
Question
J'ai 2 entités/tables.
L'un est une entité propre, appelons-la data
.Il comporte un certain nombre de champs contenant ce que l'on appelle des « codes multilingues ».
Le deuxième tableau, code
, contient les valeurs multilingues elles-mêmes.
Voici quelques exemples de données :
Data table
id name continentCode countryCode
------------------------------------
1 Toto EU CH
2 Titi AS CN
Code table
id code language text
----------------------------
1 EU EN Europe
2 EU FR Europe
3 EU DE Europa
4 CH EN Switzerland
5 CH FR Suisse
6 CH DE Schweiz
... etc
Je voudrais cartographier les propriétés continents, pays, etc. dans l'entité Data sous forme de carte, comme ça :
@OneToMany()
@MapKey(name="languageCode")
private Map<String, Code> continents;
Pour que je puisse ensuite lire le texte dans la bonne langue comme ça :
Data toto = dao.findByName("Toto");
String text = toto.getContries.get("FR").getText(); //--> returns "Suisse"
String text = toto.getContries.get("EN").getText(); //--> returns "Switzerland"
Je dois également pouvoir effectuer une recherche textuelle sur les valeurs de ces "codes", en utilisant la langue de l'utilisateur.(par exemple.obtenir toutes les données où le country='suisse', en français !)
Alors, est-il possible de cartographier un OneToMany
collection utilisant un champ clé qui n'est pas la clé primaire de l'entité actuelle ?J'ai besoin de ma collection de continents "tous les enregistrements de la table Code où le code = la valeur de mon continentCode
propriété".Ou peut-être existe-t-il une manière plus appropriée de représenter ce type de relation ?
Attention :Malheureusement, je ne peux pas modifier le schéma SQL...
La solution
OK, j'ai trouvé la solution.Le mappage OneToMany sur mon entité Data ressemble à ça :
@OneToMany()
@JoinColumn(name="code", referencedColumnName="continentCode", insertable=false, updatable=false)
@MapKey(name="languageCode")
private Map<String, AAGeoContinentThesaurusEntry> continents;
J'ai également dû mapper la colonne continentCode pour que cela fonctionne.Je ne l'ai pas fait, j'ai eu un :
org.hibernate.MappingException: Unable to find column with logical name: GCH_CDE_CODE_CNT in org.hibernate.mapping.Table
(GCHDATA) and its related supertables and secondary tables
at org.hibernate.cfg.Ejb3JoinColumn.checkReferencedColumnsType(Ejb3JoinColumn.java:396)
at org.hibernate.cfg.BinderHelper.createSyntheticPropertyReference(BinderHelper.java:102)
Maintenant je peux faire :
myData.getContinentCodes().get("FR").getText()
et recevez la chaîne "Europe" :)