2009-09-23 9 views
5

Ecco una chiave primaria composta per una delle mie entità.@IdClass JPA Annotation

public class GroupMembershipPK implements Serializable{ 

    private static final long serialVersionUID = 7816433876820743311L; 

    private User user; 
    private Group group; 

    public GroupMembershipPK(){ 
    } 

    public boolean equals(Object o){ 
     if(o==null){ 
      return false; 
     } 

     if(o instanceof GroupMembershipPK){ 
      final GroupMembershipPK groupMembershipPK=(GroupMembershipPK)o; 
      return groupMembershipPK.group.getGroupName().equals(this.group.getGroupName()) && 
       groupMembershipPK.user.getName().equals(this.user.getName()); 
     } 
     return false; 
    } 

    public int hashCode(){ 
     return super.hashCode(); 
    } 
} 

Ecco la mia entità (parte di) utilizzando il precedente come chiave primaria composta.

@Entity 
@IdClass(GroupMembershipPK.class) 
public class GroupMembership extends AbstractModelElementVersionOther{ 

    private static final long serialVersionUID = 9188465566607060376L; 

    private String memType; 
    private Group group; 
    private User user; 

    public GroupMembership(){ 
     super(); 
    } 

    @Column(nullable=false) 
    public String getMemType(){ 
     return this.memType; 
    } 

    public void setMemType(String memType){ 
     this.memType=memType; 
    } 

    @Id 
    @ManyToOne 
    @JoinColumn(name="groupId") 
    public Group getGroup(){ 
     return this.group; 
    } 

    public void setGroup(Group group){ 
     this.group=group; 
    } 

    @Id 
    @ManyToOne 
    @JoinColumn(name="userId") 
    public User getUser(){ 
     return this.user; 
    } 

    public void setUser(User user){ 
     this.user=user; 
    } 

    @Override 
    public boolean equals(Object o) { 
// 

Sono un po 'confuso su quale dovrebbe essere l'implementazione del metodo di uguale per l'entità di cui sopra. Come posso confrontare due chiavi primarie composite?

Anche i commenti su altre parti del mio codice sono ben accetti.

risposta

7

Non è una buona idea memorizzare le entità come chiave primaria. Esistono alcune limitazioni nell'utilizzo del linguaggio di query e JPA 1.0 non supporta. Inoltre, non è necessario utilizzare le entità come chiave primaria. Pensate it.If volete, date un'occhiata speciale alla seguente domanda

A class that behaves like @Entity and @Embeddable

Answer one

Comment about answer one

Vedrete che utilizza un'entità come chiave primaria non è necessaria.

Invece di

public class GroupMembershipPK implements Serializable { 

    private User user; 
    private Group group; 

} 

Usa

public class GroupMembershipPK implements Serializable { 

    private Integer userId; 
    private Integer groupId; 

} 

uguale implementazione è importante perché APP a confronto due soggetti usandolo (assegni JPA se un soggetto è in contesto di persistenza utilizzando uguale implementazione). Così si può implementare in base alle

public boolean equals(Object o) { 
    if(o == null) 
     return false; 

    if(!(o instanceof GroupMembershipPK)) 
     return false; 

    GroupMembershipPK other = (GroupMembershipPK) o; 
    if(!(getUserId().equals(other.getUserId())) 
     return false; 

    if(!(getGroupId().equals(other.getGroupId())) 
     return false; 

    return true; 
} 

Consigli: è una buona idea di utilizzare l'accesso alle proprietà, invece di accesso campo perché, in alcuni momenti, implementazione JPA utilizza un oggetto proxy a causa di problemi di prestazioni. Un oggetto proxy utilizza l'accesso alla proprietà perché consente l'implementazione JPA nel database quando necessario.

Come salvare un oggetto che utilizza una chiave primaria composta?

User user = new user(); 
Group group = new Group(); 

entityManager.save(user); 
entityManager.save(group); 

entityManager.flush(); 

UserGroup userGroup = new UserGroup(); 

userGroup.setId(new UserGroup.UserGroupId(user.getId(), group.getId())); 

entityManager.save(userGroup); 

Vuoi sapere come implementare UserGroup?

public class UserGroup { 

    private UserGroupId id; 

    // You can create UserGroupId outside UserGroup class 
    // Feel free to choice your best approach 
    @Embeddable 
    public static class UserGroupId implements Serializable { 

     private Integer userId; 
     private Integer groupId; 

     // required no-arg constructor 
     public UserGroupId() {} 

     public UserGroupId(Integer userId, Integer groupId) { 
      this.userId = userId; 
      this.roupId = groupId; 
     } 

     // getter's and setter's 

     // equals and hashcode as shown above 

    } 

    @EmbeddedId 
    public UserGroupId getId() { 
     return this.id; 
    } 

    public setId(UserGroupId id) { 
     this.id = id; 
    } 
} 

Un altro approccio per utilizzare la chiave primaria composita è IdClass. Vedere IdClass

saluti,

+0

si dovrebbe anche implementare un metodo hashCode che utilizza le proprietà GroupID UserID e, in quanto oggetti uguali devono anche avere lo stesso hash. Per esempio: (getUserId() == null? 0: getUserId(). HashCode())^(getGroupId() == null? 0: getGroupId(). HashCode()) –

+0

@ Jörn Horstmann Ciao, sei destra. Ma è stato implementato solo uguale implementazione a causa della risposta. Grazie comunque –

+0

@Arthur Ronald. Grazie, funziona perfettamente. Tuttavia, puoi dirmi come mantenere l'entità utilizzando una chiave primaria composita come descritto sopra? Ottengo il seguente errore in JBoss quando provo a farlo .------- "Eccezione nel thread" main "javax.ejb.EJBException: javax.persistence.PersistenceException: org.hibernate.id.IdentifierGenerationException: ids for questa classe deve essere assegnata manualmente prima di chiamare save() " – soontobeared

1

E 'stato menzionato in parte, in ogni caso:

  1. Nell'attuare il metodo equals, si dovrebbe uso instanceof per consentire il confronto con sottoclassi. Se Hibernate lazy carica una relazione uno a uno o molti a uno, si avrà un proxy per la classe invece della classe normale. Un proxy è una sottoclasse. Il confronto tra i nomi delle classi fallirebbe.
    Più tecnicamente, si dovrebbe seguire lo Liskovs Substitution Principle e ignorare la simmetria.
  2. Il prossimo errore è che utilizza qualcosa come name.equals(that.name) anziché name.equals(that.getName()). Il primo fallirà, se questo è un proxy.

http://www.laliluna.de/jpa-hibernate-guide/ch06s06.html

Problemi correlati