我在 and 之间有@OneToMany 关系,并且在UserDomain
and之间PartageDomain
有相同的关系。有一个由和组成的复合键。当我尝试在表中保存记录时,出现此异常:FileDomain
PartageDomain
PartageDomain
UserDomain
FileDomain
PartageDomain
Caused by: java.lang.NullPointerException
at org.hibernate.type.AbstractType.getHashCode(AbstractType.java:136)
at org.hibernate.type.AbstractType.getHashCode(AbstractType.java:144)
at org.hibernate.type.EntityType.getHashCode(EntityType.java:312)
at org.hibernate.type.ComponentType.getHashCode(ComponentType.java:212)
at org.hibernate.engine.EntityKey.generateHashCode(EntityKey.java:126)
at org.hibernate.engine.EntityKey.<init>(EntityKey.java:70)
at org.hibernate.engine.StatefulPersistenceContext.getDatabaseSnapshot(StatefulPersistenceContext.java:263)
at org.hibernate.engine.ForeignKeys.isTransient(ForeignKeys.java:212)
at org.hibernate.event.def.AbstractSaveEventListener.getEntityState(AbstractSaveEventListener.java:535)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:103)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:535)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:527)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:523)
at com.stage.dao.PartageDaoImpl.add(PartageDaoImpl.java:39)
at com.stage.service.PartageServiceImpl.add(PartageServiceImpl.java:33)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:309)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy42.add(Unknown Source)
at com.stage.beans.UserManagedBean.saveUserRights(UserManagedBean.java:234)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.sun.el.parser.AstValue.invoke(AstValue.java:234)
at com.sun.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:297)
at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:102)
... 23 more
我做了一些研究,发现这个异常来自三个案例:
a)我们有一个复合键,其中一个键的属性是另一个持久类的 FK。
b) 另一个持久类有一个 ID 字段,其值正在生成。
c) 另一个持久类的实例是瞬态的(还没有 ID)
文档中没有说明我们如何解决这些问题,但是按照 hibernate 文档中的建议,我重写了 equals() 和 hashCode() 以实现复合标识符相等。并且还实现了Serializable,但它总是不起作用。因此,如果有人对我的问题的根源有所了解;
正如上面评论中所建议的,我将 hashcode 方法添加到我的UserDomain
andFileDomain
中,getId
andgetLink
方法获取相应的对象 ID。
部分userDomain
public class UserDomain implements Serializable {
....
@OneToMany (cascade=CascadeType.ALL)
private Collection<PartageDomain> partageDomain = new ArrayList<PartageDomain>();
public Collection<PartageDomain> getPartageDomain() {
return partageDomain;
}
public void setPartageDomain(Collection<PartageDomain> partageDomain) {
this.partageDomain = partageDomain;
}
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
UserDomain that = (UserDomain) o;
if (getId() != null ? !getId().equals(that.getId()) : that.getId() != null) return false;
return true;
}
public int hashCode() {
return (getId() != null ? getId().hashCode() : 0);
}
部分FileDomain
public class FileDomain implements Serializable {
...
@OneToMany
private Collection<PartageDomain> partageDomain = new ArrayList<PartageDomain>();
public Collection<PartageDomain> getPartageDomain() {
return partageDomain;
}
public void setPartageDomain(Collection<PartageDomain> partageDomain) {
this.partageDomain = partageDomain;
}
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
FileDomain that = (FileDomain) o;
if (getLink() != null ? !getLink().equals(that.getLink()) : that.getLink() != null) return false;
return true;
}
public int hashCode() {
return (getLink() != null ? getLink().hashCode() : 0);
}
部分PartageDomain
public class PartageDomain implements Serializable {
@EmbeddedId
private PartageId partageId = new PartageId();
public PartageId getPartageId() {
return partageId;
}
public void setPartageId(PartageId partageId) {
this.partageId = partageId;
}
...
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PartageDomain that = (PartageDomain) o;
if (getPartageId() != null ? !getPartageId().equals(that.getPartageId()) : that.getPartageId() != null) return false;
return true;
}
public int hashCode() {
return (getPartageId() != null ? getPartageId().hashCode() : 0);
}
PartageId
班级:
@Embeddable
public class PartageId implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
@ManyToOne
private FileDomain fileDomain;
@ManyToOne
private UserDomain userDomain;
public FileDomain getFileDomain() {
return fileDomain;
}
public void setFileDomain(FileDomain fileDomain) {
this.fileDomain = fileDomain;
}
public UserDomain getUserDomain() {
return userDomain;
}
public void setUserDomain(UserDomain userDomain) {
this.userDomain = userDomain;
}
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PartageId that = (PartageId) o;
if (fileDomain != null ? !fileDomain.equals(that.fileDomain) : that.fileDomain != null) return false;
if (userDomain != null ? !userDomain.equals(that.userDomain) : that.userDomain != null)
return false;
return true;
}
public int hashCode() {
int result;
result = (fileDomain != null ? fileDomain.hashCode() : 0);
result = 31 * result + (userDomain != null ? userDomain.hashCode() : 0);
return result;
}
}