Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>If you want to use <code>equals()/hashCode()</code> for your Sets, in the sense that the <em>same entity</em> can only be in there once, then there is only one option: Option 2. That's because a <strong>primary key</strong> for an entity by definition never changes (if somebody indeed updates it, it's not the same entity anymore)</p> <p>You should take that literally: Since your <code>equals()/hashCode()</code> are based on the primary key, you must not use these methods, until the primary key is set. So you shouldn't put entities in the set, until they're assigned a primary key. (Yes, UUIDs and similar concepts may help to assign primary keys early.)</p> <p>Now, it's theoretically also possible to achieve that with Option 3, even though so-called "business-keys" have the nasty drawback that they can change: "All you'll have to do is delete the already inserted entities from the set(s), and re-insert them." That is true - but it also means, that in a distributed system, you'll have to make sure, that this is done absolutely everywhere the data has been inserted to (and you'll have to make sure, that the update is performed, before other things occur). You'll need a sophisticated update mechanism, especially if some remote systems aren't currently reachable...</p> <p>Option 1 can only be used, if all the objects in your sets are from the same Hibernate session. The Hibernate documentation makes this very clear in chapter <a href="http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/transactions.html#transactions-basics-identity" rel="noreferrer">13.1.3. Considering object identity</a>:</p> <blockquote> <p>Within a Session the application can safely use == to compare objects.</p> <p>However, an application that uses == outside of a Session might produce unexpected results. This might occur even in some unexpected places. For example, if you put two detached instances into the same Set, both might have the same database identity (i.e., they represent the same row). JVM identity, however, is by definition not guaranteed for instances in a detached state. The developer has to override the equals() and hashCode() methods in persistent classes and implement their own notion of object equality.</p> </blockquote> <p>It continues to argue in favor of Option 3:</p> <blockquote> <p>There is one caveat: never use the database identifier to implement equality. Use a business key that is a combination of unique, usually immutable, attributes. The database identifier will change if a transient object is made persistent. If the transient instance (usually together with detached instances) is held in a Set, changing the hashcode breaks the contract of the Set.</p> </blockquote> <p>This is true, <strong>if</strong> you </p> <ul> <li>cannot assign the id early (e.g. by using UUIDs)</li> <li>and yet you absolutely want to put your objects in sets while they're in transient state.</li> </ul> <p>Otherwise, you're free to choose Option 2.</p> <p>Then it mentions the need for a relative stability:</p> <blockquote> <p>Attributes for business keys do not have to be as stable as database primary keys; you only have to guarantee stability as long as the objects are in the same Set.</p> </blockquote> <p>This is correct. The practical problem I see with this is: If you can't guarantee absolute stability, how will you be able to guarantee stability "as long as the objects are in the same Set". I can imagine some special cases (like using sets only for a conversation and then throwing it away), but I would question the general practicability of this.</p> <hr> <p>Short version:</p> <ul> <li>Option 1 can only be used with objects within a single session.</li> <li>If you can, use Option 2. (Assign PK as early as possible, because you can't use the objects in sets until the PK is assigned.)</li> <li>If you can guarantee relative stability, you can use Option 3. But be careful with this.</li> </ul>
 

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