Skip to content

Instantly share code, notes, and snippets.

@struberg
Created October 20, 2016 14:56
Show Gist options
  • Save struberg/d38e14da51439adcd4cf4084bc67b3f3 to your computer and use it in GitHub Desktop.
Save struberg/d38e14da51439adcd4cf4084bc67b3f3 to your computer and use it in GitHub Desktop.
Hi Vlad!
The 140 char limit on Twitter isn't really helpful to make to the point statements. At least it seems you totally missed my 2nd tweet. But since the context between 2 tweets often gets lost I thus added a longer explanation as blog post https://struberg.wordpress.com/2016/10/15/tostring-equals-and-hashcode-in-jpa-entities/
I you have read my blog post carefully then you might notice that your first sentence is quite off from what I expressed. You missed that I am focusing on PORTABLE behaviour (which you as a Hibernate maintainer obviously don't care about) and on DEFAULT IDE generated behaviour (which will hit Hibernate as well).
To get things straight: most IDEs do a bad job in GENERATING a good toString(), equals() and hashCode() method. They usually just pick all the attributes. Those generated methods usually also include attributes which are @ElementCollections or @OneToMany fields. I guess you agree with me that touching those fields in e.g. toString() will also trigger lazyLoading even in Hibernate (if not set to fetch EAGER anyway)? Right?
2nd point: I explicitly showed a toString() one _should_ use for Hibernate! But please people, only print the class name and the primary key. What's wrong with that? Please explain, I don't get what you think is wrong with that.
I also noted that you don't need to implement any toString() *for OpenJPA* because here the SimpleClassName + PK is already the default which gets printed out.
Same applies to equals() and hashCode(). The generated ones (with all the fields) are almost always BS. Don't you agree?
Regarding equals() and hashCode(). I already pointed to your solution in my blog post. It is very close to a working solution but still does not solve all edges.
Oh and to be honest, I've _rarely_ seen an entity with at least your version of the equals() and hashCode()...
Example: https://github.com/vladmihalcea/high-performance-java-persistence/blob/ac1f8af5de04dcbc7cae225f05573e5ba278f207/core/src/test/java/com/vladmihalcea/book/hpjp/hibernate/association/BidirectionalManyAsOneToManyWithoutEmbeddedIdTest.java#L148
What if someone changes the title?
<pre>
Post p;..
p.setTitle("A");
Set<Post> posts = new HashSet<>();
posts.add(p);
p.setTitle("B");
posts.add(p);
p.size() // -> whoops, will be 2 but should be 1
</pre>
Just google for >java "@Entity" "public boolean equals" site:github.com< and tell me how many correct impls you did find...
My fazit was that it is often better to just omit any own equals() and hashCode() and fall back to Object.equals because it works more often than the other things I've seen in most existing code.
Ad the parallel access to managed entities: It's ok to mention specific Hibernate hacks to solve this. But on top of my blog post I explicitly noted that I'm talking about *portable* solutions. Of course I perfectly understand that YOU don't care much about portability. But some users do.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment