{"id":115,"date":"2009-04-12T02:18:57","date_gmt":"2009-04-12T09:18:57","guid":{"rendered":"http:\/\/www.zulutown.com\/blog\/?p=115"},"modified":"2009-04-12T02:18:57","modified_gmt":"2009-04-12T09:18:57","slug":"hibernate-hashcode-equals-and-eclipse","status":"publish","type":"post","link":"http:\/\/www.zulutown.com\/blog\/2009\/04\/12\/hibernate-hashcode-equals-and-eclipse\/","title":{"rendered":"Hibernate, hashCode, equals and Eclipse"},"content":{"rendered":"<p>Java programmers use often Eclipse to write their code, and it&#8217;s common to rely on the Eclipse features to quickly generate the <em>hashCode()<\/em> and <em>equals(Object obj)<\/em> methods of the beans.<\/p>\n<p>Working on a Hibernate based application, I often noticed unexpected issues, and after some <em>in depth<\/em> debugging I&#8217;ve found that probably some of these problems were caused by the Eclipse automatic generation of <code>equals<\/code> method.<\/p>\n<p>In my opinion, this is mostly caused by the fact that Hibernate generates on top of our <em>entity bean<\/em> classes other <em>proxy classes<\/em> that overrides the getters, and other methods in order to provide the <em>lazy loading<\/em> of data.<\/p>\n<p>I.e.: When Hibernate loads from the DB a <code>Movie<\/code> bean, it will have, for example, an associated list of <code>MovieActor<\/code> objects. Obviously Hibernate will not fetch all the data related to every single actor, but anyway it will generate the <em>stub<\/em> for the MovieActor objects.<\/p>\n<p>The programmer would be tempted to use code like this:<\/p>\n<pre>Movie aMovie = getEntityManager.find(...);\r\nMovieActor aMovieActor = getEntityManager.find(...);\r\nif (aMovie.getActors().contains(aMovieActor)) {\r\n\tSystem.out.println(aMovieActor.getActor().getName() + \" acted in the movie \" + aMovie.getTitle());\r\n}<\/pre>\n<p>I noticed that <code>contains<\/code> method often returns <code>false<\/code> even if that actor really acted in that movie!<br \/>\nAfter some long debugging sessions, my final idea is that the problem is how Eclipse automatically generated the <code>equals<\/code> method of <code>MovieActor<\/code> class:<\/p>\n<pre>\t@Override\r\n\tpublic boolean equals(Object obj) {\r\n\t\tif (this == obj)\r\n\t\t\treturn true;\r\n\t\tif (obj == null)\r\n\t\t\treturn false;\r\n\t\tif (!(obj instanceof MovieActor))\r\n\t\t\treturn false;\r\n\t\tMovieActor other = (MovieActor) obj;\r\n\t\tif (id == null) {\r\n\t\t\tif (other.id != null)\r\n\t\t\t\treturn false;\r\n\t\t} else if (!id.equals(other.id))\r\n\t\t\treturn false;\r\n\t\treturn true;\r\n\t}<\/pre>\n<p>In this code <code>id<\/code> is an <code>@EmbeddedId<\/code> composed by the Actor and the Movie associations. What I believe that causes problems is: <strong><code>other.id<\/code><\/strong>!<\/p>\n<p>This is because probably the Id of the <code>other<\/code> object hasn&#8217;t been loaded yet, and its fetching will happen on the calling of <code>getId()<\/code> of the proxy class built on MovieActor.<\/p>\n<p>So, I changed the <code>equals<\/code> method this way:<\/p>\n<pre>\t@Override\r\n\tpublic boolean equals(Object obj) {\r\n\t\tif (this == obj)\r\n\t\t\treturn true;\r\n\t\tif (obj == null)\r\n\t\t\treturn false;\r\n\t\tif (!(obj instanceof MovieActor))\r\n\t\t\treturn false;\r\n\t\tMovieActor other = (MovieActor) obj;\r\n\t\tif (id == null) {\r\n\t\t\tif (other.getId() != null)\r\n\t\t\t\treturn false;\r\n\t\t} else if (!id.equals(other.getId()))\r\n\t\t\treturn false;\r\n\t\treturn true;\r\n\t}<\/pre>\n<p>And after this little change, <code>contains<\/code> began to work correctly!<\/p>\n<p>Another <strong>very important<\/strong> thing is to check <em>use &#8216;instanceof&#8217; to compare types<\/em> otherwise some ugly code would be generated.<br \/>\nSome checks like <code>if (getClass() != obj.getClass())<\/code> would miserably fail when hibernate proxy classes are used.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Java programmers use often Eclipse to write their code, and it&#8217;s common to rely on the Eclipse features to quickly generate the hashCode() and equals(Object obj) methods of the beans. Working on a Hibernate based application, I often noticed unexpected &hellip; <a href=\"http:\/\/www.zulutown.com\/blog\/2009\/04\/12\/hibernate-hashcode-equals-and-eclipse\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3,118],"tags":[122,121,130,128,164,131,120,127,125,119,174,132,17,126,129,123,124],"_links":{"self":[{"href":"http:\/\/www.zulutown.com\/blog\/wp-json\/wp\/v2\/posts\/115"}],"collection":[{"href":"http:\/\/www.zulutown.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.zulutown.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.zulutown.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.zulutown.com\/blog\/wp-json\/wp\/v2\/comments?post=115"}],"version-history":[{"count":2,"href":"http:\/\/www.zulutown.com\/blog\/wp-json\/wp\/v2\/posts\/115\/revisions"}],"predecessor-version":[{"id":117,"href":"http:\/\/www.zulutown.com\/blog\/wp-json\/wp\/v2\/posts\/115\/revisions\/117"}],"wp:attachment":[{"href":"http:\/\/www.zulutown.com\/blog\/wp-json\/wp\/v2\/media?parent=115"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.zulutown.com\/blog\/wp-json\/wp\/v2\/categories?post=115"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.zulutown.com\/blog\/wp-json\/wp\/v2\/tags?post=115"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}