Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [eclipselink-users] @ManyToOne and hashCode

Ah good old hashCode fun :)

Your stack trace indicates that the NPE is happening in the Kitten
hashCode function when the instance is being placed in the collection.
 You may just have to use more aggressive null checking in your
hashCode method(s).

In my projects I absolutely exclude the version field form the hash
code method.  I exclude the id field as well.  Actually, I only
compute it once, store it in a transient property in the entity and
return the cached value on subsequent calls to hash code.  It looks
and feels convoluted but it works for my projects :)


On Thu, Jun 28, 2012 at 1:12 PM, Noah White <emailnbw@xxxxxxxxx> wrote:
> I have an entity which has a ManyToOne relationship expressed like so:
>
> Kitten:
>
> @ManyToOne(optional = false)
> @JoinColumn(name = "USER_USERID", nullable = false)
> private User owner;
>
>
> On the other side of the relationship I have:
>
> Owner:
>
> @OneToMany(mappedBy = "owner")
> @PrivateOwned
> private Set<Kittens> kittens;
>
> The Kitten class has a hashCode that looks like:
>
> @Override
> public int hashCode() {
>        int result = name.hashCode();
>        result = 31 * result + (group != null ? group.hashCode() : 0);
>        result = 31 * result + owner.hashCode();
>        return result;
> }
>
> I have a unit test that exercises creating some new Kittens. I am seeing NPEs in its hashCode when eclipselink is inside IndirectSet.add.  I'm not sure what part of the eclipselink lifecycle this is or why this is happening since on entity creation the user being assigned the ownership if fetched, assigned, and then the new kitten is added to the owner entities set of kittens. That code looks like this and is inside an EJB method:
>
> Set targetOwnerKittens = owner.getKittens();  //owner is NOT NULL and is a managed object here which was previously looked up with em.find
>
> //kitten was passed into the method and these are just there to insure that id and olversion are clear prior to persist
> kitten.setKittenId(0);   // id - sequence generated long - this just makes sure it is zero prior to persist
> kitten.setOLVersion(0);
>
> kitten.setOwner(owner);
> em.persist(kitten);
> targetOwnerKittens.add(kitten);
>
> The exception I get is below. Could this be an issue with Owner's hash code and Eclipselink trying to look it up from its cache which is keyed off a hashcode that has since changed this it returns a null? The only thing in the Owner hashCode that might change is the olVersion.  Should the optimistic lock field not be included in hashCode?
>
> TIA,
>
> -Noah
>
> java.lang.NullPointerException
>   at com.foo.KittenEntity.hashCode(KittenEntity.java:130)
>   at java.util.HashMap.put(HashMap.java:389)
>   at java.util.HashSet.add(HashSet.java:217)
>   at org.eclipse.persistence.indirection.IndirectSet.add(IndirectSet.java:173)
>   at org.eclipse.persistence.internal.queries.CollectionContainerPolicy.addInto(CollectionContainerPolicy.java:68)
>   at org.eclipse.persistence.internal.queries.ContainerPolicy.mergeChanges(ContainerPolicy.java:1093)
>   at org.eclipse.persistence.mappings.CollectionMapping.mergeChangesIntoObject(CollectionMapping.java:1334)
>   at org.eclipse.persistence.internal.descriptors.ObjectBuilder.mergeChangesIntoObject(ObjectBuilder.java:3409)
>   at org.eclipse.persistence.internal.sessions.MergeManager.mergeChangesOfWorkingCopyIntoOriginal(MergeManager.java:744)
>   at org.eclipse.persistence.internal.sessions.MergeManager.mergeChangesOfWorkingCopyIntoOriginal(MergeManager.java:617)
>   at org.eclipse.persistence.internal.sessions.MergeManager.mergeChanges(MergeManager.java:267)
>   at org.eclipse.persistence.mappings.ObjectReferenceMapping.mergeIntoObject(ObjectReferenceMapping.java:462)
>   at org.eclipse.persistence.internal.descriptors.ObjectBuilder.mergeIntoObject(ObjectBuilder.java:3466)
>   at org.eclipse.persistence.internal.descriptors.ObjectBuilder.mergeChangesIntoObject(ObjectBuilder.java:3400)
>   at org.eclipse.persistence.internal.sessions.MergeManager.mergeChangesOfWorkingCopyIntoOriginal(MergeManager.java:744)
>   at org.eclipse.persistence.internal.sessions.MergeManager.mergeChangesOfWorkingCopyIntoOriginal(MergeManager.java:617)
>   at org.eclipse.persistence.internal.sessions.MergeManager.mergeChanges(MergeManager.java:267)
>   at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.mergeChangesIntoParent(UnitOfWorkImpl.java:3254)
>   at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.mergeChangesIntoParent(RepeatableWriteUnitOfWork.java:370)
>   at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.mergeClonesAfterCompletion(UnitOfWorkImpl.java:3386)
>   at org.eclipse.persistence.transaction.AbstractSynchronizationListener.afterCompletion(AbstractSynchronizationListener.java:213)
>   at org.eclipse.persistence.transaction.JTASynchronizationListener.afterCompletion(JTASynchronizationListener.java:79)
>   at com.sun.enterprise.transaction.JavaEETransactionImpl.commit(JavaEETransactionImpl.java:537)
>   at com.sun.enterprise.transaction.JavaEETransactionManagerSimplified.commit(JavaEETransactionManagerSimplified.java:855)
>   at com.sun.ejb.containers.BaseContainer.completeNewTx(BaseContainer.java:5136)
>   at com.sun.ejb.containers.BaseContainer.postInvokeTx(BaseContainer.java:4901)
>   at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:2045)
>   at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:1994)
>   at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:222)
>   at com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate.invoke(EJBLocalObjectInvocationHandlerDelegate.java:88)
> _______________________________________________
> eclipselink-users mailing list
> eclipselink-users@xxxxxxxxxxx
> https://dev.eclipse.org/mailman/listinfo/eclipselink-users


Back to the top