Can I use the equals/hashCode generated by Ebean?

112 views
Skip to first unread message

Onilton Maciel

unread,
Aug 8, 2017, 4:28:37 PM8/8/17
to Ebean ORM
Looking at debug logs of Play/Ebean I noticed ebean-enhance adds equals and hashCode to my classes extending the Model class.

Can I use those methods in my code, or is this reserved for some ebean specific issue?

Also, is there any problema for me in overriding equals and hashCode (and not using ebean's generated one) in my own class?

Thanks,

Rob Bygrave

unread,
Aug 9, 2017, 6:06:27 AM8/9/17
to ebean@googlegroups
Can I use those methods in my code

Yes, it is intended to provide a safe and decent hashcode()/ equals() implementation that we can use in application code.  If you don't use/invoke a hashCode() call prior to the beans being loaded with an Id value ... it will work nicely.  It can't do better and be safe (not change the hashCode() value).


> or is this reserved for some ebean specific issue?

Ebean does not rely on hashCode/equals ... so yes you can override it if you desire.


is there any problem for me in overriding equals and hashCode (and not using ebean's generated one) in my own class?

No except you should note that it is difficult to implement given the nature of entity beans (they mutate and generally don't have an id value until after they have been saved etc).  That is, we should not really have an implementation where the hashCode value changes (as then an entry goes "missing" as the hashCode now means the a different bucket is looked into).

In general, the issues (and lack of awareness) around this means that:
A) I encourage the use of List over Set in entity models 
B) I usually use findMap() as a better alternative to using equals



Cheers, Rob.


--

---
You received this message because you are subscribed to the Google Groups "Ebean ORM" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ebean+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Daryl Stultz

unread,
Aug 9, 2017, 9:05:22 AM8/9/17
to eb...@googlegroups.com
On Wed, Aug 9, 2017 at 6:06 AM, Rob Bygrave <robin....@gmail.com> wrote:

In general, the issues (and lack of awareness) around this means that:
A) I encourage the use of List over Set in entity models 

Hi Rob, can you elaborate on this point? We use, possibly exclusively, Set. Using a List can result in a duplicate key violation, as our collections almost never allow duplicates.

Thanks.

/Daryl

Rob Bygrave

unread,
Aug 9, 2017, 4:59:17 PM8/9/17
to ebean@googlegroups
Set internally uses hashCode() / equals.  If the value of hashCode() changes then internally a bean that was in one particular 'bucket' is now expected to be in a different 'bucket'.  More specifically, HashSet / LinkedHashSet internally uses HashMap / LinkedHashMap which internally uses hashCode()/equals().

When the hashCode() value changes we can get the behavior:
- we can put the bean into the Set twice (duplicates)
- contains() returns false when the bean is in the set

Observing this depending on:
- the number of buckets (size of the set or map)
- the actual hashCode() values and internal hash function used (which determines the bucket a hashCode value translates to).




> Using a List can result in a duplicate key violation

In short mutating entity beans are not a good candidate for a map key.

When I am writing some de-duplication logic I'll explicitly use a Map with a key that is known to be non-null and effectively immutable rather than rely on the implicit mechanism of Set.

That is, Set most commonly is internally implemented as a Map where the keys are the entries. Hence the implicit reliance on the hashCode/equals of those entries ... and in our case those entries are entity beans that can mutate (including the id value) and are not really good candidates to be used as keys of a map.

Not sure if I have explained that well yet.



Cheers,Rob.


Rob Bygrave

unread,
Aug 15, 2017, 6:25:11 AM8/15/17
to ebean@googlegroups
Some references into JDK source examples case it helps the explanation for some readers of this thread.

----

Sets are generally implemented internally using maps. For example, HashSet is implemented using HashMap 

http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/HashSet.java#102



The result of hashCode() determines the 'bucket' / location to search.  In HashMap the internal hash() and indexFor() methods translate a hashCode() into an Entry location which is then searched linearly (ala a linked list searched via entry.next until equals() match is found).  For example:

int hash = hash(key.hashCode());
for (Entry<K,V> e = table[indexFor(hashtable.length)];



Rob Bygrave

unread,
Aug 15, 2017, 6:34:42 AM8/15/17
to ebean@googlegroups
Note that generally Ebean uses LinkedHashSet & LinkedHashMap to support ordering etc.  So interesting Java 8 source for that is:
---

LinkedHashSet uses LinkedHashMap internally via:





LinkedHashMap get(Object key) is a little different implementation wise:


 
Reply all
Reply to author
Forward
0 new messages