tags:

views:

682

answers:

2

Hi, Heres a composite primary key for one of my entities.

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 my entity(part of) using the above as a Composite Primary Key.

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

I am a little confused on what should be the equals method implementation for the above entity. How can I compare two composite primary keys?

Any comments on other parts of my code are welcome too :)..i am a JPA beginner

Thanks

A: 

Not sure what you're asking, because the simple question is to implement equals....

Jim Barrows
Yes. I was asking the same. Sorry If i didn't put it the right way.
soontobeared
+4  A: 

Hi,

It is not a good idea you store entities as primary key. There is some limitations when using query language and JPA 1.0 does not support. Besides it there is no need to use entities as primary key. Think about it.If you want, take a special look at the following question

A class that behaves like @Entity and @Embeddable

Answer one

Comment about answer one

You will see that using a entity as primary key is not necessary.

Instead of

public class GroupMembershipPK implements Serializable {

    private User user;
    private Group group;

}

Use

public class GroupMembershipPK implements Serializable {

    private Integer userId;
    private Integer groupId;

}

equals implementation is important because JPA compares two entities by using it (JPA checks whether an entity is in persistence context by using equals implementation). So you can implement according to

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

Advice: it is a good idea you use property access instead of field access because, at some times, JPA implementation uses a proxy object because of performance issues. A proxy object makes use of property access because it allows JPA implementation hits the database when necessary.

How to save an object that uses a composite primary key ?

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

Do you want to know how to implement 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 getId() {
        return this.id;
    }

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

Another approach to use composite primary key is IdClass. See IdClass

regards,

Arthur Ronald F D Garcia
You should also implement a hashCode method that uses the userId and groupId properties, since equal objects must also have the same hash. For Example:(getUserId() == null ? 0 : getUserId().hashCode()) ^ (getGroupId() == null ? 0 : getGroupId().hashCode())
Jörn Horstmann
@Jörn Horstmann Hi, you are right. But it have been implemented only equals implementation due to answer. Thank you anyway
Arthur Ronald F D Garcia
@Arthur Ronald . Thanks, Works perfectly. However, can you tell me how to persist the entity using a composite primary key as described above? I get the following error in JBoss when I try to do that.-------"Exception in thread "main" javax.ejb.EJBException: javax.persistence.PersistenceException: org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before calling save()"
soontobeared
@soontobeared It occurs because if an object has an assigned identifier - it means no @GeneratedValue -, OR A COMPOSITE KEY, the identifier SHOULD BE ASSIGNED to the object instance BEFORE calling save()
Arthur Ronald F D Garcia
Added to original answer, regards
Arthur Ronald F D Garcia
@Arthur Ronald....Thankyou...works great...
soontobeared
If you want, take a look at the following answer: http://stackoverflow.com/questions/1212058/how-to-make-a-composite-primary-key-java-persistence-annotation/1252317#1252317
Arthur Ronald F D Garcia
It can be implemented without Entities in JoinedUserRoleId class. Do you know how to... ? If don't, take a look at http://stackoverflow.com/questions/1029745/a-class-that-behaves-like-entity-and-embeddable/1034506#1034506
Arthur Ronald F D Garcia
Thanks. But, I am using JPA.
soontobeared
It can be implemented bu using JPA. Try it
Arthur Ronald F D Garcia