【问题标题】:How to annotate Map<Entity, Entity> with JPA?如何使用 JPA 注释 Map<Entity, Entity>?
【发布时间】:2021-05-17 16:34:41
【问题描述】:

应用程序堆栈:Spring MVCSpring DataJPAHibernate。共有三个实体:studenttutortheme

主题

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

学生

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

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

导师

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

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

为了保存student-tutor-theme 关系,我想使用这个表(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
)

我如何注释实体中的 tutorsstudents 字段,因为它们的内容正确保留在此表中?

【问题讨论】:

  • @MapKeyColumn@ManyToMany?
  • @dan1st 哦,也许吧。但我不知道,我该如何使用它。我了解一般原则,但我对这些注释在我的案例中的具体应用感兴趣

标签: java spring hibernate jpa spring-data-jpa


【解决方案1】:

就像@kolossus 提到的:使用@MapKeyJoinColumn¹注解,使类(或映射字段)看起来像这样(可以忽略AbstractPersistable 的扩展):

学生:

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;

}

导师:

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;

}

鉴于此,将创建如下内容:

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

¹:请参阅Javadoc documentation of @MapKeyJoinColumn 了解其他示例

【讨论】:

  • 不知道这个,很高兴知道。但无论如何,我会将连接表映射为实体,因为稍后当您必须为报告编写一些查询代码时会更容易。
  • @DelfinoGomes 如果它只是一个没有附加信息的简单连接表,我认为这很好,不要将它映射到实体。但是,如果某些信息起作用(例如“开始/结束日期”等附加列),我也认为将表映射到实体会更好(或唯一的可能性)。 (关于查询的要点:我不知道是否/如何使用 Spring Data 功能,例如 findByXY 等查询方法,但我认为这将是一个单独的问题)
猜你喜欢
  • 2012-09-05
  • 2015-05-13
  • 2017-12-18
  • 1970-01-01
  • 2013-05-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多