Hibernate - 具有复合键哈希码异常的OneToMany

时间:2012-08-04 23:52:49

标签: java hibernate java-ee jpa persistence

我在UserDomainPartageDomain之间存在@OneToMany关系,FileDomainPartageDomain之间的关系相同。 PartageDomain具有由UserDomainFileDomain组成的复合键。 当我尝试在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,但它始终不起作用。所以,如果有人对我的问题的根源有所了解;

正如上面的评论所述,我将哈希码方法添加到UserDomainFileDomaingetIdgetLink方法获取相应的对象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;
        }
    }

0 个答案:

没有答案