@EqualsAndHashCode for Hibernate

911 views
Skip to first unread message

Rinaldo

unread,
Mar 9, 2012, 1:56:25 PM3/9/12
to Project Lombok
First of all, I would like to congratulate Project Lombok. It's very
helpful and make our codes cleaner. :)

I was looking at the EqualsAndHashCode that is generated by lombok
nowadays, and there are 2 things that we do and lombok doesn't.
In our Hibernate Entities we like to use only ID for
EqualsAndHashCode, since that's what ID is supposed to do, identify
the entity.

Equals:

When overriding equals, we check if both ID's are null. If they are
null, it means it is a new Entity that hasn't been persisted yet
(otherwise it would have an ID assigned), so we compare the objects
(objectA == objectB). If they are different objects, return false.

HashCode:

When overriding hashCode, we check if ID is null. If is is null, then
we call super.hashCode().

I would like to know if Lombok plans on implementing something like
that, since it is really nice to be able to use only ID for Equals and
Hash Code.

Thanks. :)

eric.giese

unread,
Mar 12, 2012, 6:41:03 AM3/12/12
to Project Lombok
Such an implementation is handmade and, I guess, breaks the contract
of equals and hashcode.
If you are doing such a thing, then it would not be a good Idea to use
a tool like lombok to generate this code, as it is a custom
implementation which needs attention, and not generic java-typical
boilerplate.

Matthew Jaggard

unread,
Mar 12, 2012, 6:44:46 AM3/12/12
to project...@googlegroups.com
Also, what's the benefit? Saving a few CPU cycles in comparing the other fields?


--
You received this message because you are subscribed to the Google
Groups group for http://projectlombok.org/

To post to this group, send email to project...@googlegroups.com
To unsubscribe from this group, send email to
project-lombo...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/project-lombok?hl=en

Roel Spilker

unread,
Mar 12, 2012, 8:29:12 AM3/12/12
to project...@googlegroups.com
Well, it does not break the contract, since it the contract is very loose regarding state changes :-( The javadoc of Object#hashCode states "Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified."

Roel Spilker

unread,
Mar 12, 2012, 8:34:21 AM3/12/12
to project...@googlegroups.com
Possibly the best solution is having a common superclass for all your entities and have that implement the equals and hashcode the way you want. Then you can use @EqualsAndHashCode(callsuper=true, of="")

Fabrizio Giudici

unread,
Mar 12, 2012, 8:40:35 AM3/12/12
to project...@googlegroups.com, Roel Spilker
On Mon, 12 Mar 2012 13:34:21 +0100, Roel Spilker <r.sp...@gmail.com>
wrote:

> Possibly the best solution is having a common superclass for all your
> entities and have that implement the equals and hashcode the way you
> want.
> Then you can use @EqualsAndHashCode(callsuper=true, of="")

... or, better, a @Delegate.

--
Fabrizio Giudici - Java Architect, Project Manager
Tidalwave s.a.s. - "We make Java work. Everywhere."
fabrizio...@tidalwave.it
http://tidalwave.it - http://fabriziogiudici.it

Rinaldo

unread,
Mar 13, 2012, 9:54:58 AM3/13/12
to project...@googlegroups.com
Well, not actually.

The problem is that, in our model, most entities don't have other unique atributes to indentify them. Almost all attributes can be changed by the user, and we deal a lot with collections in the view layer. Using other attributes to compare the entities would result in duplicated entries in our lists/sets.


Em segunda-feira, 12 de março de 2012 07h44min46s UTC-3, Mat Jaggard escreveu:
Also, what's the benefit? Saving a few CPU cycles in comparing the other fields?

On 12 March 2012 10:41, eric.giese <eric...@googlemail.com> wrote:
Such an implementation is handmade and, I guess, breaks the contract
of equals and hashcode.
If you are doing such a thing, then it would not be a good Idea to use
a tool like lombok to generate this code, as it is a custom
implementation which needs attention, and not generic java-typical
boilerplate.

--
You received this message because you are subscribed to the Google
Groups group for http://projectlombok.org/

To post to this group, send email to project-lombok@googlegroups.com

To unsubscribe from this group, send email to
Message has been deleted

Rinaldo

unread,
Mar 13, 2012, 10:01:07 AM3/13/12
to project...@googlegroups.com
I don't see why/where it breaks the contract. Can you explain?

As to it not being generic, I agree. I was trying to suggest maybe "another version" of @EqualsAndHashCode, perhaps uniquely made for Hibernate.

I don't know how many people that uses Hibernate are interested in Lombok, or how much is Project Lombok interested in Hibernate, that's why I just asked. :)

Rinaldo

unread,
Mar 13, 2012, 10:02:02 AM3/13/12
to project...@googlegroups.com
That and @Delegate are actually pretty good suggestions. Thank you both. :)

Reinier Zwitserloot

unread,
Mar 13, 2012, 11:55:58 AM3/13/12
to project...@googlegroups.com
@Delegate won't work, because all j.l.Object methods are never delegated (otherwise, delegating also means you get that object's toString() and such, bad idea). Unfortunately, that means that even if you WANT to delegate some of j.l.Object's own, you can't.

For objects that have no unid, i.e. that haven't been added to the DB yet, what are you going to use for hashCode? Technically it doesn't matter much (even if hashCodes are the same the objects don't have to be equal), but it would be nice if hashCode and equals work in a similar fashion.

You can use @EqualsAndHashCode(of="unid"), but then you won't get the intended behaviour when unid is null (2 instances, both of whom have a null unid, would be considered equal).

Other than that, I don't know - you'd indeed need a special hibernate-specific version.



 --Reinier Zwitserloot



--
You received this message because you are subscribed to the Google
Groups group for http://projectlombok.org/
 
To post to this group, send email to project...@googlegroups.com

To unsubscribe from this group, send email to

Fabrizio Giudici

unread,
Mar 13, 2012, 12:06:22 PM3/13/12
to project...@googlegroups.com, Reinier Zwitserloot
On Tue, 13 Mar 2012 16:55:58 +0100, Reinier Zwitserloot
<rei...@zwitserloot.com> wrote:

> @Delegate won't work, because all j.l.Object methods are never delegated
> (otherwise, delegating also means you get that object's toString() and
> such, bad idea). Unfortunately, that means that even if you WANT to
> delegate some of j.l.Object's own, you can't.

You caught me.

eric.giese

unread,
Mar 14, 2012, 6:13:37 AM3/14/12
to Project Lombok
On 13 Mrz., 15:01, Rinaldo <rinald...@gmail.com> wrote:
> I don't see why/where it breaks the contract. Can you explain?

Well, I'm not sure. I guess it won't and I'm incorrect here. :-) I am
just a bit worried about your implementation, since it does not follow
the general guidelines, which state that equals compares an object by
its reference and then simply non-transient field-by-field.
I have experimented with such hibernate-specific equals
implementations as well in the past, but after some time I came to the
conclusion that the only useful equals/hashcode implementation for
hibernate entities is a == b.

The problem is that JPA/Hibernate-DAOs are very complex and
comparisons and equality really depend on the context you are in. Even
the id has some pitfalls considering new entities and null - thats why
you included the special "null"-rule. Allowing ONLY reference equality
protects you from even more unexpected behaviors and avoids dangerous
side-effects like the prominent "HashSet + MutableField"-Defect:
http://blog.mgm-tp.com/2012/03/hashset-java-puzzler/

Like with compareTo and Comparator, I tend to use an external class
whenever I do something thats not just a "plain old field-by-field"-
equals.
Reply all
Reply to author
Forward
0 new messages