在哪种情况下您使用 JPA @JoinTable 注释?

问题描述

:正如一些评论者所指出的,该JoinTable示例不需要mappedBy注释属性。事实上,最新版本的 Hibernate 通过打印以下错误来拒绝启动:

org.hibernate.AnnotationException: 
   Associations marked as mappedBy must not define database mappings 
   like @JoinTable or @JoinColumn

假设您有一个实体命名Project和另一个实体命名Task,并且每个项目可以有许多任务。

您可以通过两种方式为此场景设计数据库模式。

一个解决方案是创建一个名为的表Project和另一个名为的表Task,并将一个外键列添加到名为的任务表中project_id

Project      Task
-------      ----
id           id
name         name
             project_id

这样,就可以确定任务表中每一行的项目。如果您使用这种方法,在您的实体类中,您将不需要连接表:

@Entity
public class Project {

   @OnetoMany(mappedBy = "project")
   private Collection<Task> tasks;

}

@Entity
public class Task {

   @ManyToOne
   private Project project;

}

另一种解决方案是使用第三个表,例如Project_Tasks,并将项目和任务之间的关系存储在该表中:

Project      Task      Project_Tasks
-------      ----      -------------
id           id        project_id
name         name      task_id

Project_Tasks表称为“联接表”。要在 JPA 中实现第二个解决方案,您需要使用@JoinTable注解。例如,为了实现单向的一对多关联,我们可以这样定义我们的实体:

@Entity
public class Project {

    @Id
    @GeneratedValue
    private Long pid;

    private String name;

    @JoinTable
    @OnetoMany
    private List<Task> tasks;

    public Long getPid() {
        return pid;
    }

    public void setPid(Long pid) {
        this.pid = pid;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<Task> getTasks() {
        return tasks;
    }

    public void setTasks(List<Task> tasks) {
        this.tasks = tasks;
    }
}

@Entity
public class Task {

    @Id
    @GeneratedValue
    private Long tid;

    private String name;

    public Long getTid() {
        return tid;
    }

    public void setTid(Long tid) {
        this.tid = tid;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

这将创建以下数据库结构:

ER图1

注释还允许您自定义连接表的@JoinTable各个方面。例如,我们是否tasks像这样注释属性

@JoinTable(
        name = "MY_JT",
        joinColumns = @JoinColumn(
                name = "PROJ_ID",
                referencedColumnName = "PID"
        ),
        inverseJoinColumns = @JoinColumn(
                name = "TASK_ID",
                referencedColumnName = "TID"
        )
)
@OnetoMany
private List<Task> tasks;

生成数据库将变为:

ER图2

最后,如果您想为多对多关联创建模式,则使用连接表是唯一可用的解决方案。

解决方法

在哪种情况下使用 JPA@JoinTable注释?