I'm trying to figure out what's wrong with this approach, given my particular usage patterns:
@Entity
public class DomainObject {
@Id // + sequence generator
private Long id;
@Override
public boolean equals(Object o) {
// bunch of other checks omitted for clarity
if (id != null) {
return id.equals(o.getId());
}
return super.equals(o);
}
@Override
public int hashCode() {
if (id != null) {
return id.hashCode();
}
return super.hashCode();
}
I've read several posts on the subject and it sounds like you don't want to use a DB-generated sequence value in equals/hashCode because they won't be set until the objects are persisted and you don't want disparate transient instances to all be equal, or the persistence layer itself might break.
But is there anything wrong with falling back to the default Object equals/hashCode (instance equality) for transient objects and then using the generated @Id when you have it?
The worst thing I can think of is, a transient object can't ever be equal to a persistent object, which is fine in my use case - the only time I'm ever putting objects in collections and want contains
to work, all the objects are already persistent and all have IDs.
However, I feel like there's something else wrong in a really subtle, non-obvious way deep in the persistence layer but I can't quite figure out what.
The other options don't seem that appealing either:
doing nothing and living with instance equality (default Object.equals): works great for most of my entities, but getting tired of workarounds for the handful of cases when I want a collection with a mix of detached entities (e.g., session scope) and "live" ones from current transaction
using a business key: I have clear natural keys but they're mutable, and this would have some of the same problems as above (hashCode stability if object changes)
using a UUID - I know that will work, but feels wrong to pollute the DB with artifacts to support java.util collections.
See also: