Careeroza
Real World Example
Diagnosing a Slow Order Update
A payments team (think Paytm or Razorpay dashboards) saw "mark order shipped" take 2 seconds. The method loaded the order through a repository method that also pulled 5,000 audit rows into the session, so every AUTO flush dirty-checked thousands of entities. Understanding the internals pointed straight to the fix:
// BEFORE: big persistence context + a query inside a loop triggers repeated AUTO flushes
@Transactional
public void markShipped(List<Long> orderIds) {
for (Long id : orderIds) {
Order o = orders.findWithAuditTrail(id); // loads Order + 5,000 AuditEntry entities
o.setStatus(OrderStatus.SHIPPED);
long open = orders.countByStatus(OrderStatus.PACKED); // query -> AUTO flush -> dirty check ALL
metrics.gauge("orders.packed", open);
}
}
// AFTER
@Transactional
public void markShippedFast(List<Long> orderIds) {
for (List<Long> chunk : Lists.partition(orderIds, 100)) {
orders.findAllById(chunk) // only the orders, no audit trail
.forEach(o -> o.setStatus(OrderStatus.SHIPPED));
em.flush(); // one batched flush per chunk
em.clear(); // keep the context small
}
metrics.gauge("orders.packed", orders.countByStatus(OrderStatus.PACKED)); // once, at the end
}What Changed
| Internal | Before | After |
|---|---|---|
| Managed entities per flush | ~5,000+ | ≤ 100 |
| Flushes | one per order (AUTO before each count) | one per 100 orders |
| UPDATE statements | not batched | JDBC batches of 50 |
| Time for 500 orders | ~2 s each call | ~180 ms total |