Okay, I'm very new to hibernate. I've got the problem where I'm composing a Set before I save an object graph. After a bit of thinking, and a bit of reading, I dont think anyone else has the solution.
fyi
Its obvious that the hashcode will change if its based on the identity, so persist the hashcode when the object is first created. This will satisfiy java collection contracts aswell as logical identity semantics that are enforced by the database. The identity ID is only assigned once the object is persisted. Before then, if we do an "equals" we can test that we have not been given a DB identity, therefore we use ==.
Now, i'm not too sure about proxies (still a bit new here). When do they get created and used? do they get put into the 2nd level cache? if there is
a proxy, then where is the real object? (since the hashcode is in the database).
(I had a big problem with 2nd level cache not working, thought I was missing something.... didnt mark my classes as @cachable)
Pro: collections work before DB and identity is maintained
Con: extra data column (hashcode). it doesnt need to be indexed like the identity ID/whatever. ALL(?) data always loaded because hashcode and equals have been overided.
Code:
/**
* @hibernate.class table="Cat"
* @hibernate.cache usage="nonstrict-read-write"
*/
class Cat
{
// Synthentic Identity (unique enforced by database)
Integer id;
/**
* @hibernate.id generator-class="native" column="euid"
*/
public Integer getId()
{
return id;
}
public void setId(Integer id)
{
this.id = id;
}
// store this otherwise evil things happen with sets
private int hashcode = super.hashCode();
/**
* @hibernate.property not-null="true"
*/
public int getHashCode()
{
return hashcode;
}
public void setHashCode(int hashcode)
{
this.hashcode = hashcode;
}
public int hashCode()
{
return hashcode;
}
public boolean equals(Object obj)
{
// (1) same instance (creation or same session)
if (obj == this) return true;
// (2) hashcode must match (we honour hashcode from creation)
if (hashcode != obj.hashCode()) return false;
// (3) hashcode might match, but duplicate hashcode the same
if (obj instanceof Cat)
{
Cat le = (Cat)obj;
// (4) if we dont have an id, then we're not persisted and rule (1) is authorative
if (this.id == null || le.getId() == null) return false;
// (5) we've been persisted, check our identifier
if (this.id.intValue() == le.getId().intValue()) return true;
}
// (6) no
return false;
}
}