我是一名JPA新手,并且尝试了解双向OneToMany关系b / w项目和任务实体的@JoinTable批注,其中Project可以具有多个任务。

我可以将@JoinTable与具有@ManyToOne批注的实体一起使用,但是当我将@JoinColumn放置在具有@OneToMany的另一个实体上时,我没有获得在@ManyToOne批注中指定“ mappedBy”属性的选项。

我想知道为什么 ?

我尝试在两个实体上放置@JoinTable批注,但是Hibernate试图在Join表中插入两个记录

项目实体:

@Entity
@Data
public class Project {
    @Id
    @Column(name = "project_pk")
    @GeneratedValue
    private Long id;

    @Column(name = "project_name")
    private String name;

    @OneToMany(mappedBy = "project", cascade = CascadeType.ALL)
    List<Task> tasks;
}
任务实体:

@Entity
@Data
public class Task {

    @Id
    @GeneratedValue
    @Column(name = "task_pk")
    private Long id;

    public Task() {
    }

    private String name;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinTable(name = "project_related_tasks",
            inverseJoinColumns = @JoinColumn(name = "project_id", referencedColumnName = "project_pk"),
            joinColumns = @JoinColumn(name = "task_id", referencedColumnName = "task_pk")
    )
    private Project project;

    public Task(String name) {
        this.name = name;
    }
}
来自布格的解答

mapledBy的实际含义是:表示休眠哪些实体将负责那些相关的实体。它放置在不想对那些实体负责的类上。因此,放置它的地方是声明让另一个类负责。Hibernate仅在对主要实体的那些相关实体负责的情况下,才会检测并保留对这些实体的更改。如果不负责,休眠将忽略那些相关的实体,并且它们不会在数据库级别被修改。

因此,您仅需决定一个将具有mapedBy的类要么是

public class Project {
 @OneToMany(mappedBy = "project", cascade = CascadeType.ALL)
    List<Task> tasks;
  }
或者

public class Task {

@ManyToOne(cascade = CascadeType.ALL, mappedBy = "tasks")
    @JoinTable(name = "project_related_tasks",
            inverseJoinColumns = @JoinColumn(name = "project_id", referencedColumnName = "project_pk"),
            joinColumns = @JoinColumn(name = "task_id", referencedColumnName = "task_pk")
    )
    private Project project;
}

如果您决定让mapBy作为“任务类”使用,则意味着如果您坚持一个项目并且该项目包含修改或新的“任务”作为子实体,那么(由于cascade.All)这些子任务实体也将在数据库级别进行存放。之所以会发生这种情况,是因为Project类还将负责这些子Task实体。

如果您再次保存项目实体,但是Task类没有带来mapedBy(这意味着Project具有mapedBy,因此该项目不负责Task实体),那么该项目将保留在数据库级别,但是所有修改或在项目保存期间,它包含在任务字段中的新任务将不会转移到数据库级别