在哪种情况下使用 JPA@JoinTable注释?
@JoinTable
编辑 2017-04-29 :正如一些评论者所指出的,该JoinTable示例不需要mappedBy注释属性。事实上,最新版本的 Hibernate 通过打印以下错误来拒绝启动:
JoinTable
mappedBy
org.hibernate.AnnotationException: Associations marked as mappedBy must not define database mappings like @JoinTable or @JoinColumn
假设您有一个实体命名Project和另一个实体命名Task,并且每个项目可以有许多任务。
Project
Task
您可以通过两种方式为此场景设计数据库模式。
第一个解决方案是创建一个名为的表Project和另一个名为的表Task,并将一个外键列添加到名为的任务表中project_id:
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_Tasks
Project Task Project_Tasks ------- ---- ------------- id id project_id name name task_id
该Project_Tasks表称为“联接表”。要在 JPA 中实现第二个解决方案,您需要使用@JoinTable注解。例如,为了实现单向的一对多关联,我们可以这样定义我们的实体:
Project 实体:
@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; } }
Task 实体:
@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; } }
这将创建以下数据库结构:
注释还允许您自定义连接表的@JoinTable各个方面。例如,我们是否tasks像这样注释属性:
tasks
@JoinTable( name = "MY_JT", joinColumns = @JoinColumn( name = "PROJ_ID", referencedColumnName = "PID" ), inverseJoinColumns = @JoinColumn( name = "TASK_ID", referencedColumnName = "TID" ) ) @OneToMany private List<Task> tasks;
生成的数据库将变为:
最后,如果您想为多对多关联创建模式,则使用连接表是唯一可用的解决方案。