以下是我的某个实体的复合主键。
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方法实现应该有点困惑。如何比较两个复合主键?
我也欢迎对我的代码的其他部分发表任何评论。
答案 0 :(得分:7)
将实体存储为主键并不是一个好主意。使用查询语言时存在一些限制,而JPA 1.0不支持。除此之外,不需要使用实体作为主键。想一想。如果你想,请特别关注以下问题
A class that behaves like @Entity and @Embeddable
您将看到不必使用实体作为主键。
而不是
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)
无论如何,部分提到了:
equals
方法时,您应使用instanceof
以允许与子类进行比较。如果Hibernate延迟加载一对一或多对一关系,那么您将拥有该类的代理而不是普通类。代理是子类。比较班级名称会失败
从技术上讲,您应该遵循Liskovs Substitution Principle并忽略对称性。name.equals(that.name)
而不是name.equals(that.getName())
。如果是代理,第一个将失败。