-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 19 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Set does not contained retrieved version of persisted object
PostPosted: Tue Jul 19, 2005 6:12 pm 
Newbie

Joined: Tue Jul 19, 2005 5:58 pm
Posts: 8
Location: Minneapolis
OK, I RTFM'd, made some adjustments and still have this problem. Code to follow.

I create a persistable object.
I add it to a set.
I assert the set contains the object which passes.
I save the object.
I commit the transaction, close the session and reopen the session.

I retrieve the Permission from the db into a new reference.
I compare the hashcodes of these and call equals on both objets.
These tests pass so the retrieved object equals the original object in every way except they are separate instances.

I assert the original object is contained in the Set. This passes.
I assert the retrieved object is contained in the Set. This fails.


Code:
        Permission permission = new Permission( "test permission " + uniqueLongValue() );
        Set s = new HashSet();
        s.add( permission );
        assertTrue(s.contains( permission ));
        session.save( permission );
        commitTransactionCloseAndReopenSession();
       
        Permission retrievedPermission = (Permission )session.get(Permission.class, permission.getId());
        assertEquals(permission.hashcode(), retrievedPermission.hashcode());
       
        assertEquals(permission, retrievedPermission);
        assertEquals(retrievedPermission, permission);
       
        assertFalse(permission == retrievedPermission);
       
        assertTrue(s.contains( permission ));
        assertTrue(s.contains( retrievedPermission ));   


Pleaseandthankyou


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 19, 2005 6:38 pm 
Expert
Expert

Joined: Wed Apr 06, 2005 5:03 pm
Posts: 273
Location: Salt Lake City, Utah, USA
Just a guess, but it might be that you have a generated ID, and use that ID in equals/hashCode. Maybe post your hbm and POJO.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 19, 2005 6:52 pm 
Newbie

Joined: Tue Jul 19, 2005 5:58 pm
Posts: 8
Location: Minneapolis
Here's the code. We're using xdoclet to generate the hbm files so the mappings are with the code but I included the resulting HBM at the bottom also. The equals and hashcode are built using the value attribute which is a business key and is passed at creation.

Code:

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.collections.set.UnmodifiableSet;
import org.hibernate.HibernateException;

import com. .ime.context.IMEContext;
import com. .ime.exception.IMEErrorCode;
import com. .ime.exception.IMEException;

/**
* @hibernate.class table="PERMISSION"
* @hibernate.discriminator column="PERMISSION_TYPE" type="java.lang.String"
*
* @hibernate.query name="findAllPermissions" query="from Permission p"
*
* @hibernate.query name="findPermissionByValue" query="from Permission p where
*                  p.value = :value"

*/
public abstract class AbstractPermission
{

    public static final String ID = "permissionID";
    public static final String PERMISSION = "permission";
    public static final String PERMISSIONS = "permissions";

    private String value;
    private Long id;


    protected AbstractPermission()
    {
    }

    protected AbstractPermission( String value )
    {
        setValue( value );
    }

    /**
     * @hibernate.property column = "value" unique = "true" not-null = "true"
     *                     length="255"
     * @return value
     */
    protected String getValue()
    {
        return this.value;
    }

    private void setValue( String value )
    {
        this.value = value;
    }


    /**
     * @hibernate.id generator-class="native" column = "PERMISSION_ID" name="id"
     * @return id
     */
    public Long getId()
    {
        return this.id;
    }

    private void setId( Long id )
    {
        this.id = id;
    }

    public String toString()
    {
        return getValue();
    }

    public boolean equals( Object o )
    {
        if( o == null )
        {
            return false;
        }
        if( o == this )
        {
            return true;
        }
        if( !(o instanceof AbstractPermission) )
        {
            return false;
        }
        return ((AbstractPermission)o).getValue().equals( this.getValue() );
    }

    public int hashcode()
    {
        int result = 17;
        result = result * 37 + getValue().hashCode();
        return result;
    }


}


/**
* @hibernate.subclass table="PERMISSION" discriminator-value="userpermission"

*/
public class Permission extends AbstractPermission
{
    public static final Permission USER_PERMISSION_1 = new Permission( "UserPermission1" );


