단방향 및 양방향 JPA와 최대 절전 모드 연결의 차이점은 무엇입니까?


135

단방향 및 양방향 연관의 차이점은 무엇입니까?

db에서 생성 된 테이블이 모두 같기 때문에 내가 찾은 유일한 차이점은 입찰 관계의 각면이 다른 쪽을 참조하고 단방향은 참조하지 않는다는 것입니다.

이것은 단방향 연결입니다

public class User {
    private int     id;
    private String  name;
    @ManyToOne
    @JoinColumn(
            name = "groupId")
    private Group   group;
}

public class Group {
    private int     id;
    private String  name;
}

양방향 연관

public class User {
    private int     id;
    private String  name;
    @ManyToOne
    @JoinColumn(
            name = "groupId")
    private Group   group;
}
public class Group {
    private int         id;
    private String      name;
    @OneToMany(mappedBy="group")
    private List<User>  users;
}

차이점은 그룹이 사용자에 대한 참조를 보유하는지 여부입니다.

이것이 유일한 차이점인지 궁금합니다. 어느 것이 권장됩니까?


7
이제 그룹에 포함 된 사용자를 알 수 있습니다. 나는 이것이 작은 차이라고 생각하지 않습니다.
Satadru Biswas 8:19에

5
양방향 관계는 업데이트와 관련하여 혼란스러워졌습니다. :)
diyoda_

답변:


152

주된 차이점은 양방향 관계가 양방향으로 탐색 액세스를 제공하므로 명시적인 쿼리없이 다른쪽에 액세스 할 수 있다는 것입니다. 또한 계단식 옵션을 양방향에 적용 할 수 있습니다.

특히 "일대 다"및 "다 대다"관계의 경우 탐색 액세스가 항상 좋은 것은 아닙니다. Group수천 개의을 포함 하는 a 를 상상해보십시오 User.

  • 그들에게 어떻게 접근하겠습니까? 너무 많은 Users를 사용하면 일반적으로 필터링 및 페이지 매김을 적용해야하므로 쿼리를 실행해야합니다 ( 컬렉션 필터링 을 사용하지 않는 한 나에게 해킹처럼 보입니다). 이러한 경우 일부 개발자는 메모리에 필터링을 적용하는 경향이 있으며 이는 성능에 좋지 않습니다. 이러한 관계가 있으면 이러한 종류의 개발자가 성능에 영향을주지 않고 관계를 사용할 수 있습니다.

  • 당신은 어떻게 새로운 추가 할 User받는 사람들 Group? 다행스럽게도, Hibernate는 그것을 유지할 때 관계의 소유 측면을 보므로, 당신은 만 설정할 수 있습니다 User.group. 그러나 객체를 메모리에 일관성있게 유지하려면에 추가 User해야 Group.users합니다. 그러나 Hibernate Group.users는 데이터베이스에서 모든 요소를 ​​가져옵니다 !

따라서 모범 사례 의 권장 사항에 동의하지 않습니다 . 사용 사례 (양방향 탐색 액세스가 필요합니까?) 및 가능한 성능 영향을 고려하여 양방향 관계를 신중하게 설계해야합니다.

또한보십시오:


안녕, 감사합니다, 당신은 내 질문에 답변했기 때문에 당신이 최대 절전 모드의 전문가 인 것 같습니다 : stackoverflow.com/questions/5350770/… . 그리고 지금 나는 관계가 확실하지 않다, 나는 코멘트에 더 많은 것을 쓸 수 없기 때문에, 여기에 dpaste.de/J85m을 게시한다 . 가능하다면 체크를 해주시기 바랍니다. :)
hguser

@ hguser : 마침내 당신이 양방향 관계를 맺기로 결정했다면, 양쪽을 일관되게 유지하기 위해 전화 setGroup()하는 것이 더 좋을 것이라고 생각합니다 addUser().
axtavt

group.addUser () 내에서 setGroup ()을 호출하지 않으면 어떻게됩니까?
hguser

@ hguser : 관계가 지속되지 않을 것입니다. 답변 2를 참조하십시오. setGroup()없이 호출 할 수 addUser()있지만 메모리에서 개체의 상태가 일치하지 않습니다.
axtavt

올바른 매핑을 할 수 없다는 것을 알았습니다 .github에서 프로젝트를 확인할 시간이 있습니까? 작은 프로젝트입니다.
hguser

31

두 가지 주요 차이점이 있습니다.

