问题描述
:正如一些评论者所指出的,该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;
}
}
这将创建以下数据库结构:
注释还允许您自定义连接表的@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;
最后,如果您想为多对多关联创建模式,则使用连接表是唯一可用的解决方案。
解决方法
在哪种情况下使用 JPA@JoinTable
注释?