Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

@IdClass JPA Annotation

Tags:

jpa

Here is 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.

like image 973
soontobeared Avatar asked Sep 23 '09 21:09

soontobeared


1 Answers

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 UserGroupId getId() {
        return this.id;
    }

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

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

regards,

like image 59
Arthur Ronald Avatar answered Oct 14 '22 02:10

Arthur Ronald