[hibernate-issues] [Hibernate-JIRA] Commented: (HHH-3799) PersistentSet does not honor hashcode/equals contract when loaded eagerly

David Tarico (JIRA) noreply at atlassian.com
Thu Feb 23 20:43:49 EST 2012


    [ https://hibernate.onjira.com/browse/HHH-3799?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=45667#comment-45667 ] 

David Tarico commented on HHH-3799:
-----------------------------------

In my scenario, objects have a name, which in the database is a non-nullable field and has a unique constraint, but it's not the primary key.  The PK is an auto-generated integer.   I need to fetch an already persisted set, and add a new item if it doesn't already exist.

It seems natural to make equals/hashCode use the name for identity, and then use a set to avoid duplicates.

The problem with your proposed hashCode is that it assumes either all the entities in the collection are persistend, or all are new and don't have an ID.

Assume we have two objects, FOO and BAR, both which have the same name.  FOO is persisted and in the set, but BAR is new and not yet in the set.  If I do set.contains(BAR) it will return false, and if I do set.add(BAR) it will succesfully add BAR and have both FOO and BAR in the set, causing a unique constraint violation when persisted.

Using a buisness key such as name is a common practice and is even the example given in Java Persistence with Hibernate in the section on "Object identity and equality" where they have a User with this example of hashCode:

public int hashCode() {
	return username.hashCode();
}

Our hashCode actually looks like

public int hashCode() {
	if (name == null) {
		return 0;
	}
	else {
		return name.hashCode();
	}
}

It took a couple developers more than a day to figure out why the set was not finding the elements that were already in it and allowing the addition of duplicates.  We had to work around the problem by using a list instead of a set, and adding our own code to check for duplicates before adding an item.  But in my opinion, that makes PersistentSet broken and unusable because it violates the contract of how hashCode() is expected to behave.



> PersistentSet does not honor hashcode/equals contract when loaded eagerly
> -------------------------------------------------------------------------
>
>                 Key: HHH-3799
>                 URL: https://hibernate.onjira.com/browse/HHH-3799
>             Project: Hibernate ORM
>          Issue Type: Bug
>          Components: core
>    Affects Versions: 3.3.1, 3.5.1
>            Reporter: Igor Vaynberg
>            Assignee: Gail Badner
>         Attachments: test.zip
>
>
> when persistent set is loaded eagerly in some situations it calls hashcode on its items before their field values are populated and then uses this incorrect hashcode to store them in the set. this makes set items inaccessible by any collection items that rely on hashcode such as contains(), remove(), etc.
> attached is a simple maven test project that reproduces the error, unzip and mvn test to run the test.

--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira

        


More information about the hibernate-issues mailing list