पाठ 5 / 25

Entity States and Dirty Checking

Describe transient, managed, detached and removed states and automatic dirty checking.

Four states of an entity

Every entity instance is in one of four states relative to a persistence context. Transient (new): created with new, not yet associated with a persistence context or a database row. Managed (persistent): associated with the current persistence context; Hibernate tracks it. Detached: was managed, but the persistence context has closed or the entity was detached, so changes are no longer tracked. Removed: scheduled for deletion at the next flush. The most powerful consequence is automatic dirty checking: when a transaction flushes, Hibernate compares each managed entity's current state with the snapshot taken when it was loaded and issues UPDATE statements for changed entities, without any explicit save call. The persistence context also acts as a first-level cache and identity map: within one context, loading the same ID twice returns the same Java object, guaranteeing a single in-memory representation per row. Detached entities, typically objects returned from a service after the transaction ended, must be reattached with merge to persist further changes.

Dirty checking in action

No save call: the change is detected and written at commit.

@Transactional
public void applyDiscount(Long productId, BigDecimal percent) {
    Product p = em.find(Product.class, productId);       // managed; snapshot taken
    BigDecimal factor = BigDecimal.ONE.subtract(percent.movePointLeft(2));
    p.changePrice(p.getPrice().multiply(factor));         // just change the object
}   // commit -> flush -> UPDATE products SET price = ? WHERE id = ?

@Transactional
public void identity(Long id) {
    Product a = em.find(Product.class, id);               // SELECT
    Product b = em.find(Product.class, id);               // no SELECT: first-level cache
    assert a == b;                                         // same Java object
}

public Product loadOutsideTransaction(Long id) {
    return productService.findById(id);                   // returned entity is DETACHED here
    // changing it now will not be saved unless merged in a new transaction
}

A tracked shopping cart

A managed entity is an item in a shop's tracked cart: the shop notices whenever you change the quantity and bills you at checkout. A detached entity is a photocopy of the receipt you took home; scribbling on it changes nothing in the shop's system.

त्वरित जाँच: Inside a transaction, you load an entity and change one field without calling save. What happens at commit?

  • Nothing; changes are lost
  • Hibernate detects the change by dirty checking and issues an UPDATE
  • An exception is thrown
  • The entity is deleted
Answer

Hibernate detects the change by dirty checking and issues an UPDATE — Managed entities are compared with their snapshot at flush, and changes are written automatically.