2012-12-14 9 views
5

Używam tylko adnotacji JPA i hibernacji 4.0.1 jako implementacji JPA.Tabela odwzorowań JPA/Hibernate dla relacji Jeden do wielu

Mam klasy Assessment który ma dwa zestawy Comment:

@Entity 
@Table(name = "ASSESSMENT") 
public class Assessment{ 

    @OneToMany(fetch = FetchType.EAGER) 
    private Set<Comment> auditComments = new HashSet<Comment>(); 

    @OneToMany(fetch = FetchType.EAGER) 
    private Set<Comment> comments = new HashSet<Comment>(); 
} 

(ja pomijam pobierające, ustawiaczy, kaskady adnotacji i innych nieistotnych linii kodu)

Komentarz:

@Entity 
@Table(name = "COMMENT") 
public class Comment{ 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private Long id; 

    @Column(columnDefinition = "text") 
    private String text; 
} 

Teraz, ponieważ Comment nie ma odwołanie z powrotem do Assessment (jest to celowo), nie mogę używać właściwości mappedBy, a Hibernate musi utworzyć tabelę odwzorowań między Comment i Assessment. Domyślnie nazywa się ASSESSMENT_COMMENT.

Gdybym miał tylko jeden zestaw Comment w Assessment, to działałoby idealnie dobrze. ASSESSMENT_COMMENT miałby tylko dwie kolumny:

[ASSESSMENT_ID, COMMENT_ID] 

, które doskonale reprezentują relację jeden-do-wielu.

Teraz tutaj jest problem:

Bo nie ma jednego zestawu Comment ale dwóch, Hibernate stara się odwzorować dwa zestawy przy użyciu tylko jednej tabeli ASSESSMENT_COMMENT. Ta tabela ma 3 kolumny:

[ASSESSMENT_ID, COMMENT_ID, AUDITCOMMENT_ID] 

Oprócz tego 3 kolumny są ustawione jako nie-null.

To na pewno nie zadziała. Na przykład, jeśli mam tylko jeden element w audComents i żaden w komentarzach, hibernate próbuje wstawić jeden wiersz z wartością null w COMMENT_ID, który tworzy wyjątek SQL.

Pytania:

Dla mnie to wygląda na błąd. Powinny być dwie tabele mapowania, a nie jedna.

Tak, 1) czy jest to znany błąd w Hibernate? 2) czy istnieje sposób obejścia tego? Czy mogę wymusić Hibernate, aby utworzyć dwie tabele odwzorowania, po jednej dla każdego zestawu. Należy pamiętać, że nie można zmienić klasę Comment mieć odniesienie do Assessment (wymaganie logika biznesowa)

Odpowiedz

8

Przede wszystkim, można użyć dwóch kolumn w tabeli komentarza zwrócić z powrotem do ich oceny:

@OneToMany(fetch = FetchType.EAGER) 
@JoinColumn(name = "audit_commented_assessment_id") 
private Set<Comment> auditComments = new HashSet<Comment>(); 

@OneToMany(fetch = FetchType.EAGER) 
@JoinColumn(name = "commented_assessment_id") 
private Set<Comment> comments = new HashSet<Comment>(); 

Jeśli chcesz przyłączyć dwie tabele, sprawiedliwy powiedzieć tak:

@OneToMany(fetch = FetchType.EAGER) 
@JoinTable(name = "assessment_audit_comment", 
      joinColumns = @JoinColumn(name = "assessment_id"), 
      inverseJoinColumns = @JoinColumn(name = "comment_id")) 
private Set<Comment> auditComments = new HashSet<Comment>(); 

@OneToMany(fetch = FetchType.EAGER) 
@JoinTable(name = "assessment_comment", 
      joinColumns = @JoinColumn(name = "assessment_id"), 
      inverseJoinColumns = @JoinColumn(name = "comment_id")) 
private Set<Comment> comments = new HashSet<Comment>(); 

to oczywiście wyjaśnione the documentation.

+0

Dzięki temu poprawiono. Nigdy nie miałem dwóch kolekcji tego samego typu, więc nigdy nie musiałem używać adnotacji @JoinTable. – phoenix7360

+0

Jak wyglądałaby klasa Komentarz, jeśli chciałbyś mieć relację dwukierunkową? Na przykład. w komentarzu POJO chciałbym mieć odniesienie do oceny? Nie możesz użyć dwóch @jointable (jeden przeciwko każdej tabeli mapowania rodzica)? Jak byś to zrobił? – nize

+2

@nize: Jeśli powiązania były dwukierunkowe, musiałbyś skomentować stronę właściciela skojarzeń. W Comment masz pole 'commentedAssessment' i pole' audititedAssessment'. Zostaną zmapowane za pomocą '@ ManyToOne', z tabelą łączenia jak powyżej, ale z połączonymi Kolumnami i inwersjamiJoinKolumnami. W Assessment po prostu masz '@OneToMany (mappedBy =" auditedAssessment ") private Set auditComments;' i '@OneToMany (mappedBy =" commentedAssessment ") Ustaw komentarze;' –

Powiązane problemy