협회 측에 액세스

첫 번째는 관계에 액세스하는 방법과 관련이 있습니다. 단방향 연결의 경우 한쪽 끝에서만 연결을 탐색 할 수 있습니다.

따라서 단방향 @ManyToOne연결의 경우 외래 키가있는 자식 쪽에서 만 관계에 액세스 할 수 있습니다.

단방향 @OneToMany연결이있는 경우 외래 키가있는 부모 쪽에서 만 관계에 액세스 할 수 있습니다.

양방향 @OneToMany연결의 경우 부모 또는 자식 쪽에서 두 가지 방법으로 연결을 탐색 할 수 있습니다.

또한 양방향 연관을 위해 추가 / 제거 유틸리티 메소드사용하여 양쪽이 올바르게 동기화되었는지 확인해야합니다 .

공연

두 번째 측면은 성능과 관련이 있습니다.

  1. 를 들어 @OneToMany, 단방향 협회는 양방향들뿐만 아니라 수행하지 않습니다 .
  2. 를 들어 @OneToOne, 양방향 연관은 Hibernate가 프록시 할당 또는 널 (null) 값할지 여부를 알 수없는 경우 부모가 eagerly 페치 원인이 될 것입니다 .
  3. 의 경우는 @ManyToMany, 컬렉션 타입은 상당히 차이가로 수 Sets보다 더 잘 수행Lists .

11

코딩 측면에서 볼 때 응용 프로그램이 JPA 사양 5 (42 페이지의 JPA 사양 5)에 따라 양쪽을 동기화 상태로 유지해야하기 때문에 양방향 관계는 구현하기가 더 복잡합니다. 불행하게도, 본 명세서에 제공된 예는 더 자세한 내용을 제공하지 않으므로, 복잡성 수준에 대한 아이디어를 제공하지는 않는다.

두 번째 레벨 캐시를 사용하지 않는 경우, 트랜잭션이 끝날 때 인스턴스가 삭제되므로 관계 메소드가 올바르게 구현되지 않는 것이 일반적으로 문제가되지 않습니다.

두 번째 레벨 캐시를 사용할 때 잘못 구현 된 관계 처리 방법으로 인해 손상된 것이 있으면 다른 트랜잭션에서도 손상된 요소를 볼 수 있습니다 (두 번째 레벨 캐시는 전역적임).

올바르게 구현 된 양방향 관계는 쿼리와 코드를 더 단순하게 만들 수 있지만 비즈니스 논리 측면에서 실제로 의미가없는 경우 사용해서는 안됩니다.


9

이것이 유일한 차이점이라고 100 % 확신 하지는 않지만 주요 차이점입니다. 또한 Hibernate 문서에 의해 양방향 연관을 갖는 것이 권장된다 :

http://docs.jboss.org/hibernate/core/3.3/reference/en/html/best-practices.html

구체적으로 특별히:

양방향 연결 선호 : 단방향 연결은 쿼리하기가 더 어렵습니다. 대규모 응용 프로그램에서는 거의 모든 연결을 쿼리에서 양방향으로 탐색 할 수 있어야합니다.

나는 개인적으로이 담요 추천에 약간의 문제가있다 - 그것은 나 아이가 부모에 대해 알고 어떤 실제적인 이유가없는 경우가 있습니다 것 같습니다 (예를 들어, 왜 주문 항목 않습니다 필요가 그것이 순서에 대해 알아야 할 사항 관련되어 있습니까?), 그러나 그 가치도 합리적입니다. 그리고 양방향성이 실제로 아무 것도 아프지 않기 때문에 나는 그것을 준수하기에 너무 불쾌감을 느끼지 않습니다.


axtavt가 설명했듯이 양방향은 경우에 따라 다칠 수 있습니다! Hibernate 엔티티에 매핑 된 모든 관계에 매우주의를 기울일 것입니다! 당신이하고있는 일을 정확히 알지 못한다면 Hibernate에 물건을로드하는 데 필요한 시간이 끝날 수 있습니다. 유스 케이스에 대해 신중하게 생각하고 다른 유스 케이스에 다른 모델 클래스를 사용하십시오. F.ex. 사물 목록에서 모든 관련 개체가 필요하지 않으며 레이블과 ID 만 있으면됩니다. 따라서 목록 엔터티는 세부 엔터티와는 다른 (매우 단순합니다) 나에게있어
cslotty
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.