Jak tworzyć i obsługiwać złożony klucz podstawowy w JPA

108

Chcę mieć wersje z tego samego wpisu danych. Innymi słowy, chcę zduplikować wpis z innym numerem wersji.

id - Version będzie kluczem podstawowym.

Jak powinna wyglądać jednostka? Jak mogę go skopiować z inną wersją?

id Version ColumnA

1   0      Some data
1   1      Some Other data
2   0      Data 2. Entry
2   1      Data
Kayser
źródło
Korzystając z @IdClassadnotacji, kolejną wskazówką, którą znalazłem, jest to, że @Columnadnotacja powinna zostać umieszczona w polach klasy Entity ( YourEntityw przykładowym kodzie RohitJan).
KenSV

Odpowiedzi:

231

Możesz utworzyć Embedded class, który zawiera twoje dwa klucze, a następnie mieć odniesienie do tej klasy, tak jak EmbeddedIdw twoim Entity.

Byś potrzebne @EmbeddedIdi @Embeddableadnotacje.

@Entity
public class YourEntity {
    @EmbeddedId
    private MyKey myKey;

    @Column(name = "ColumnA")
    private String columnA;

    /** Your getters and setters **/
}
@Embeddable
public class MyKey implements Serializable {

    @Column(name = "Id", nullable = false)
    private int id;

    @Column(name = "Version", nullable = false)
    private int version;

    /** getters and setters **/
}

Innym sposobem osiągnięcia tego zadania jest użycie @IdClassadnotacji i umieść Zarówno idw to IdClass. Teraz możesz użyć normalnych @Idadnotacji dla obu atrybutów

@Entity
@IdClass(MyKey.class)
public class YourEntity {
   @Id
   private int id;
   @Id
   private int version;

}

public class MyKey implements Serializable {
   private int id;
   private int version;
}
Rohit Jain
źródło
4
Czy można używać @Generatedvalueidentyfikatorów przez EmbeddedId
Kayser,
1
@Kayser. Z tego co wiem. Nie. Musisz jawnie ustawić ich wartość w swojej instancji KeyClass, a następnie ustawić tę instancję klasy klucza w swoim Entity.
Rohit Jain
@Kayser. @GeneratedValuemoże służyć tylko do generowania wartości kluczy dla klucza podstawowego, nie może generować kombinacji dla kluczy złożonych.
Rohit Jain
1
@RohitJain tylko jedno: tak naprawdę nie możesz upublicznić osadzonej klasy (aby była publiczna, musi znajdować się we własnym pliku)
Lucas
1
@FastEngy Nadal można uzyskać do niego dostęp przez Wayback Machine: web.archive.org/web/20170123035517/http://uaihebert.com/… . Wygląda na to, że ten artykuł został zastąpiony przez web.archive.org/web/20170202203555/http://uaihebert.com/… i web.archive.org/web/20161014051056/http://uaihebert.com/…, które również zniknęły …
radlan
9

Klasa MyKey musi zostać zaimplementowana, Serializablejeśli używasz@IdClass

Swapnil17
źródło
5

Klasa klucza:

@Embeddable
@Access (AccessType.FIELD)
public class EntryKey implements Serializable {

    public EntryKey() {
    }

    public EntryKey(final Long id, final Long version) {
        this.id = id;
        this.version = version;
    }

    public Long getId() {
        return this.id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Long getVersion() {
        return this.version;
    }

    public void setVersion(Long version) {
        this.version = version;
    }

    public boolean equals(Object other) {
        if (this == other)
            return true;
        if (!(other instanceof EntryKey))
            return false;
        EntryKey castOther = (EntryKey) other;
        return id.equals(castOther.id) && version.equals(castOther.version);
    }

    public int hashCode() {
        final int prime = 31;
        int hash = 17;
        hash = hash * prime + this.id.hashCode();
        hash = hash * prime + this.version.hashCode();
        return hash;
    }

    @Column (name = "ID")
    private Long id;
    @Column (name = "VERSION")
    private Long operatorId;
}

Klasa podmiotu:

@Entity
@Table (name = "YOUR_TABLE_NAME")
public class Entry implements Serializable {

    @EmbeddedId
    public EntryKey getKey() {
        return this.key;
    }

    public void setKey(EntryKey id) {
        this.id = id;
    }

    ...

    private EntryKey key;
    ...
}

Jak mogę go powielić z inną wersją?

Możesz odłączyć jednostkę, która została pobrana od dostawcy, zmienić klucz Entry, a następnie utrwalić ją jako nową jednostkę.

callfarc0de
źródło
Czy można zdefiniować identyfikator w Entrykey AUTOGENERATED. oder coś takiego @GeneratedValue(strategy = GenerationType.IDENTITY)
Kayser
1
Zastanawiam się też, jak obliczyć hash dla 2 długich kluczy podstawowych. Jak dla hashi primena metody hashCodew klasie EntryKey, możesz mi powiedzieć, gdzie ta idea pochodzi?
Bruce Sun
1

Klasa MyKey (@Embeddable) nie powinna mieć żadnych relacji, takich jak @ManyToOne

Ranuka
źródło
Dlaczego nie? Czy spojrzałeś na ten przykład ?
Buhake Sindi