Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>There are some issues worth noticing if you're dealing with classes that are persisted using an Object-Relationship Mapper (ORM) like Hibernate, if you didn't think this was unreasonably complicated already!</p> <p><strong>Lazy loaded objects are subclasses</strong></p> <p>If your objects are persisted using an ORM, in many cases you will be dealing with dynamic proxies to avoid loading object too early from the data store. These proxies are implemented as subclasses of your own class. This means that<code>this.getClass() == o.getClass()</code> will return <code>false</code>. For example:</p> <pre><code>Person saved = new Person("John Doe"); Long key = dao.save(saved); dao.flush(); Person retrieved = dao.retrieve(key); saved.getClass().equals(retrieved.getClass()); // Will return false if Person is loaded lazy </code></pre> <p><em>If you're dealing with an ORM, using <code>o instanceof Person</code> is the only thing that will behave correctly.</em></p> <p><strong>Lazy loaded objects have null-fields</strong></p> <p>ORMs usually use the getters to force loading of lazy loaded objects. This means that <code>person.name</code> will be <code>null</code> if <code>person</code> is lazy loaded, even if <code>person.getName()</code> forces loading and returns "John Doe". In my experience, this crops up more often in <code>hashCode()</code> and <code>equals()</code>.</p> <p><em>If you're dealing with an ORM, make sure to always use getters, and never field references in <code>hashCode()</code> and <code>equals()</code>.</em></p> <p><strong>Saving an object will change its state</strong></p> <p>Persistent objects often use a <code>id</code> field to hold the key of the object. This field will be automatically updated when an object is first saved. Don't use an id field in <code>hashCode()</code>. But you can use it in <code>equals()</code>.</p> <p>A pattern I often use is</p> <pre><code>if (this.getId() == null) { return this == other; } else { return this.getId().equals(other.getId()); } </code></pre> <p>But: you cannot include <code>getId()</code> in <code>hashCode()</code>. If you do, when an object is persisted, its <code>hashCode</code> changes. If the object is in a <code>HashSet</code>, you'll "never" find it again.</p> <p>In my <code>Person</code> example, I probably would use <code>getName()</code> for <code>hashCode</code> and <code>getId()</code> plus <code>getName()</code> (just for paranoia) for <code>equals()</code>. It's okay if there are some risk of "collisions" for <code>hashCode()</code>, but never okay for <code>equals()</code>.</p> <p><em><code>hashCode()</code> should use the non-changing subset of properties from <code>equals()</code></em></p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload