2009-09-23 15 views
5

ここには、自分のエンティティの1つの複合主キーがあります。@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(); 
    } 
} 

Heres私のエンティティ(一部)は、複合主キーとして上記を使用しています。

@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メソッドの実装とは何かについて少し混乱しています。 2つの複合主キーを比較するにはどうすればよいですか?

私のコードの他の部分についてのコメントも大歓迎です。

答えて

7

エンティティを主キーとして保存することはお勧めできません。クエリー言語を使用する場合、JPA 1.0がサポートしていない場合、いくつかの制限があります。それ以外に、エンティティを主キーとして使用する必要はありません。あなたは主キーとしてエンティティを使用する必要がないことがわかります

Comment about answer one

Answer one

A class that behaves like @Entity and @Embeddable

次の質問で特別見て、あなたがしたいit.If考えてみてください。

代わりの

public class GroupMembershipPK implements Serializable { 

    private User user; 
    private Group group; 

} 

使用

public class GroupMembershipPK implements Serializable { 

    private Integer userId; 
    private Integer groupId; 

} 

JPAはそれを(エンティティに等しい実装を使用して永続コンテキスト内にあるかどうかをJPAチェック)を使用して2つのエンティティを比較するため、実装が重要であると等しいです。だから、

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()) –

+0

@JörnHorstmannこんにちは右。しかし、それは実装されているため、回答は実装のためだけです。とにかくありがとうございます –

+0

@Arthur Ronald。ありがとう、完璧に動作します。しかし、上記のように複合主キーを使用してエンティティを永続化する方法を教えてください。 JBossで私がしようとすると、次のようなエラーが発生します.------- "スレッド" main "javax.ejb.EJBExceptionの例外:javax.persistence.PersistenceException:org.hibernate.id.IdentifierGenerationException:idsこのクラスはsave()を呼び出す前に手動で割り当てる必要があります " – soontobeared

1

を参照してください。それはとにかく、部分的に言及されました:

  1. equalsメソッドを実装するとき、あなたはサブクラスと比較できるようにinstanceofを使用する必要があります。 Hibernateが1対1または多対1のリレーションをロードする場合、プレーンクラスではなくクラス用のプロキシを使用します。プロキシはサブクラスです。クラス名の比較は失敗します。
    さらに技術的には、Liskovs Substitution Principleに従って対称性を無視する必要があります。
  2. 次の落とし穴は、name.equals(that.getName())の代わりにname.equals(that.name)のようなものを使用しています。それがプロキシの場合、最初のものは失敗します。

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

関連する問題