4

I have a database with an object, which has translations.

There are 2 tables: table Object which has id and more properties and table 'object_translation' which has object_id, language (varchar) and translation (varchar)

I would like to map this to

public class Object {
    private Map<Language, String> translations
}

Where language is an enum in code and a string in the DB.

Is this possible with annotations? or do I need to create either Collection<QuestionTranslation> or write my own hibernate mapping functions in the DAO (I'm using spring-data, so I would prefer to keep it nice and clean as interfaces and annotations)

Versions: spring-boot 2 with provided hibernate from spring-boot-starter:

spring boot: <version>2.0.3.RELEASE</version>
<hibernate.version>5.2.17.Final</hibernate.version>
<hibernate-jpa-2.1-api.version>1.0.2.Final</hibernate-jpa-2.1-api.version>

So far I have this:

@OneToMany
@JoinTable(name = "object_translation", joinColumns = {@JoinColumn(name = "object_id", referencedColumnName = "id")})
@MapKey(name = "language")
@MapKeyEnumerated(EnumType.STRING)
private Map<Language, String> translations;

But how do I map the value as well? (for clarification: the String value should be the translation column in the DB)

Because I don't have a primary-key, this should theoretically be possible?

Thanks in advance!

user3392782
  • 181
  • 4
Thomas Stubbe
  • 1,945
  • 5
  • 26
  • 40

2 Answers2

2

I managed to fix it =)

You shouldn't use @OneToMany.

What I used:

public class Object {

    @ElementCollection(fetch = FetchType.EAGER)
    @CollectionTable(name = "object_translation",
                 foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_object_translation_object"),
                 joinColumns = @JoinColumn(name = "object_id"))
    @MapKeyColumn(name = "language", nullable = false)
    @MapKeyEnumerated(EnumType.STRING)
    @Column(name = "translation", nullable = false)
    private Map<Language, String> translations;
}
Thomas Stubbe
  • 1,945
  • 5
  • 26
  • 40
0

It is not achievable from ORM perspective. There is no way to tell ORM framework to map String to Translation column.

The best way to achieve this would be by retrieving the rows from Object_Translation as a List or Set using @OneToMany or @ManyToMany with mappedBy and then writing your custom to convert them to a map.

user3392782
  • 181
  • 4
  • so your answer is basically: It's not possible with annotations, you need to write your own DAO with a mapping from and to the entity? – Thomas Stubbe Nov 27 '18 at 13:23
  • If you are planning to write the custom code in DAO , then yes. I personally prefer writing such code in my entity itself. – user3392782 Nov 27 '18 at 13:26
  • Wouldn't `@CollectionTable` with `@Column` work? I'll try it out – Thomas Stubbe Nov 27 '18 at 13:29
  • @CollectionTable is to retrieve a list of values instead of objects based on a JoinColumn. For e.g. if you would like to retrieve all the values of translation for a particular object_id without getting the "language", then you can use it. But not for what you have described you wish to achieve. – user3392782 Nov 27 '18 at 13:45
  • Works like a charm =) – Thomas Stubbe Nov 27 '18 at 13:57