2013-02-06 6 views
10

Mam tabelę, która zawiera tylko 2 pola. Tabela ma złożony PK utworzony przez te dwa pola.Tabela JPA z 2 polami klucza podstawowego

Podczas korzystania z Netbeans do tworzenia komponentów bean z bazy danych komponent bean obiektu nie jest tworzony automatycznie, tak jak inne tabele zawierające więcej niż 2 pola.

Sądzę, że muszę sam utworzyć ziarnistość. Jaka jest najlepsza praktyka tworzenia tego komponentu bean? Czy musi zawierać obiekt COMPOSITE KEY czy nie?

+0

@Xavi López: tworzą razem PK. – user2046810

Odpowiedz

27

Nie używam NetBeans, więc nie mogę powiedzieć nic o narzędziach do mapowania.

Do odwzorowania klucza złożonego dostępnych jest kilka opcji. Można

  • Zdefiniować oddzielny @Embeddable obiekt z polami PK i używać go jako @EmbeddedId w swojej klasie @Entity

    @Embeddable 
    public class MyCompositePK { 
        @Column 
        private String fieldA; 
        @Column 
        private String fieldB; 
    } 
    @Entity 
    public class MyBean { 
        @EmbeddedId 
        private MyCompositePK id; 
        @Column 
        private String fieldC; 
    } 
    
  • Zdefiniuj non-odwzorowany POJO z pól PK i używać go jako @IdClass w @Entity.

    @Entity 
    @IdClass(value=ClassAB.ClassABId.class) 
    public class ClassAB implements Serializable { 
        private String idA; 
        private String idB; 
    
        @Id 
        @Column(name="ID_A") 
        public String getIdA(){ return idA; } 
        public void setIdA(String idA){ this.idA = idA; } 
    
        @Id 
        @Column(name="ID_B") 
        public String getIdB(){ return idB; } 
        public void setIdB(String idB){ this.idB = idB; } 
    
        static class ClassABId implements Serializable { 
         private String idA; 
         private String idB; 
    
         public String getIdA(){ return idA; } 
         public void setIdA(String idA){ this.idA = idA; } 
    
         public String getIdB(){ return idB; } 
         public void setIdB(String idB){ this.idB = idB; } 
    
         // implement equals(), hashcode() 
        } 
    } 
    

    W tym przykładzie ClassABId to statyczna wewnętrzna klasa tylko dla wygody.

Te opcje wyjaśniono również w doskonałej odpowiedzi Pascala Thivent na to pytanie: How to map a composite key with Hibernate?.

To pokrewne pytanie omawia różnice między tymi podejściami: Which anotation should I use: @IdClass or @EmbeddedId. Zauważ, że deklaracja pól zostaje zduplikowana przy użyciu metody @IdClass.

W każdym razie nie sądzę, że istnieje alternatywa do utworzenia dwóch klas. Właśnie dlatego zadałem to pytanie: Mapping a class that consists only of a composite PK without @IdClass or @EmbeddedId. Wygląda na to, że jest to funkcja specyficzna dla hibernacji.

Na marginesie, jeśli masz kontrolę nad strukturą DB, możesz również rozważyć unikanie kluczy złożonych. There are some reasons to do so.

+2

Biorąc pod uwagę, że obiekt zawiera tylko dwa podstawowe pola klucza, czy może to być jego własna "IdClass"? –

+1

@TomAnderson To interesujące. Nigdy nie próbowałem. Wygląda na to, że [ktoś zrobił] (https://forum.hibernate.org/viewtopic.php?p=2419264), bez powodzenia.Spec nie wydaje się tego wymawiać. Może zależeć od wdrożenia. –

+1

@TomAnderson: Nie sądzę, ponieważ klasa ID musi zaimplementować metodę equals() opartą tylko na wartościach kluczy złożonych. –

0

Dzięki @ XaviLópez. Twoje wyjaśnienie naprawiło mój kod, który został zadeklarowany jako własny IdClass wspomniany przez @Tom Anderson. Kiedy zadeklarowałem jako własny IdClass z 2 kolumnami @Id, zapytanie JPA pobierające listę tego obiektu zwróciło oczekiwane "n" elementy na liście wyników, ale każdy element na tej liście ma wartość null. Ale rozmiar "n" jest oczekiwany. Po przejściu do statycznej klasy wewnętrznej, która jest mniej refaktoryzacji, jest w stanie zwrócić właściwy zestaw wyników.

Według mnie: samo odniesienie IdClass nie będzie działać, ponieważ jaźń jest już bytem i musi być w Kontekście trwałości. Jeśli mam również podstawowy obiekt klucza tego samego typu, to w kontekście utrwalania będą dwa "identyczne" obiekty. Tak więc nie powinno być dozwolone. Dlatego nie powinniśmy używać samoodnośnego @IdClass. Utwórz statyczną klasę wewnętrzną jako typ klucza głównego, który jest mniej inwazyjny.

Powiązane problemy