차이점은 무엇입니까?
@Entity
public class Company {
@OneToMany(cascade = CascadeType.ALL , fetch = FetchType.LAZY)
@JoinColumn(name = "companyIdRef", referencedColumnName = "companyId")
private List<Branch> branches;
...
}
과
@Entity
public class Company {
@OneToMany(cascade = CascadeType.ALL , fetch = FetchType.LAZY, mappedBy = "companyIdRef")
private List<Branch> branches;
...
}
답변
주석은 @JoinColumn
이 엔티티가 관계 의 소유자 임을 나타냅니다 (즉, 해당 테이블에 참조 된 테이블에 대한 외래 키가있는 열이 mappedBy
있음 ). 반면이 특성 의 엔티티는 관계의 반대임을 나타냅니다. 소유자는 “기타”엔티티에 상주합니다. 이것은 또한 “mappedBy”(완전한 양방향 관계)로 주석이 달린 클래스에서 다른 테이블에 액세스 할 수 있음을 의미합니다.
특히 문제의 코드에서 올바른 주석은 다음과 같습니다.
@Entity
public class Company {
@OneToMany(fetch = FetchType.LAZY, mappedBy = "company")
private List<Branch> branches;
}
@Entity
public class Branch {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "companyId")
private Company company;
}
답변
@JoinColumn
관계의 양쪽에 사용될 수 있습니다. 문제는 측면에서 사용 @JoinColumn
하는 것에 관한 것이 었습니다 @OneToMany
(드문 경우). 그리고 여기서 요점은 실제 정보 복제 (열 이름)와 일부 추가 UPDATE
명령문 을 생성하는 최적화되지 않은 SQL 쿼리입니다 .
설명서 에 따르면 :
이후 하나 많은된다 (거의) 항상 오너 측 JPA에 사양의 쌍방향 관계가 많은 관계로 하나에 의해 주석된다@OneToMany(mappedBy=...)
@Entity
public class Troop {
@OneToMany(mappedBy="troop")
public Set<Soldier> getSoldiers() {
...
}
@Entity
public class Soldier {
@ManyToOne
@JoinColumn(name="troop_fk")
public Troop getTroop() {
...
}
Troop
Soldier
병력 속성 을 통해 양방향 일대 다 관계가 있습니다. mappedBy
측면 에서 물리적 매핑을 정의 할 필요는 없습니다 .
으로, 많은에 양방향 하나를 매핑하려면 소유 측면으로 일대면 , 당신은 제거해야 할 mappedBy
요소를 하나에 많은 설정 @JoinColumn
으로 insertable
하고 updatable
false로. 이 솔루션은 최적화되지 않았으며 몇 가지 추가 UPDATE
설명 이 생성됩니다 .
@Entity
public class Troop {
@OneToMany
@JoinColumn(name="troop_fk") //we need to duplicate the physical information
public Set<Soldier> getSoldiers() {
...
}
@Entity
public class Soldier {
@ManyToOne
@JoinColumn(name="troop_fk", insertable=false, updatable=false)
public Troop getTroop() {
...
}
답변
이것은 매우 일반적인 질문 이므로이 답변을 기반으로하는이 기사를 작성
했습니다.
단방향 일대 다 연결
이 기사 에서 설명했듯이 @OneToMany
와 함께 주석 을 사용 하면 다음 다이어그램 @JoinColumn
의 상위 Post
엔터티와 하위 엔터티와 같은 단방향 연결이 있습니다 PostComment
.
단방향 일대 다 연관을 사용하는 경우 상위 측만 연관을 맵핑합니다.
이 예에서는 Post
엔터티 만 @OneToMany
하위 PostComment
엔터티에 대한 연결을 정의합니다 .
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "post_id")
private List<PostComment> comments = new ArrayList<>();
양방향 일대 다 연관
속성 세트 @OneToMany
와 함께 with 를 사용하면 mappedBy
양방향 연관이 있습니다. 이 경우 엔터티에는 다음 그림 과 같이 자식 엔터티 Post
모음이 PostComment
있고 자식 PostComment
엔터티에는 부모 엔터티에 대한 참조가 있습니다 Post
.
에서 PostComment
엔티티는 post
다음과 같이 개체 속성 매핑됩니다 :
@ManyToOne(fetch = FetchType.LAZY)
private Post post;
fetch
속성을 명시 적으로 설정 한 이유는FetchType.LAZY
기본적으로 모든 연결@ManyToOne
과@OneToOne
연결을 열심히 가져 와서 N + 1 쿼리 문제를 일으킬 수 있기 때문입니다. 이 주제에 대한 자세한 내용은 이 기사를 확인 하십시오 .
에서 Post
엔티티는 comments
다음과 같이 연관 매핑된다 :
@OneToMany(
mappedBy = "post",
cascade = CascadeType.ALL,
orphanRemoval = true
)
private List<PostComment> comments = new ArrayList<>();
mappedBy
의 속성 @OneToMany
주석을 참조합니다 post
자식 재산 PostComment
법인과이 방법은, Hibernate는 양방향 연관이에 의해 제어되는 것을 알고 @ManyToOne
이 테이블 관계에 기반으로하는 외래 키 컬럼 값을 관리하는 담당 측면.
양방향 연결을 위해서는 addChild
and와 같은 두 가지 유틸리티 방법이 필요합니다 removeChild
.
public void addComment(PostComment comment) {
comments.add(comment);
comment.setPost(this);
}
public void removeComment(PostComment comment) {
comments.remove(comment);
comment.setPost(null);
}
이 두 가지 방법은 양방향 연결의 양쪽이 동기화되지 않도록합니다. 양쪽 끝을 동기화하지 않으면 Hibernate는 연결 상태 변경이 데이터베이스로 전파 될 것이라고 보장하지 않습니다.
JPA 및 Hibernate와 양방향 연관을 동기화하는 최상의 방법에 대한 자세한 내용은 이 기사를 확인 하십시오 .
어느 것을 선택해야합니까?
단방향 @OneToMany
협회는 매우 잘 수행하지 않습니다 당신이 그것을 피해야한다, 그래서.
보다 효율적인 양방향 @OneToMany
을 사용하는 것이 좋습니다 .
답변
맵핑 된 주석은 이상적으로 항상 양방향 관계의 상위 측 (회사 클래스)에서 사용되어야하며,이 경우 하위 클래스의 멤버 변수 ‘회사'(브랜치 클래스)를 가리키는 회사 클래스에 있어야합니다.
@JoinColumn 어노테이션 은 엔티티 연관을 결합하기 위해 맵핑 된 열을 지정하는 데 사용 되며이 어노테이션은 모든 클래스 (Parent 또는 Child)에서 사용할 수 있지만 한쪽에서만 (부모 클래스 또는 Child 클래스가 아닌) 이상적으로 사용되어야합니다. 두 경우 모두)이 경우에는 Branch 클래스의 외래 키를 나타내는 양방향 관계의 자식 측 (지점 클래스)에서 사용했습니다.
아래는 작업 예입니다.
부모 클래스, 회사
@Entity
public class Company {
private int companyId;
private String companyName;
private List<Branch> branches;
@Id
@GeneratedValue
@Column(name="COMPANY_ID")
public int getCompanyId() {
return companyId;
}
public void setCompanyId(int companyId) {
this.companyId = companyId;
}
@Column(name="COMPANY_NAME")
public String getCompanyName() {
return companyName;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
@OneToMany(fetch=FetchType.LAZY,cascade=CascadeType.ALL,mappedBy="company")
public List<Branch> getBranches() {
return branches;
}
public void setBranches(List<Branch> branches) {
this.branches = branches;
}
}
어린이 교실, 지사
@Entity
public class Branch {
private int branchId;
private String branchName;
private Company company;
@Id
@GeneratedValue
@Column(name="BRANCH_ID")
public int getBranchId() {
return branchId;
}
public void setBranchId(int branchId) {
this.branchId = branchId;
}
@Column(name="BRANCH_NAME")
public String getBranchName() {
return branchName;
}
public void setBranchName(String branchName) {
this.branchName = branchName;
}
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="COMPANY_ID")
public Company getCompany() {
return company;
}
public void setCompany(Company company) {
this.company = company;
}
}
답변
이 답변이 제안하는 것처럼 @JoinColumn
항상 물리적 정보 위치 와 관련이있을 필요는 없다는 것을 추가하고 싶습니다 . 당신은 결합 할 수 있습니다 와 부모 테이블 자식 테이블을 가리키는에는 테이블 데이터가없는 경우에도 마찬가지입니다.@JoinColumn
@OneToMany
JPA에서 단방향 OneToMany 관계를 정의하는 방법
단방향 OneToMany, 반대 ManyToOne, 조인 테이블 없음
JPA 2.x+
그래도 사용할 수있는 것 같습니다 . 자식 클래스에 참조의 전체가 아닌 부모의 ID 만 포함시키려는 상황에 유용합니다.
답변
나는 Óscar López의 대답에 동의하지 않습니다. 그 대답은 정확하지 않습니다!
@JoinColumn
이 엔티티가 관계의 소유자임을 나타내는 것은 아닙니다 . 대신 @ManyToOne
(이 예제에서)이 작업을 수행 하는 주석입니다.
의 관계는 다음과 같은 주석을 @ManyToOne
, @OneToMany
그리고 @ManyToMany
할 JPA / 최대 절전 모드를 말할 매핑을 만듭니다. 기본적으로이 작업은 별도의 조인 테이블을 통해 수행됩니다.
@JoinColumn
조인 열 이 아직없는 경우
@JoinColumn
이를 만드는 것이 목적입니다 . 그렇다면이 주석을 사용 하여 조인 열의 이름을 지정할 수 있습니다
.
매핑
MappedBy
매개 변수 의 목적은 JPA에 지시 하는 것입니다 . 관계가이 관계 의 반대 엔티티에 의해 이미 맵핑되고 있으므로 다른 결합 테이블을 작성하지 마십시오 .
기억하십시오 : MappedBy
기본적으로 조인 테이블을 작성하여 수행하는 두 엔티티를 연관시키는 메커니즘을 생성하는 것이 목적인 관계 주석의 특성입니다. MappedBy
해당 프로세스를 한 방향으로 중지합니다.
외래 키 필드에 대한 세 가지 매핑 주석 중 하나를 사용하여 매핑의 메커니즘이 클래스 내에서 지시되기 때문에 사용하지 않는 엔터티 는 관계 MappedBy
의 소유자 라고 합니다. 이는 맵핑의 특성을 지정할뿐만 아니라 결합 테이블 작성을 지시합니다. 또한 조인 테이블을 억제하는 옵션은 외래 키에 @JoinColumn 주석을 적용하여 소유자 엔터티의 테이블 내에 대신 유지함으로써도 존재합니다.
요약하면 : @JoinColumn
새 조인 열을 만들거나 기존 열의 이름을 바꿉니다. 이 MappedBy
매개 변수는 조인 테이블을 통해 또는 소유자 엔티티의 연관된 테이블에 외래 키 열을 작성하여 맵핑을 작성하기 위해 다른 (하위) 클래스의 관계 주석과 협력하여 작동합니다.
MapppedBy
작동 방식 을 설명하려면 아래 코드를 고려하십시오. 경우 MappedBy
매개 변수를 삭제했다, 다음 최대 절전 모드가 실제로 만들 것 두 테이블을 조인! 왜? 다 대다 관계에는 대칭이 있기 때문에 Hibernate는 한 방향을 다른 방향으로 선택하는 데 대한 근거가 없습니다.
그러므로 MappedBy
우리는 Hibernate에게 말하기 위해 사용 한다. 우리는 다른 엔티티를 선택 하여 두 엔티티 사이의 관계의 맵핑을 지시했다.
@Entity
public class Driver {
@ManyToMany(mappedBy = "drivers")
private List<Cars> cars;
}
@Entity
public class Cars {
@ManyToMany
private List<Drivers> drivers;
}
소유자 클래스에 @JoinColumn (name = “driverID”)을 추가하면 (아래 참조) 조인 테이블을 만들지 않고 대신 Cars 테이블에 driverID 외래 키 열을 만들어 매핑을 구성합니다.
@Entity
public class Driver {
@ManyToMany(mappedBy = "drivers")
private List<Cars> cars;
}
@Entity
public class Cars {
@ManyToMany
@JoinColumn(name = "driverID")
private List<Drivers> drivers;
}
답변
JPA는 계층화 된 API이며 다른 수준에는 자체 주석이 있습니다. 최상위 레벨은 (1) 지속성 클래스를 설명하는 엔티티 레벨이며, 엔티티가 관계형 데이터베이스 및 (3) Java 모델로 맵핑되는 것으로 가정하는 (2) 관계형 데이터베이스 레벨이 있습니다.
레벨 1 주석 : @Entity
, @Id
, @OneToOne
, @OneToMany
, @ManyToOne
, @ManyToMany
. 이러한 고급 주석 만 사용하여 애플리케이션에 지속성을 도입 할 수 있습니다. 그러나 JPA의 가정에 따라 데이터베이스를 작성해야합니다. 이러한 주석은 엔티티 / 관계 모델을 지정합니다.
레벨 2 주석 : @Table
, @Column
, @JoinColumn
, … 관계형 데이터베이스 테이블에 엔티티 / 속성의 매핑에 영향을 / 당신은 JPA의 기본값에 만족하지 않거나 기존 데이터베이스에 매핑해야하는 경우 경우 열. 이러한 주석은 구현 주석으로 볼 수 있으며 매핑 수행 방법을 지정합니다.
제 생각에는 가능한 한 높은 수준의 주석에 충실한 다음 필요에 따라 낮은 수준의 주석을 도입하는 것이 가장 좋습니다.
질문에 대답하려면 : @OneToMany
/ mappedBy
는 엔티티 도메인의 주석 만 사용하므로 가장 좋습니다. @oneToMany
/는 @JoinColumn
또한 미세하지만 이것이 꼭 필요한 것은 구현 주석을 사용합니다.