Based on various bad experiences my rule of thumb as a Java programmer is to only implement equals()
and hashCode()
on immutable objects, where two instances of the object really are interchangeable.
Basically I want to avoid situations like the HashMap
key problem in that link, or like the following:
- Get a thing with a certain identity.
- Modify it.
- Add it to a set.
- (later) Get another thing with the same identity.
- Modify it.
- Add it to the same set.
- Fail to notice that this add doesn't actually happen, since the set thinks the thing is already there.
- Do something with the things in the set.
- Fail to notice that the change from step (5) is ignored, and we still have the state from step (2).
And by and large over the course of my Java career I haven't found a lot of use for equals()
except for (1) value objects and (2) putting things into collections. I've also found that immutability + copy-and-modify constructors/builders is generally a much happier world than setters. Two objects might have the same ID and might represent the same logical entity, but if they have different data -- if they represent snapshots of the conceptual entity at different times -- then they're not equal()
.
Anyway, I'm now in a Hibernate shop, and my more Hibernate-savvy colleagues are telling me this approach isn't going to work. Specifically, the claim seems to be that in the following scenario --
- Hibernate loads a thing from the database -- we'll call it instance
h1
. - This thing is marshaled and sent somewhere via a web service.
- The web service client fiddles with it and sends a modified version back.
- The modified version is unmarshalled on the server -- we'll call it instance
h4
. - We want Hibernate to update the database with the modifications.
-- unless h1.equals(h4)
(or perhaps h4.equals(h1)
, I'm not clear, but I would hope it's transitive anyway so whatever), Hibernate will not be able to tell that these are the same thing, and Bad Things Will Happen.
So, what I want to know:
- Is this true?
- If so, why? What is Hibernate using
equals()
for? - If Hibernate needs
h1
andh4
to be equal, how does it (and how do we) keep track of which one is the modified version?
Note: I've read Implementing equals() and hashCode() in the Hibernate docs and it doesn't deal with the situation I'm worried about, at least directly, nor does it explain in any detail what Hibernate really needs out of equals()
and hashCode()
. Neither does the answer to equals and hashcode in Hibernate, or I wouldn't have bothered to post this.