1

The app's stack: Spring MVC, Spring DataJPA, Hibernate. There are three entities: student, tutor, theme.

Theme:

@Entity
@Table(name = "themes")
public class Theme {
    // fields omitted
}

Student:

@Entity
@Table(name = "students")
public class Student {

    private Map<Theme, Tutor> tutors;
    // other fields omitted
}

Tutor:

@Entity
@Table(name = "tutors")
public class Tutor {

    private Map<Theme, Student> students;
    // other fields omitted
}

For save student-tutor-theme relationships i want use this table (PostgreSQL):

CREATE TABLE themes_students_tutors
(
    theme_id   INTEGER NOT NULL,
    student_id INTEGER NOT NULL,
    tutor_id   INTEGER NOT NULL,
    FOREIGN KEY (theme_id) REFERENCES themes (id) ON DELETE CASCADE,
    FOREIGN KEY (student_id) REFERENCES students (id) ON DELETE CASCADE,
    FOREIGN KEY (tutor_id) REFERENCES tutors (id) ON DELETE CASCADE
)

How i can to annotate tutors and students fields in entities, for their content correct persists in this table?

3
  • 1
    @MapKeyColumn and @ManyToMany? Commented Feb 14, 2021 at 16:03
  • 1
    Try the @MapKeyJoinColumn. Commented Feb 14, 2021 at 17:03
  • @dan1st oh, maybe. but i not know, how i can use it. I understand the general principle, but I am interested in the specific application of these annotations in my case Commented Feb 14, 2021 at 17:06

1 Answer 1

2

Like @kolossus mentioned: Use the @MapKeyJoinColumn¹ annotation, so that the classes (or the map fields) look like this (you can ignore the extention of AbstractPersistable):

Student:

public class Student extends AbstractPersistable<Long> {

    @ManyToMany
    @JoinTable(name = "themes_students_tutors", joinColumns = {
            @JoinColumn(name = "student_id", referencedColumnName = "id") }, inverseJoinColumns = {
                    @JoinColumn(name = "tutor_id", referencedColumnName = "id") })
    @MapKeyJoinColumn(name = "theme_id")
    private Map<Theme, Tutor> tutors;

}

Tutor:

public class Tutor extends AbstractPersistable<Long> {

    @ManyToMany
    @JoinTable(name = "themes_students_tutors", joinColumns = {
            @JoinColumn(name = "tutor_id", referencedColumnName = "id") }, inverseJoinColumns = {
                    @JoinColumn(name = "student_id", referencedColumnName = "id") })
    @MapKeyJoinColumn(name = "theme_id")
    private Map<Theme, Student> students;

}

Given that, something like this would be created:

Hibernate: create table students (id bigint not null, primary key (id))
Hibernate: create table themes (id bigint not null, primary key (id))
Hibernate: create table themes_students_tutors (tutor_id bigint not null, student_id bigint not null, theme_id bigint not null, primary key (student_id, theme_id))
Hibernate: create table tutors (id bigint not null, primary key (id))
Hibernate: alter table themes_students_tutors add constraint FKm5l4is34t5gs14p4skkv3aup7 foreign key (student_id) references students
Hibernate: alter table themes_students_tutors add constraint FK8o0mm5ywi0l4hdxi4lgw4dbnu foreign key (theme_id) references themes
Hibernate: alter table themes_students_tutors add constraint FKa0n6jvie0kmk0pmikcuvtepxh foreign key (tutor_id) references tutors

¹: See the Javadoc documentation of @MapKeyJoinColumn for some other samples

Sign up to request clarification or add additional context in comments.

2 Comments

Didn't know this one, good to know. But anyway, I would map the join table as Entity as I find it easier later on when you have to code some queries for reports.
@DelfinoGomes If it stays a simple join table without additional information, I think it's just fine, not to map it to an entity. But if some information come into play (like additional columns such as "start/end date"), I also think it would be better (or the only possibility) to map the table to an entity. (Good point about queries: I don't know if/how it is possible to use Spring Data features such as query methods like findByXY, but I think this would be a separate question)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.