1

Having the database below (simplified):

Translation( id, language, text)
StoryChapter (id, chapterTitle)

The Translation primary key is (id, language)

Here's what I got so far in Java:

@Entity
@IdClass(TranslationId.class)
public class Translation {

    @Id
    private long id;

    @Id
    private String language;

    @Lob
    private String text;
    
}

public class TranslationId implements Serializable {

    private long id;
    private String language;

}


@Entity
public class StoryChapter {

    @Id
    private int id;

    @ManyToMany
    @JoinColumn(
            name = "chapter_title",
            referencedColumnName = "id"
    )
    private List<Translation> chapterTitle;

}

My only concern with this code is that it requires a new table to join StoryChapter and Translation, and I'd like to avoid this behavior (but go along with it if it's really impossible).

Using OneToMany is also a no-go because it requires additional columns within Translation table, and this table will be used by many other entities later on.

So, with data example, if a have in my Translation table:

id language text
1 EN This is a chapter title !
1 FR C'est un titre de chapitre !
2 EN And another one !
2 FR Et un autre !

I'd like my StoryChapter to be like:

id (PK) chapterTitle
1 1
2 2

And in Java, my chapterTitle list should have the two entries (the two languages available).

Is this behavior even possible with JPA ?

Solution

Thanks to Martin'sRun who gave me valuable informations to solve my problem.

For each Set added, a corresponding field need to be created, which will hold the raw value:

    private long chapterTitle;

    @OneToMany
    @JoinColumn(name = "id", referencedColumnName = "chapterTitle")
    private Set<Translation> chapterTitles;

At that point, the tables in database looked like I wanted. But upon using findAll(), this error was thrown:

StoryChapter cannot be cast to class java.io.Serializable

I just added implements Serializable to my class.

Then, another error poped-up:

failed to lazily initialize a collection of role: StoryChapter.chapterTitles, could not initialize proxy - no Session

So I just added fetch = FetchType.EAGER on the @OneToMany annotation.

Now everything works as expected.

alexpado
  • 13
  • 3
  • Does the Id column on StoryChapter represent a foreign-key relation to id on translation table in the example? How is the relation between the tables established? – Martin'sRun Apr 18 '21 at 20:40
  • @Martin'sRun Sorry, I made a mistake in the example by putting 2 times "1" as ID. The column id on StoryChapter is the ID of that table, I'd like to "simulate" a FK from chapterTitle to the translation id (list of translation) – alexpado Apr 18 '21 at 21:38

1 Answers1

1

The Translation table looks to be a generic text translations, which could be referenced from multiple entities. This relation between StoryChapter and Translation is uni-directional and one-to-many, is supported on JPA.

Story chapter can reference a collection of Translations with:

    @OneToMany
    @JoinColumn(name = "id", referencedColumnName = "chapterTitle")
    private Set<Translation> chapterTitle;

Other entities which use the translation table can do the same as well.

Check this SO post for more details and documentation How to define unidirectional OneToMany relationship in JPA

Martin'sRun
  • 522
  • 3
  • 11
  • Thanks for this answer ! I updated my post to reflect all edits I needed to do for this solution to work ! – alexpado Apr 18 '21 at 23:59