168 votes

Quelle annotation devrais-je utiliser: @IdClass ou @EmbeddedId

La spécification JPA (Java Persistence API) dispose de deux manières différentes de spécifier des clés composites d'entité: @IdClass et @EmbeddedId.

J'utilise les deux annotations sur mes entités mappées, mais cela s'avère être un gros désastre pour les personnes qui ne connaissent pas très bien JPA.

Je souhaite adopter un seul moyen de spécifier des clés composites. Lequel est vraiment le meilleur? Pourquoi?

121voto

smink Points 39640

Je considère que, @EmbeddedId est probablement plus détaillé parce que, avec l' @IdClass vous ne pouvez pas accéder à l'intégralité de la clé primaire de l'objet à l'aide de n'importe quel champ de l'accès de l'opérateur. À l'aide de l' @EmbeddedId vous pouvez le faire comme ceci:

@Embeddable class EmployeeId { name, dataOfBirth }
@Entity class Employee {
  @EmbeddedId EmployeeId employeeId;
  ...
}

Cela donne une notion claire des champs qui font de la clé composite, car elles sont toutes regroupées dans une classe qui est accessible par le biais d'un accès sur le terrain de l'opérateur.

Une autre différence avec @IdClass et @EmbeddedId , c'est quand il s'agit d'écrire les requêtes HQL :

Avec @IdClass vous écrivez:

sélectionnez c.ClientId de la Clientèle c

et avec @EmbeddedId vous devez écrire:

sélectionnez c.MyPk.ClientId de la Clientèle c

Vous devez écrire plus de texte pour la même requête. Certains pourraient faire valoir que ce qui diffère de plus de la langue naturelle comme celle promue par IdClass. Mais la plupart du temps, la compréhension de droit à partir de la requête d'un champ donné est la partie de la clé composée est d'une aide précieuse.

19voto

laz Points 12212

J'ai découvert un cas où j'ai eu à utiliser EmbeddedId en faveur de IdClass. Dans ce scénario il y a une table de jointure qui a des colonnes supplémentaires définies. J'ai tenté de résoudre ce problème en utilisant IdClass pour représenter la clé d'une entité qui représente explicitement les lignes dans la table de jointure. Je ne pouvais pas le faire fonctionner de cette façon. Heureusement, "la Persistance Java Avec Hibernate" a une section dédiée à ce sujet. Une des solutions proposées était très semblable à la mienne mais elle a utilisé EmbeddedId à la place. J'ai modélisé ma objets après ceux dans le livre il se comporte désormais correctement.

18voto

Ondrej Bozek Points 1988

Autant que je sache, si votre composite PK contient FK il est plus facile et plus simple à utiliser @IdClass

Avec @EmbeddedId vous devez définir la configuration de votre FK colonne deux fois, onece en @Embeddedable et une fois pour comme par exemple @ManyToOne@ManyToOne doit être en lecture seule(@PrimaryKeyJoinColumn) parce que vous ne pouvez pas avoir un jeu de colonnes à deux variables (conflits possibles).
Donc, vous devez configurer votre FK à l'aide de simples type en @Embeddedable.

Sur l'autre site à l'aide d' @IdClass cette situation peut être traitée beaucoup plus facile, comme indiqué dans les Clés Primaires par le biais de OneToOne et Relations ManyToOne:

Exemple JPA 2.0 ManyToOne id de l'annotation

...
@Entity
@IdClass(PhonePK.class)
public class Phone {

    @Id
    private String type;

    @ManyToOne
    @Id
    @JoinColumn(name="OWNER_ID", referencedColumnName="EMP_ID")
    private Employee owner;
    ...
}

Exemple JPA 2.0 id de classe

...
public class PhonePK {
    private String type;
    private long owner;

    public PhonePK() {}

    public PhonePK(String type, long owner) {
        this.type = type;
        this.owner = owner;
    }

    public boolean equals(Object object) {
        if (object instanceof PhonePK) {
            PhonePK pk = (PhonePK)object;
            return type.equals(pk.type) && owner == pk.owner;
        } else {
            return false;
        }
    }

    public int hashCode() {
        return type.hashCode() + owner;
    }
}

9voto

bertie Points 4186

Je pense que le principal avantage est que nous pourrions utiliser @GeneratedValue pour l'identifiant lors de l'utilisation de @IdClass? Je suis sûr que nous ne pouvons pas utiliser @GeneratedValue pour @EmbeddedId.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X