Thread:
 Summed up 
 obsidian   22 Jul 2007, 00:33 

Comment
Prev. thread 
 Next thread
 
Prev. posting 
 Next posting
From: obsidian (22 Jul 2007, 00:33) Replies: 0, Views: 2657
Subject: Summed up
The real problem, as others put it, is that the hibernate ID is the only
real candidate for equals()/hashCode(), but most people generate them in
the DB, so don't have it until they've saved, by which point it's
usually too late. General code doesn't like distinguishing between
created vs. loaded objects. Wanting to mix the two types in a
collection, including one that can survive across Sessions, is quite an
ordinary, even basic desire IMO. 

It seems like the official advice is to fake out equals()/hashCode()
with data that's highly unlikely to meet the contract of those methods.
Some people are lucky and have "business key" fields that change less
often than their collections live for. Most people aren't lucky. Or if
they are today, who can guarantee what someone may change tomorrow? The
classic example of a business key is "name" or a "username" or whatever,
yet names and usernames change all the time (i.e. it's an editor and the
name/username's not immutable), and that makes it a fundamentally wrong
thing to build equals/hashcode on. Using more mutable properties at once
makes this problem worse, not better. If you've got a property that
really doesn't ever change, why did you bother making a separate ID
column anyway?

Don't get me wrong. I can see why this "business key" approach would
work for some people, sometimes. I would simply caution against it far
more strongly than the hibernate documentation does. Let's call it what
it is. It's usually going to be a risky shortcut. And when you lose at
identifer roulette, you will not always get a pretty error message to
tell you. 

I'd have laid out the solutions differently:

1) Have your equals/hashCode methods work off of IDs, and use an ID
generation strategy that allows you to know the ID when the object is
created. 

	1a) UUID, or something more exotic. Everyone hates these. UUIDs are too
big, and annoying if you share your tables with non-hibernate apps.
They're also just plain uncommon, which makes them seem spooky to most
people. 

	1b) Keep your sequences, and use an API, rather than new, to create
your entities, have it hit the DB to get the identifier in advance (i.e.
run the sequence). Nobody seems to like this either, because you pay a
(by comparison to the normal case) staggering IO cost to instantiate an
object. 

	See also things like: http://www.devx.com/Java/Article/30396

2) Try this dangerous fakery with "business keys." I hope you have some,
and that you don't change them, nor does anyone else who comes along
later doing things you didn't anticipate today. 

3) Get scared away and try not to need equals()/hashCode() after all.
Hibernate doesn't, according to Gavin. (Nice work, by the way.) 

I'll say this, it seems clear this is not a Hibernate problem, except
inasmuch as Hibernate makes your life so easy it can obscure certain
immutable underlying facts about life with an RDBMS. Any system managing
sometimes-new/sometimes-persistent objects will have to find an answer
for this.
Prev. thread 
 Next thread
 
Prev. posting 
 Next posting
© Copyright 2006, Red Hat Middleware, LLC. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc. [Privacy Policy]