2012-10-27 3 views
15

두 엔티티 USER 및 NOTIFICATION이 있다고 가정 해 보겠습니다. 그리고 저는 아래와 같이 관계를 맺고 있습니다.JPA OneToMany :리스트 대 세트

public class UserAccount{ 

    @Id 
    @Column(name = "USER_NAME") 
    private String emailid; 

    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL) 
    @JoinTable(name = "USERS_NOTIFICATIONS", joinColumns = { @JoinColumn(name = "USER_NAME") }, inverseJoinColumns = { @JoinColumn(name = "NOTIFICATION_ID") }) 
    private List<Notification> notifications; 

    //setters, getter, equals and hashcode 
} 

나는 equals와 hashcode (비즈니스 키/기본 키로 생성 된 IDE)를 오버라이드했습니다. 사용자 A가 있다고 가정 해보십시오. 첫 번째 알림을 추가하면 일반 삽입 문이 생깁니다. 그러나 동일한 사용자에 대한 추가 기능을 추가하면 삭제 한 다음 삽입합니다. 로그입니다 :

Hibernate: delete from USERS_NOTIFICATIONS where USER_NAME=? 
Hibernate: insert into USERS_NOTIFICATIONS (USER_NAME, NOTIFICATION_ID) values (?, ?) 
Hibernate: insert into USERS_NOTIFICATIONS (USER_NAME, NOTIFICATION_ID) values (?, ?) 
Hibernate: insert into USERS_NOTIFICATIONS (USER_NAME, NOTIFICATION_ID) values (?, ?) 
//as many inserts as the notifications the user has 

모든 사용자에게 동일한 결과가 발생합니다. 이제 Set with List를 바꾸면 정상적인 삽입이 발생합니다. 그리고 doucmentationblog을 읽은 후에 이유를 발견했습니다. 단방향 OneToMany 연결 설정 프리젠

  • 에서

    관측이 바람직하다.

는 인덱싱 된 콜렉션 및 세트 요소들을 추가하고, 제거하고 업데이트의 측면에서 가장 효율적인 작업을 할 수 있음을 분명히해야한다. 양방향 OneToMany 관계에서

  • 은 (ManyToOne의 관리) 목록 및 가방 효율적입니다.

가방 및 목록 질문

커플 가장 효율적인 역 모음입니다

  1. 합니까 내가 단방향 OneToMany 맵핑의 목록을 통해 설정을 선호 할이 평균 (꽤 분명하지만)? 하지만 해결 방법이 있습니까?
  2. 또는 중복이있을 때 목록을 사용하는 데 양방향 관계가되도록 도메인을 조정해야합니까?
+2

주문을 원할 때 List를 사용하고 그렇지 않을 때는 Set을 사용한다고 생각했을 것이다. 지속성 솔루션과 상관없이 모델링 할 필요가있는 것을 기반으로 모델을 선택하십시오. 모든 퍼시스턴스 솔루션은 어느 하나를 처리 할 수 ​​있어야합니다. – DataNucleus

+3

@DataNucleus : 하나는 그렇게 생각했을 것입니다. Hibernate가 단방향 맵에 효율적으로 추가하는 것을 처리 할 것이라고 생각할 수도있다. 때로는 사람들이 생각이 잘못되었다는 것을 알게됩니다! –

+0

@DataNucleas : 나는 그런 식으로 생각했다.하지만 위에서 언급 한 문제를 얻은 후 문서를 통해 나는 그 이상을 발견했다. – shazinltc

답변

1

목록 : 중복 요소를 허용합니다.

집합 : 모든 요소는 고유해야합니다.

이제 목록에서 요소를 덮어 쓰는 중일 때 삭제가 발생할 수 있으므로 UserAccount 유형의 지속 된 엔터티를 수정하면 이전 목록에있는 항목이 제거됩니다.

+0

아니오. 그렇지 않습니다. 제가 열거 한 문서를 읽으십시오. 삭제 이유가 있습니다. – shazinltc

