Flush and Commit

Flush Is Not Commit

FlushCommit
WhatSends pending SQL (INSERT/UPDATE/DELETE) to the databaseMakes the transaction's changes permanent
Undoable?Yes, a rollback still undoes flushed SQLNo
Visible to other transactions?No (with normal isolation)Yes
Triggered byem.flush(), before a JPQL query that might be affected, before commitcommit() / end of @Transactional method

When Hibernate Flushes (FlushModeType.AUTO)

@Transactional
public void demo() {
    Product p = em.find(Product.class, 1L);
    p.setPrice(new BigDecimal("1299.00"));        // nothing sent yet

    // a query on products: Hibernate flushes first so the query sees the new price
    List<Product> cheap = em.createQuery(
            "select p from Product p where p.price < :max", Product.class)
        .setParameter("max", new BigDecimal("1300.00"))
        .getResultList();

    System.out.println(cheap.size());
}                                                 // commit: flush (nothing left) + COMMIT

Order of SQL

# log

Example output

Hibernate: select p1_0.id,...,p1_0.stock from products p1_0 where p1_0.id=?
Hibernate: update products set category=?,created_at=?,description=?,name=?,price=?,sku=?,status=?,stock=? where id=?
Hibernate: select p1_0.id,...,p1_0.stock from products p1_0 where p1_0.price<?

Order of Operations at Flush

  1. INSERTs (in the order persist was called)
  2. UPDATEs (dirty entities)
  3. Collection changes
  4. DELETEs

Note: Because of this order, deleting a row and inserting a new one with the same unique value in one transaction can fail with a constraint violation. Call em.flush() after the remove to force the DELETE first.

Exercise

Exercise: In this method, how many SQL statements run, and in what order? Product a = em.find(Product.class, 1L); Product b = em.find(Product.class, 1L); b.setStock(10); a.setStock(10); (row 1 had stock 120; transaction then commits).

Show answer
1. select ... from products where id=?    (first find)
   second find: no SQL - same object from the persistence context (a == b)
2. update products set ... where id=?    (one UPDATE at commit;
                                          a and b are the same object,
                                          so it is dirty only once)