Hibernate discourages using object keys (such as an ID) as "identity keys", because when Hibernate inserts new object, it will change the ID value, essentially changing object "identity":
When such ID is used (sole or as a part) of object identity, i.e. equals() operator, it must be used as a part of hashCode() as well. As a result, Hibernate insertion will "damage" the set: objects are now in a "wrong" hashCode bucket, and the object in the hash set will not match any more, for example set.contains(copyOfOriginalObject) will lie.
However, in many application scenarios, there is no "business key" choice, and one has to use the "row ID" as an identity key.
One solution to this problem is simply discarding the entire object tree with set(s) containing such objects - and in case you need them again, load such objects into a new session. But that adds a tremendeous overhead - not to mention that in case of interim data 'save', you can not re-populate your application with new data.
It seems that a better solution would be a "repairing" the set after the insert (get the collection of the set objects, clear the set, and then re-insert all items back). However, clearing the set appers to mark the entire set "dirty". In addition, I am afraid that the session cache may contain object cached by the original hashCode - also invalid.
Is Hibernate implementation handling this problem in some way?
Is there something application can do?
Note that where feasible, we do manufacture unique business keys. But in other cases this would add an unacceptable overhead - not to mention that such facility always increases a deadlock opportunity.
Hibernate version: 3.1
|