    protected Permission()
    {

    }

    protected Permission( String value )
    {
        super( value );
    }

}


Code:
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">

<hibernate-mapping
>
    <class
        name="com. .ime.domain.user.AbstractPermission"
        table="PERMISSION"
        dynamic-update="false"
        dynamic-insert="false"
        select-before-update="false"
        optimistic-lock="version"
    >

        <id
            name="id"
            column="PERMISSION_ID"
            type="java.lang.Long"
        >
            <generator class="native">
              <!-- 
                  To add non XDoclet generator parameters, create a file named
                  hibernate-generator-params-AbstractPermission.xml
                  containing the additional parameters and place it in your merge dir.
              -->
            </generator>
        </id>

        <discriminator
            column="PERMISSION_TYPE"
            type="java.lang.String"
        />

        <property
            name="value"
            type="java.lang.String"
            update="true"
            insert="true"
            access="property"
            column="value"
            length="255"
            not-null="true"
            unique="true"
        />

        <!--
            To add non XDoclet property mappings, create a file named
                hibernate-properties-AbstractPermission.xml
            containing the additional properties and place it in your merge dir.
        -->
        <subclass
            name="com. .ime.domain.user.Permission"
            dynamic-update="false"
            dynamic-insert="false"
            discriminator-value="userpermission"
        >
       <!--
               To add non XDoclet property mappings, create a file named
                hibernate-properties-Permission.xml
      containing the additional properties and place it in your merge dir.
       -->

        </subclass>
        <subclass
            name="com. .ime.domain.user.AdminPermission"
            dynamic-update="false"
            dynamic-insert="false"
            discriminator-value="adminpermission"
        >
       <!--
               To add non XDoclet property mappings, create a file named
                hibernate-properties-AdminPermission.xml
      containing the additional properties and place it in your merge dir.
       -->

        </subclass>

    </class>

        <query name="findAllPermissions"><![CDATA[
            from Permission p
        ]]></query>
        <query name="findPermissionByValue"><![CDATA[
            from Permission p where p.value = :value
        ]]></query>

</hibernate-mapping>


Top
 Profile  
 
 Post subject: Update
PostPosted: Wed Jul 20, 2005 10:09 am 
Newbie

Joined: Tue Jul 19, 2005 5:58 pm
Posts: 8
Location: Minneapolis
If I change the Collection in the test to an ArrayList it works.

This would seem to imply the issue is due to a hashcode difference as the difference in the contains implementations is the use of HashCode in the Set. But I've already asserted the hashcodes of the two objects are equal.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jul 20, 2005 3:18 pm 
Beginner
Beginner

Joined: Wed May 04, 2005 5:17 am
Posts: 40
I must be going mad, but I can't figure out how you've managed to do this ;)

Can you print out the values of hashCode and getValue on both objects.


Top
 Profile  
 
 Post subject: hashcodes and values
PostPosted: Wed Jul 20, 2005 5:21 pm 
Newbie

Joined: Tue Jul 19, 2005 5:58 pm
Posts: 8
Location: Minneapolis
permission.hashcode(): -508204249
permission.getValue(): test permission 1121894459888
retrievedPermission.hashcode(): -508204249
retrievedPermission.getValue(): test permission 1121894459888


Top
 Profile  
 
 Post subject: Re: hashcodes and values
PostPosted: Wed Jul 20, 2005 5:50 pm 
Expert
Expert

Joined: Mon Feb 14, 2005 12:32 pm
Posts: 609
Location: Atlanta, GA - USA
martynspeck wrote:
permission.hashcode(): -508204249
permission.getValue(): test permission 1121894459888
retrievedPermission.hashcode(): -508204249
retrievedPermission.getValue(): test permission 1121894459888


Set's don't allow duplicates.


Top
 Profile  
 
 Post subject: Re: hashcodes and values
PostPosted: Wed Jul 20, 2005 5:54 pm 
Newbie

Joined: Tue Jul 19, 2005 5:58 pm
Posts: 8
Location: Minneapolis
pksiv wrote:

Set's don't allow duplicates.


