2009-09-23 167 views
5

這是我的一個實體的複合主鍵。@IdClass JPA註釋

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(); 
    } 
} 

繼承人我的實體(的一部分)使用上述作爲複合主鍵。

@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) { 
// 

我對上面的實體應該是什麼樣的equals方法有點困惑。我如何比較兩個複合主鍵?

我的代碼的其他部分的任何意見也歡迎。

回答

7

將實體存儲爲主鍵不是一個好主意。使用查詢語言和JPA 1.0不支持時有一些限制。除此之外,不需要使用實體作爲主鍵。想想你想要它。如果,採取特殊看看以下問題

A class that behaves like @Entity and @Embeddable

Answer one

Comment about answer one

你會看到,使用實體主鍵是沒有必要的。

而不是

public class GroupMembershipPK implements Serializable { 

    private User user; 
    private Group group; 

} 

使用

public class GroupMembershipPK implements Serializable { 

    private Integer userId; 
    private Integer groupId; 

} 

等於實現是非常重要的,因爲JPA使用它比較兩個實體(實體JPA檢查是否是持久化上下文,通過使用等於實現)。所以,你可以根據

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

建議實行的是你使用屬性訪問而不是域訪問,因爲,在某些時候,JPA實現使用由於性能問題的代理對象是個好主意。代理對象利用屬性訪問,因爲它允許JPA實現在必要時觸擊數據庫。

如何保存使用複合主鍵的對象?

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); 

你想知道如何實現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; 
    } 
} 

另一種使用複合主鍵的方法是IdClass。見IdClass

問候,

+0

你也應該實現使用用戶ID和的groupId屬性,因爲相等的對象也必須具有相同的哈希一個hashCode方法。例如: (getUserId()== null?0:getUserId()。hashCode())^(getGroupId()== null?0:getGroupId()。hashCode()) – 2009-09-24 12:11:11

+0

@JörnHorstmann嗨,你好對。但由於答案的原因,它已經被執行只是等於執行。無論如何,謝謝 – 2009-09-24 13:35:44

+0

@Arthur Ronald。謝謝,完美的作品。但是,你能告訴我如何使用上面描述的複合主鍵持久實體嗎?我在JBoss中遇到以下錯誤,當我嘗試這樣做時.-------「線程中的異常」main「javax.ejb.EJBException:javax.persistence.PersistenceException:org.hibernate.id.IdentifierGenerationException:ids for這個類必須在調用save()之前手動分配save()「 – soontobeared 2009-10-06 16:11:26

1

有人提到的部分,反正:

  1. 在實現equals方法,你應該使用instanceof,以便與子類進行比較。如果Hibernate懶惰加載一對一或多對一的關係,那麼您將擁有該類的代理而不是普通類。代理是一個子類。比較類名稱會失敗。
    從技術上講,您應該遵循Liskovs Substitution Principle並忽略對稱性。
  2. 下一個陷阱是使用類似name.equals(that.name)而不是name.equals(that.getName())。如果這是代理,第一個將失敗。

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