我在UserDomain
和PartageDomain
之间存在@OneToMany关系,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,但它始终不起作用。所以,如果有人对我的问题的根源有所了解;
正如上面的评论所述,我将哈希码方法添加到UserDomain
和FileDomain
,getId
和getLink
方法获取相应的对象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;
}
}