Issue
This is the first time that I have used Maps to do persistence with JPA. I also lose myself a bit at the conceptual level.
I have an object (poi) which has none, one or more description in different language. I want the poi object to have a map [lang, description]
@Entity
public class Poi {
@Id
@Column(name = "id")
private Long id;
@OneToMany(cascade = CascadeType.ALL)
@JoinTable(name = "description_poi_mapping",
joinColumns = {@JoinColumn(name = "poi_id", referencedColumnName = "id")},
inverseJoinColumns = {@JoinColumn(name = "description_id", referencedColumnName = "id")})
@MapKeyJoinColumn(name = "lang_id")
@MapKey
private Map<Lang, Description> descriptionCourte;
Description:
@Entity
public class Description {
@Id
@Column(name = "id")
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
private String label;
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "lang_id")
private Lang lang;
Lang:
@Entity
public class Lang {
@Id
@GeneratedValue(strategy= GenerationType.AUTO)
@Column(name = "id")
private Long id;
@Column(name = "label")
private String label;
So, a description contains a label which is attached to a language (fr, en, it, de, ...) I wish I could do, on the map;
> poi.getDescriptionCourte().get("en") or
> poi.getDescriptionCourte().get("fr")
Basically, that the key of the map is the language label (if it exists). If the "poi" has 1 description in English and 1 in French, then my map must have 2 record whose key value is "fr" or "en" (the label recorded for "lang")
Of course, the goal is to be able to reuse the lang class for other descriptions.
Excluding my current result is not at all what I want, here it is:
Could you help me please ?
thanking you.
Solution
That's not directly possible. You could implement equals
/hashCode
of Lang
such that only the label is used, then you can access elements like poi.getDescriptionCourte().get(new Lang("fr"))
or abstract this away in separate method poi.getDescriptionCourte("fr")
which does what I wrote before. Note though that this requires you to fetch all Lang objects i.e. have a managed representation of them in the current session/entityManager, so I would suggest you use Locale
instead which is mapped by Hibernate to a string column containing just the local code. You could also model the Lang
as @Embeddable
or provide an AttributeConverter
that converts between String
and Lang
. This way, no additional joins/fetches are necessary.
Answered By - Christian Beikov