어떤 경우에 JPA @JoinTable
주석 을 사용 합니까?
어떤 경우에 JPA @JoinTable
주석 을 사용 합니까?
답변:
편집 2017-04-29 : 일부 주석 작성자가 지적한 것처럼 JoinTable
예제에는 mappedBy
주석 속성이 필요하지 않습니다 . 사실, 최신 버전의 최대 절전 모드는 다음 오류를 인쇄하여 시작을 거부합니다.
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
주석 을 사용해야합니다 . 예를 들어, 단방향 일대 다 연관을 구현하기 위해 엔티티를 다음과 같이 정의 할 수 있습니다.
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
과 같이 속성에 주석을 달았습니다 .
@JoinTable(
name = "MY_JT",
joinColumns = @JoinColumn(
name = "PROJ_ID",
referencedColumnName = "PID"
),
inverseJoinColumns = @JoinColumn(
name = "TASK_ID",
referencedColumnName = "TID"
)
)
@OneToMany
private List<Task> tasks;
결과 데이터베이스는 다음과 같습니다.
마지막으로 다 대다 연관에 대한 스키마를 작성하려는 경우 결합 테이블을 사용하는 것이 유일하게 사용 가능한 솔루션입니다.
@JoinTable/@JoinColumn
와 같은 필드에 주석을 달 수 있다고 생각 합니다 mappedBy
. 올바른 예는 mappedBy
in을 유지하고 로 (또는 그 반대로) Project
이동해야 @JoinColumn
합니다.Task.project
Project_Tasks
요구 name
의 Task
세 개의 열이되는,뿐만 아니라 : project_id
, task_id
, task_name
, 어떻게 이것을 달성하기 위해?
Caused by: org.hibernate.AnnotationException: Associations marked as mappedBy must not define database mappings like @JoinTable or @JoinColumn:
ManyToMany 연관을 맵핑하는 유일한 솔루션입니다. 연관을 맵핑하려면 두 엔티티 테이블 사이에 결합 테이블이 필요합니다.
또한 많은면의 테이블에 외래 키를 추가하지 않기 위해 OneToMany (일반적으로 단방향) 연결에도 사용되므로 한쪽과 독립적으로 유지하십시오.
설명 및 예제 는 최대 절전 모드 설명서 에서 @JoinTable을 검색하십시오 .
다 대 다 관계를 처리 할 수 있습니다. 예:
Table 1: post
post has following columns
____________________
| ID | DATE |
|_________|_________|
| | |
|_________|_________|
Table 2: user
user has the following columns:
____________________
| ID |NAME |
|_________|_________|
| | |
|_________|_________|
조인 테이블을 사용하면 다음을 사용하여 매핑을 만들 수 있습니다.
@JoinTable(
name="USER_POST",
joinColumns=@JoinColumn(name="USER_ID", referencedColumnName="ID"),
inverseJoinColumns=@JoinColumn(name="POST_ID", referencedColumnName="ID"))
테이블을 생성합니다 :
____________________
| USER_ID| POST_ID |
|_________|_________|
| | |
|_________|_________|
@ManyToMany
협회대부분의 경우 다 @JoinTable
대다 테이블 관계의 맵핑을 지정 하려면 어노테이션 을 사용해야 합니다.
따라서 다음 데이터베이스 테이블이 있다고 가정하십시오.
에서 Post
엔티티,이 같은 관계를 매핑하는 것입니다 :
@ManyToMany(cascade = {
CascadeType.PERSIST,
CascadeType.MERGE
})
@JoinTable(
name = "post_tag",
joinColumns = @JoinColumn(name = "post_id"),
inverseJoinColumns = @JoinColumn(name = "tag_id")
)
private List<Tag> tags = new ArrayList<>();
@JoinTable
주석은을 통해 테이블 이름을 지정하는 데 사용되는 name
속성뿐만 아니라 외래 키 열이 참조합니다 post
테이블 (예 joinColumns
)과의 외래 키 열 post_tag
링크 테이블이 참조합니다 Tag
비아 개체 inverseJoinColumns
속성.
@ManyToMany
주석 의 계단식 속성 은로 설정되어PERSIST
있으며 , 우리의 경우에는 레코드가 아닌 다른 부모 레코드에 대해 DELETE 문이 발행MERGE
되므로 계단식REMOVE
은 잘못된 생각 이기 때문에 설정됩니다 . 이 주제에 대한 자세한 내용은 이 기사를 확인 하십시오 .tag
post_tag
@OneToMany
연관맵핑 @OneToMany
이없는 단방향 연관 @JoinColumn
은 일대 다가 아니라 다 대다 테이블 관계처럼 작동합니다.
따라서 다음 엔티티 맵핑이 있다고 가정하십시오.
@Entity(name = "Post")
@Table(name = "post")
public class Post {
@Id
@GeneratedValue
private Long id;
private String title;
@OneToMany(
cascade = CascadeType.ALL,
orphanRemoval = true
)
private List<PostComment> comments = new ArrayList<>();
//Constructors, getters and setters removed for brevity
}
@Entity(name = "PostComment")
@Table(name = "post_comment")
public class PostComment {
@Id
@GeneratedValue
private Long id;
private String review;
//Constructors, getters and setters removed for brevity
}
Hibernate는 위의 엔티티 매핑을 위해 다음과 같은 데이터베이스 스키마를 가정 할 것이다 :
이미 설명한 것처럼 단방향 @OneToMany
JPA 매핑은 다 대다 연결처럼 동작합니다.
링크 테이블을 사용자 정의하기 위해 @JoinTable
주석 을 사용할 수도 있습니다 .
@OneToMany(
cascade = CascadeType.ALL,
orphanRemoval = true
)
@JoinTable(
name = "post_comment_ref",
joinColumns = @JoinColumn(name = "post_id"),
inverseJoinColumns = @JoinColumn(name = "post_comment_id")
)
private List<PostComment> comments = new ArrayList<>();
그리고 지금, 링크 테이블 호출 할 것입니다 post_comment_ref
및 외래 키 열이 될 것입니다 post_id
를 들어, post
테이블 및 post_comment_id
를 들어, post_comment
테이블.
단방향
@OneToMany
연관은 효율적이지 않으므로 양방향@OneToMany
연관을 사용하거나@ManyToOne
측면 만 사용하는 것이 좋습니다 . 이 주제에 대한 자세한 내용은 이 기사 를 확인하십시오 .