@IdClass JPA Annotation

时间:2009-09-23 21:01:25

标签: 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方法实现应该有点困惑。如何比较两个复合主键?

我也欢迎对我的代码的其他部分发表任何评论。

2 个答案:

答案 0 :(得分: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通过使用equals实现检查实体是否在持久化上下文中)。所以你可以按照

实现
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

的问候,

答案 1 :(得分:1)

无论如何,部分提到了:

  1. 在实施equals方法时,您应使用instanceof 以允许与子类进行比较。如果Hibernate延迟加载一对一或多对一关系,那么您将拥有该类的代理而不是普通类。代理是子类。比较班级名称会失败 从技术上讲,您应该遵循Liskovs Substitution Principle并忽略对称性。
  2. 下一个陷阱是使用name.equals(that.name)而不是name.equals(that.getName())。如果是代理,第一个将失败。
  3. http://www.laliluna.de/jpa-hibernate-guide/ch06s06.html