8

나는 오래 전에이 문제에 직면했다.짧은에서 최대 절전 모드 https://fedcsis.org/proceedings/2013/pliks/322.pdf

에 많은 협회에 성능 안티 패턴 하나의 :

내가이 글을 발견

  • 가방 의미 ->List/Collection + @OneToMany -> 하나의 요소 추가 : 1 삭제 , N 삽입, 삭제 된 하나의 요소 : 삭제, N 삽입
  • 목록 의미 ->List + @OneToMany + @IndexColumn/@OrderColumn -> 하나의 요소 추가 : 1 개 삽입, M 업데이트, 하나의 요소 제거 : 1 삭제, M 업데이트
  • 설정의 의미 ->Set + @OneToMany -> 하나의 요소 추가 : 1 개 삽입, 하나의 요소가 제거 : 1
삭제

나를 위해 : 그렇습니다. 단방향 인 @OneToMany에 대해 ListSet으로 변경해야한다는 것을 의미합니다. 따라서 최대 절전 모드 예상과 일치하도록 모델을 변경했는데 응용 프로그램의보기 부분이 대부분 List에 의존했기 때문에 많은 문제가 발생했습니다 ...

한 손으로는 Set이 나를위한 논리적 인 선택입니다. 중복이 없으며, 반면에 List은 다루기가 더 쉬웠습니다.

그래서 JPA/Hibernate가 모델 객체를 변경하도록 강요했는데, @EmbededId을 사용할 때 JPA/Hibernate 없이는 그렇게하지 않을 것입니다. 그리고 당신이 항상 equals 메소드의 모든 어플리케이션에서 HibernateProxy을 알아야 할 때 ... else if(object instanceof HibernateProxy) { ..., JPA/Hibernate 퍼티 테이션 레이어가 다른 레이어에 조금 침입하는 것을 알 수 있습니다.

그러나 directely JDBC를 사용할 때 모델 또는 비즈니스 방법을 변경하여 지속성을 향상시키는 데 사용합니다. 레이어 분리가 꿈일 수 있으며 비용이 너무 많이들 수 있습니다.

그리고 그들은 주석 일부 코드가 List에 의존 (예 : JSF/PrimeFaces <dataTable> 또는 <repeat> 구성 요소로) 변경할 수없는 문제를 가지고 @OrderBy

TreeSet 같은 SortedSet을 경우 당신은 Set을 주문할 수 있습니다 따라서 을 List으로 변경하고 Set으로 돌아 가야합니다. 그러나 setNotifications(new HashSet<>(notificationList))을 수행하면 최대 절전 모드로 관리되는 org.hibernate.collection.PersistentSet이므로 추가 쿼리가 발생합니다 ... 그래서 addAll()removeAll()을 사용했습니다. 세터 대신 :

protected <E> void updateCollection(@NonNull Collection<E> oldCollection, @NonNull Collection<E> newCollection) { 
    Collection<E> toAdd = new ArrayList<>(newCollection) ; 
    toAdd.removeAll(oldCollection) ; 

    Collection<E> toRemove = new ArrayList<>(oldCollection) ; 
    toRemove.removeAll(newCollection) ; 

    oldCollection.removeAll(toRemove) ; 
    oldCollection.addAll(toAdd) ; 
} 

마음 당신의 @Entityequals()hashCode() 방법 ...

또 다른 한가지 문제점은 Set/List/Bag 의미가 JPA가 아닌 Hibernate에서이기 때문에 구현으로 Hibernate와 함께 JPA를 사용하려는 경우 JPA와 Hibernate를 모두 마스터해야한다는 것입니다.)

하나의 특정 공급 업체에 의존하지 않도록 구현을 추상화하기위한 사양입니다. 대부분의 JavaEE 스펙이 성공했지만 JPA는 실패했고 나는 Hibernate와 독립적으로 포기했다.

+0

감사합니다. 신문은 정말로 더 나쁜 독서 다! –