liveBook · Manning

Identity

As explained in Java Persistence with Spring Data and Hibernate epub

Object identity is the property by which two object references are the same when they refer to the same object instance.

Object identity answers a narrow question: do two Java references point to the same instance? The `==` operator tests this. Object equality is different: `equals()` can treat distinct instances as equivalent, although its inherited implementation uses identity. Database identity is different again: two persistent objects represent the same database row when they have the same table and primary key. section 5.2.1

A JPA persistence context makes those distinctions manageable during a unit of work. Within one context, only one managed instance represents a particular row. Repeatedly finding an entity by the same identifier therefore returns references to that instance: `a == b` is true. The context also makes changes to that instance visible to other code working within the same unit of work. section 10.1.2 section 10.3.1

The same row across two contexts

Suppose `a` and `b` are obtained by finding an entity with the same identifier in one persistence context. After that context closes, another context finds the row as `c`. Then `a == b`, but `a != c`; all three references have the same database identifier. With the inherited `equals()` implementation, `a.equals(c)` is false. Adding `a`, `b`, and `c` to a `HashSet` therefore leaves two elements, not one. section 10.3.1

Listing 10.2 Guaranteed scope of object identity in Java Persistence
Path: managing-data/src/test/java/com/manning/javapersistence/ch10
 /SimpleTransitionsTest.java – scopeOfIdentity()
 
em = emf.createEntityManager();               #1
em.getTransaction().begin();                  #2
Item a = em.find(Item.class, ITEM_ID);        #3
Item b = em.find(Item.class, ITEM_ID);        #3
assertTrue(a == b);                           #4
assertTrue(a.equals(b));                      #5
assertEquals(a.getId(), b.getId());           #6
em.getTransaction().commit();                 #7
em.close();                                   #8
em = emf.createEntityManager();
em.getTransaction().begin();
Item c = em.find(Item.class, ITEM_ID);
assertTrue(a != c);                           #9
assertFalse(a.equals(c));                     #10
assertEquals(a.getId(), c.getId());           #11
em.getTransaction().commit();
em.close();
#1 Create a persistence context.
#2 Begin the transaction.
#3 Load some entity instances.
#4 References <kbd>a</kbd> and <kbd>b</kbd> are obtained from the same persistence context; they have the same Java identity.
#5 <kbd>equals()</kbd> relies on Java identity comparison.
#6 <kbd>a</kbd> and <kbd>b</kbd> reference the same <kbd>Item</kbd> instance, in persistent state, managed by the persistence context for that unit of work.
#7 Commit the transaction.
#8 Close the persistence context. References <kbd>a</kbd> and <kbd>b</kbd> are in a detached state when the first persistence context is closed.
#9 <kbd>a</kbd> and <kbd>c</kbd>, loaded in different persistence contexts, aren’t identical.
#10 <kbd>a.equals(c)</kbd> is also <kbd>false</kbd>, because the <kbd>equals()</kbd> method has not been overridden, which means it uses instance equality (<kbd>==</kbd>).
#11 A test for database identity still returns <kbd>true</kbd>.

The Java listing compares `==`, `equals()`, and identifiers before and after opening a second persistence context. section 10.3.1

Use reference identity when reasoning about managed entities inside one persistence context. Do not assume that matching database identifiers imply the same Java instance after detachment or a lookup in another context; collection behavior also depends on the entity’s `equals()` implementation. section 10.1.2 section 10.3.1

How Java Persistence with Spring Data and Hibernate epub covers it

How deep it goes
Works through Java comparisons and persistence-context lifecycle, but does not provide an implementation of custom equality.
Examples
Compares repeated entity lookups across two persistence contexts and tests the resulting references in a HashSet.
What it assumes
Assumes familiarity with Java references and `equals()` while defining database identity before applying it to JPA.
What you can do after
Diagnose/debug with it when reference comparisons or Set sizes differ after entities are loaded in separate persistence contexts.
How it connects
Connects object equality and database identity to primary keys, persistence contexts, and detached entities.

Also explained in

Compare how 8 books explain identity →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Java Persistence with Spring Data and Hibernate epub. The section links point to the parts of the book it draws on.