Yes, I know that.

The question is how is it possible for a set which contains Object a to return false to contains(b) when b.equals(a) && a.equals(b) && a.hashcode() == b.hashcode()


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jul 21, 2005 4:54 am 
Beginner
Beginner

Joined: Wed May 04, 2005 5:17 am
Posts: 40
Can you step through the implementation of the Set you are using during unit testing, and see why it returns false?


Top
 Profile  
 
 Post subject: Re: hashcodes and values
PostPosted: Thu Jul 21, 2005 11:13 am 
Expert
Expert

Joined: Sat Jan 17, 2004 2:57 pm
Posts: 329
Location: In the basement in my underwear
martynspeck wrote:
pksiv wrote:

Set's don't allow duplicates.


Yes, I know that.

The question is how is it possible for a set which contains Object a to return false to contains(b) when b.equals(a) && a.equals(b) && a.hashcode() == b.hashcode()


Definitely, if the hashcode changes in any way after the Object is added to the Set, the contains will fail.

The Set uses an underlying HashMap to store the values based on the original HashCode. So if your item has a hash code of 10000000 and it changes to 5934757 after you put it in the Set the above condition you posted will hold true but contains(b) will return false.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jul 21, 2005 11:19 am 
Beginner
Beginner

Joined: Wed May 04, 2005 5:17 am
Posts: 40
But the hashCode doesn't change does it?


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jul 21, 2005 11:27 am 
Newbie

Joined: Tue Jul 19, 2005 5:58 pm
Posts: 8
Location: Minneapolis
After the object is added to the set and I've retrieved a copy from the database I assert the equality of their hashcodes and print the hashcodes which I posted above.

At the time of the call to contains their hashcodes are equal.

I've tried tracing into the HashSet contains method but cannot see the values of the variables in there.


Top
 Profile  
 
 Post subject: Re: hashcodes and values
PostPosted: Thu Jul 21, 2005 12:10 pm 
Newbie

Joined: Wed Jul 20, 2005 5:41 pm
Posts: 2
VampBoy wrote:


The Set uses an underlying HashMap to store the values based on the original HashCode. So if your item has a hash code of 10000000 and it changes to 5934757 after you put it in the Set the above condition you posted will hold true but contains(b) will return false.


I was thinking the same thing you were, but strictly looking at the code above, the hashCode function is based on the value property, which apparently doesn't change anywhere between when he creates his object, stores it, and checks it again. So in theory, the object has the same hashCode before the save and after the save and after the retrieval. Maybe you can check this for us martynspeck just to make sure. If hashCode is the same at all stages, then I'm stumped (which based on the code above, is what I'd expect). If it changes, theres your problem, you just need to figure out why.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jul 21, 2005 12:15 pm 
Newbie

Joined: Tue Jul 19, 2005 5:58 pm
Posts: 8
Location: Minneapolis
I'll check for that. I've got a demo this afternoon which doesn't depend on this so I'll post after that.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jul 21, 2005 12:36 pm 
Newbie

Joined: Tue Sep 28, 2004 7:14 pm
Posts: 7
I am seeing similar behavior. I am using hibernate 3.0.5. I too am having issues using contains against a transient object. Normally, this ends up being a bug in my implementation. I too iterated through and found that the hashcodes match and equals returns true when compared against the equivalent object in the set. I verified that the objects in the set have distinct hashcodes and are not equivalent.

Finally, I implemented the test below. It doesn't prove that there isn't a bug in my implementation, but it does suggest that there is difference in behavior between PersistentSet and HashSet.

Here is a snippet of the code and output.

Code:
//
//where coll2 is a persistent set and item is a transient entity
//
System.out.println("Coll2:  " + coll2.getClass().getName());
System.out.println("Coll2 contains item:  " + coll2.contains(item));
Set hashSet = new HashSet(coll2);
System.out.println("HashSet contains item:  " + hashSet.contains(item));


Code:
//output
Coll2:  org.hibernate.collection.PersistentSet
Coll2 contains item:  false
HashSet contains item:  true


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 19 posts ]  Go to page 1, 2  Next

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
cron
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.