Comment créer et gérer une clé primaire composite dans JPA

108

Je veux avoir des versions de la même entrée de données. En d'autres termes, je souhaite dupliquer l'entrée avec un autre numéro de version.

id - Version sera la clé primaire.

À quoi devrait ressembler l'entité? Comment puis-je le dupliquer avec une autre version?

id Version ColumnA

1   0      Some data
1   1      Some Other data
2   0      Data 2. Entry
2   1      Data
Kayser
la source
Lors de l'utilisation de l' @IdClassannotation, un autre conseil que j'ai trouvé est que l' @Columnannotation doit aller dans les champs de la classe Entity ( YourEntitydans l'exemple de code de RohitJan).
KenSV

Réponses:

231

Vous pouvez créer un Embedded class, qui contient vos deux clés, puis avoir une référence à cette classe comme EmbeddedIddans votre fichier Entity.

Vous auriez besoin des annotations @EmbeddedIdet @Embeddable.

@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 **/
}

Une autre façon de réaliser cette tâche est d'utiliser l' @IdClassannotation et le lieu à la fois votre iddans ce IdClass. Vous pouvez maintenant utiliser l' @Idannotation normale sur les deux attributs

@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
la source
4
Est-il possible d'utiliser @Generatedvaluepour les identifiants par EmbeddedId
Kayser
1
@Kayser. Pour autant que je sache. Non. Vous devez définir explicitement leur valeur dans votre instance KeyClass, puis définir cette instance de classe de clé dans votre entité.
Rohit Jain
@Kayser. @GeneratedValuene peut être utilisé que pour générer des valeurs de clé pour une clé primaire, il ne peut pas générer de combinaison pour des clés composites.
Rohit Jain
1
@RohitJain juste une chose: vous ne pouvez en fait pas rendre publique la classe intégrée (doit être dans son propre fichier pour être publique)
Lucas
1
@FastEngy Il est toujours accessible via Wayback Machine: web.archive.org/web/20170123035517/http://uaihebert.com/… . Il semble que cet article soit remplacé par web.archive.org/web/20170202203555/http : //uaihebert.com/... et web.archive.org/web/20161014051056/http://uaihebert.com/… qui a également disparu …
radlan
9

La classe MyKey doit implémenter Serializablesi vous utilisez@IdClass

Swapnil17
la source
5

Classe clé:

@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;
}

Classe d'entité:

@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;
    ...
}

Comment puis-je le dupliquer avec une autre version?

Vous pouvez détacher l'entité récupérée du fournisseur, modifier la clé d'entrée, puis la conserver en tant que nouvelle entité.

callfarc0de
la source
Ist il est possible de définir l'identifiant dans Entrykey AUTOGENERATED. ou quelque chose comme ça @GeneratedValue(strategy = GenerationType.IDENTITY)
Kayser
1
Je me demande également comment calculer le hachage pour 2 longues clés primaires. En ce qui concerne hashet primeen méthode hashCodeen classe EntryKey, pouvez-vous me dire d'où vient cette idée?
Bruce Sun
1

La classe MyKey (@Embeddable) ne doit pas avoir de relations comme @ManyToOne

Ranuka
la source
Pourquoi pas? Avez-vous regardé cet exemple ?
Buhake Sindi